1
HBITMAP g_startcapBitmap = NULL, g_stopcapBitmap= NULL;
int nScreenWidth, ntWinx;


enum {ID_BUTTON_START=1,ID_BUTTON_STOP};  //constants for buttons
/*
 * Message loop handler for the notification window.
 */
LRESULT CALLBACK myWndProcedure(HWND hWnd, UINT Msg,
               WPARAM wParam, LPARAM lParam)
{
    PAINTSTRUCT ps;
    HDC hdc; 

    std::string json;
    switch(Msg)
    {
        case WM_CREATE:
            buttonStart = CreateWindowEx(WS_EX_TOPMOST,L"Button",L"START CAPTURE",BS_PUSHBUTTON | BS_BITMAP | WS_CHILD | WS_VISIBLE ,10,1,180,30,hWnd,(HMENU)ID_BUTTON_START,NULL,0);           
            g_startcapBitmap = (HBITMAP)::LoadImage(GetModuleHandle(NULL),
                                        //L"StartCaptureWhite.bmp",
                                      MAKEINTRESOURCE(IDB_BITMAP1),
                                       IMAGE_BITMAP,
                                       180,
                                       30,
                                       LR_DEFAULTCOLOR);
            if(g_startcapBitmap == NULL)
                LOG_INFO("loading startbitmap failed...!");
            if( ::SendMessage(buttonStart, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)g_startcapBitmap) == 0)
                LOG_INFO("sendimage for btnstart failed...!");


        break;


        case WM_PAINT:
            hdc = BeginPaint(hWnd, &ps);

            EndPaint(hWnd, &ps);
            break;



        case WM_COMMAND: //Command from Child windows and menus are under this message
             switch(wParam) //the ID is wParam
             {                  
                case ID_BUTTON_START: //check for our button ID  btnStart
                    {

                        json.clear();
                        ScreenEvent screenEvent("CONTROL","START");
                        json = screenEvent.getJSONtextAsString();
                        ScreenIndexHandler* screenIndexHandler = ScreenIndexHandler::getInstance();
                        if(screenIndexHandler == NULL )
                        {
                            LOG_INFO("Bad Screenhandler object");
                            exit(0);
                        }
                        screenIndexHandler->addToEventQueue(json);

                        ::SetWindowPos(hWnd,NULL,ntWinx,0,200,5,SWP_DRAWFRAME);

                        buttonStop = CreateWindowEx(WS_EX_TOPMOST, L"Button",L"STOP CAPTURE",BS_PUSHBUTTON |BS_BITMAP |  WS_CHILD | WS_VISIBLE, 0,0,0,0,hWnd,(HMENU)ID_BUTTON_STOP,NULL,0); 
                        g_stopcapBitmap = (HBITMAP)LoadImage(GetModuleHandle(NULL),
                                       MAKEINTRESOURCE(IDB_BITMAP2),
                                       //L"..//..//images//StopCaptureWhite.bmp",
                                       IMAGE_BITMAP,
                                       180,
                                       30,
                                       LR_DEFAULTCOLOR);

                        ::SendMessage(buttonStop, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)g_stopcapBitmap);
                        ::ShowWindow(buttonStart,SW_HIDE);
                        ::UpdateWindow(hWnd);

                        NotificationWindow::isStartCap = true;
                        LOG_INFO("Added to EventQueue!");
                        break;
                    }

这是通知窗口的代码,它会在我的插件的某些方法被调用时显示。

上面的代码实际上是插件 dll 使用的库(.lib)文件的一部分。情况是当我将资源文件与独立 exe 的测试程序链接时,会显示开始和停止按钮上的图像。

但是,当我创建 dll(它是另一个使用我的 .lib 的 .sln 的一部分)时,它会毫无问题地创建。.dll 文件包含我使用 .rc 文件嵌入的 2 个图像(使用一些 dll 提取器工具验证)。

现在,当我通过浏览器调用dll并调用其负责显示通知窗口的函数(带有开始按钮)时,窗口会显示但在开始按钮上没有图像

日志显示 LoadImage() 函数失败,因此 SendMessage()。

如何用dll解决这个问题?

有没有其他方法可以为按钮/打包图像

请帮忙。

谢谢!

4

1 回答 1

5

关键可能在这段代码中:

LoadImage(GetModuleHandle(NULL), ...)

始终GetModuleHandle(NULL)返回应用程序主 EXE 的句柄,但您的图像位于 DLL 的资源部分。

如果希望它从 DLL 运行,则必须传递函数HINSTANCE接收到的任何资源加载DllMain()函数。或者,您可以使用GetModuleHandle("name.dll"),但在代码中硬连线 DLL 的名称并不是一个好主意。

在 EXE 和 DLL 中获得相同代码工作的任何简单方法是定义一个全局变量(不要导出它!):

HINSTANCE g_thisModule = NULL;

DllMain()函数中,分配给它:

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    g_thisModule = hinstDll;
}

如果它不是 DLL,而是 EXE,则可以g_thisModuleWinMain(). 如果它是一个控制台程序,只需在main():中添加这一行g_thisModule = GetModuleHandle(NULL);

然后使用此变量加载任何本地资源:

LoadImage(g_thisModule, ...)
于 2013-08-02T15:10:01.473 回答