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 であるテスト プログラムにリンクすると、開始ボタンと停止ボタンに IMAGE が表示されます。

しかし、私の.libを使用する別の.slnの一部であるdllを作成すると、問題なく作成されます.dll ファイルには、.rc ファイルを使用して埋め込んでいる 2 つの画像が含まれています (いくつかの dll-extractor ツールを使用して検証されています)。

ブラウザからdllを呼び出し、通知ウィンドウを表示する機能を呼び出すと(開始ボタン付き)、ウィンドウは表示されますが、開始ボタンに画像はありません。

ログには、LoadImage() 関数が失敗したため、SendMessage() が失敗したことが示されています。

dll でこの問題を解決するにはどうすればよいですか?

ボタンの画像をパッケージ化する他の方法はありますか/

助けてください。

ありがとう!

4

1 に答える 1

5

鍵はおそらく次のコードにあります。

LoadImage(GetModuleHandle(NULL), ...)

常にアプリケーションのメイン EXE のハンドルGetModuleHandle(NULL)を返しますが、画像は 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, ...)
于 2013-08-02T15:10:01.473 に答える