使用dll运行时,按钮上没有显示位图

时间:2013-08-02 15:06:01

标签: c++ winapi visual-c++ visual-studio-2005

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的测试程序链接时,会显示启动和停止按钮上的IMAGE。

但是,当我创建dll时,它是另一个使用我的.lib的.sln的一部分,它的创建没有问题。 .dll文件包含我使用.rc文件嵌入的2个图像(使用一些dll-extractor工具验证)。

现在,当我通过浏览器调用 dll 并调用其负责显示Notification-window(带启动按钮)的功能时,窗口显示为 NO IMAGE on “开始”按钮。

日志说LoadImage()函数失败,所以SendMessage()。

如何用dll解决这个问题。?

还有其他方法来打包按钮/

的图像

请帮忙。

谢谢!

1 个答案:

答案 0 :(得分:4)

关键可能在于这段代码:

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_thisModule中的参数中获取WinMain()。如果是控制台程序,只需在main()g_thisModule = GetModuleHandle(NULL);中添加此行。

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

LoadImage(g_thisModule, ...)