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解决这个问题。?
还有其他方法来打包按钮/
的图像请帮忙。
谢谢!
答案 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, ...)