简体   繁体   中英

win32 - Dialog inside .dll

I want to a create.dll, which shows some dialog.

In my.dll I have this code:

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

ShowError calls Message box and GetLastErrorAsString() just calls standard GetLastError and converts to string.
I have this output:

The specified resource type cannot be found in the image file.

Then I have a standard win32 Window application and there I call method, which calls the mentioned code.

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

What I am doing wrong? Do I need to link resource files to.dll?

I am using Visual studio 2010 and dialog is specified in my resource file (.rc).

The error code and message are accurate: The resource cannot be found where you instructed the system to go looking for it: The executable image that was used to start the process, not your DLL. The behavior is documented (see CreateDialogParam ):

hInstance [in, optional]

Type: HINSTANCE

A handle to the module which contains the dialog box template. If this parameter is NULL, then the current executable is used.

Since you have the dialog template stored inside your DLL, you will have to pass the HINSTANCE that identifies your DLL. There are a number of ways to get the correct value, but passing NULL or GetModuleHandle(NULL) won't work. Both of these return the module handle to the executable image that started the process (not your DLL).

The easy solution: Pick the hInstance passed into your DllMain and store it in a global variable for later use.

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;
}

The robust solution: This solution can be used anywhere, in a DLL, an EXE, or a static LIB. Only down-side: It relies on undocumented features of Microsoft's linker. Don't worry, though, it won't fail silently.

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

HINST_THISMODULE will always hold the correct value, regardless of where it is used. 1)

The same can be achieved using official interfaces ( GetModuleHandleEx ) as well. The following solution can be used from an EXE, a DLL, or a static LIB as well, so long as you make sure to compile and link the function into the respective module:

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

    return hModule;
}

This returns an HMODULE , not an HINSTANCE . This is not an issue, though, since they are the same thing 2) .


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

2)What is the difference between HINSTANCE and HMODULE?

You specified NULL as the first parameter to CreateDialogParam . If you want to load the dialog resource file from the Win32 Window Application, you should use this instead:

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

However, if you want to load it from the DLL itself, you should replace the first parameter with the HINSTANCE parameter from the DllMain entry point function of the DLL.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM