2015-08-26 81 views
0

我想創建一個.dll文件,它會顯示一些對話框。win32 - 對話框裏面的.dll

在我的.dll我有這樣的代碼:

HWND hDlg = CreateDialogParam(NULL, MAKEINTRESOURCE(IDD_RANKING_DIALOG), NULL, msgProc, NULL); 
if (!hDlg) { 
    ShowError(GetLastErrorAsString().c_str()); 
    return false; 
} 

ShowError調用消息框,GetLastErrorAsString()只是調用標準GetLastError,並將其轉換爲字符串。
我有這樣的輸出:

在圖像文件中找不到指定的資源類型。

然後我有一個標準的win32窗口應用程序,在那裏我調用方法,它調用上述代碼。

DialogTest test; 
test.showDialog(); // calls functionality from .dll 

我在做什麼錯了?我需要將資源文件鏈接到.dll嗎?

我正在使用Visual Studio 2010和dialog在我的資源文件(.rc)中指定。

+4

您在'hInstance'參數傳遞'NULL'到'CreateDialogParam()'。這意味着對話資源將被加載到已加載DLL的可執行文件中,而不是在DLL本身中查找。您應該傳遞與您的DLL相關的'HINSTANCE'。 –

+0

我曾嘗試使用GetModuleHandle(0)而不是NULL,但它並沒有幫助。那麼我怎麼才能得到DLL的HINSTANCE。 –

+1

它作爲第一個參數傳遞給你的'DllMain()'。 –

回答

2

您指定了NULL作爲CreateDialogParam的第一個參數。不過,如果你想從DLL本身加載

HWND hDlg = CreateDialogParam(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_RANKING_DIALOG), NULL, msgProc, NULL); 

,你應該用HINSTANCE替換第一個參數:如果要加載從Win32窗口應用程序的對話框資源文件,你應該使用這個參數來自DLL的DllMain入口點函數。

+1

不,'GetModuleHandle(NULL)'返回與當前可執行文件相關的模塊,而不是DLL。 –

+0

@FrédéricHamidi感謝您指出這一點,我相信我已更正了答案 –

+1

是的,但不需要調用GetModuleHandle()。如果要從當前可執行文件的模塊加載資源,只需將'NULL'傳遞給'CreateDialogParam()'。 –

5

錯誤代碼和消息是準確的:在指示系統去查找資源的位置找不到資源:用於啓動進程的可執行映像,而不是您的DLL。該行爲被記錄在案(見CreateDialogParam):

的hInstance [中,可選]

類型:HINSTANCE

句柄包含對話框模板模塊。如果此參數爲NULL,則使用當前的可執行文件。

由於您將對話框模板存儲在您的DLL中,因此您必須通過標識您的DLL的HINSTANCE。有很多方法可以獲得正確的值,但通過NULLGetModuleHandle(NULL)將不起作用。這兩個都將模塊句柄返回到啓動進程的可執行映像(而不是您的DLL)。

最簡單的辦法:挑的hInstance傳遞到您的DllMain並將其儲存在供以後使用全局變量。

HINSTANCE g_hInst = NULL; 

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { 
    switch (fdwReason) { 
    case DLL_PROCESS_ATTACH: 
     g_hInst = hinstDLL; 
     break; 
    default: 
     break; 
    } 
    return TRUE; 
} 

強大的解決方案:該解決方案可以在任何地方,DLL,EXE或靜態LIB中使用。唯一的缺點:它依賴於微軟鏈接器的未公開的特性。不過不要擔心,它不會默默地失敗。

EXTERN_C IMAGE_DOS_HEADER __ImageBase; 
#define HINST_THISMODULE ((HINSTANCE)&__ImageBase) 

HINST_THISMODULE將始終保持正確的值,不管它是用來在何處。 1)

同樣可以使用官方接口(GetModuleHandleEx)來實現。以下解決方案可以從EXE,DLL中,或靜態庫使用爲好,只要你確保編譯和功能鏈接到相應的模塊:

HMODULE GetCurrentModuleHandle() { 
    HMODULE hModule = NULL; 
    GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, 
         (LPCTSTR)GetCurrentModuleHandle, 
         &hModule); 

    return hModule; 
} 

這將返回HMODULE,不一個HINSTANCE。但這不是問題,因爲它們是相同的東西2)


1)Accessing the current module's HINSTANCE from a static library

2)What is the difference between HINSTANCE and HMODULE?

+0

謝謝,所有的解決方案看起來都正確,但我嘗試了這一點,它的工作原理。 –

相關問題