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 thing2).
1) From Accessing 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.
Related
I just found out that there is a minimal unmanaged API for ClickOnce applications in windows that is located in dfshim.dll. Unfortunately I could only find a very incomplete documentation on MSDN: http://msdn.microsoft.com/en-us/library/bb629396.aspx
There are only very few references in the web. All of them are using the DLL by executing command lines to call the DLL's functions using rundll32.exe.
I would like to call the DLL's functions from C++ code. I did not find a header file to include or a stub-file to link.
I could explicitely load the DLL during runtime and resolve the function symbols manually but that seems pretty uncommon for a Windows API. Also I would need to guess the signature for many of the functions.
How can I use that DLL with Visual Studio 2013? Why is there no include file? Is this actually an official/public API?
Strange, this code is hardly documented.
we ended up in this code:
bool LaunchClickOnceApplication(LPCSTR pszApplication)
{
HRESULT hr(-1);
HINSTANCE hInst = ::LoadLibrary("dfshim.dll");
if ( hInst )
{
typedef HRESULT (WINAPI *dfshim_LaunchApplicationProc) (LPCWSTR pszApplication, LPVOID pData, DWORD dwFlags);
dfshim_LaunchApplicationProc fnLaunch = (dfshim_LaunchApplicationProc)GetProcAddress(hInst, "LaunchApplication");
if ( fnLaunch )
{
hr = fnLaunch(CA2W(pszApplication), NULL, 0);
}
::FreeLibrary(hInst);
return SUCCEEDED(hr);
}
else
{
DWORD dwErr = ::GetLastError();
char szMsg[128];
_snprintf_s(szMsg, sizeof(szMsg), _TRUNCATE, "Cannot load dfshim.dll: %lu", dwErr);
AfxMessageBox(szMsg);
return false;
}
}
It is kind of unprofessional not to rely on documentation. It it more like a hack, but I don't see an alternative way. This code works for us.
I have this MFC app that loads strings from string resource using CString::LoadString function. Each of the apps dialogue box's classes and its associated resources are contained in an MFC extension DLL.
CString::LoadString loads strings from the main module's(.exe) resource's string resource successfully but fails to load string from the DLL's resource's string resource.
In each case I get my instance handle for load string from CWinApp object by calling :
CWinApp *WinApp = AfxGetApp(),
and of course the instance's handle is WinApp->m_hInstance which I use as the first argument in my call to CString::LoadString function.
What could be the cause and what could be the solution.
Are you passing the EXE's HINSTANCE to load a string from the extension library? Sounds like it.
With MFC, if you have extension libraries and you make sure your string identifiers are unique, you just need to call the CString::LoadString(UINT nID) version. Because extension libraries create CDynLinkLibrary structures that go into a global linked list, the LoadString(UINT) function will search through all your MFC libraries until it finds the HINSTANCE that contains that string, and then it will load from there. If you insist on using the LoadString() function with an HINSTANCE argument, be sure to use the HINSTANCE of the extension DLL, and not the extension of the EXE when you want to load a string or dialog from the DLL.
For small projects, like less than a dozen DLLs, you probably manage to just use unique IDs for everything. When you get into the insanely large projects like 100+ DLLs, then you have to use other techniques like specially named functions in your DLL that call AfxSetResourceHandle() or know to always use the HINSTANCE of the DLL. That's another topic.
Just to complement Joe Willcoxson's answer, be sure to check that every MFC Extension DLL you are using,needs a special initialization code, similar to the example below:
#include "stdafx.h"
#include <afxdllx.h>
static AFX_EXTENSION_MODULE MyExtDLL = { NULL, NULL };
extern "C" int APIENTRY
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
TRACE0("MyExt.DLL Initializing!\n");
// Extension DLL one-time initialization
if (!AfxInitExtensionModule(MyExtDLL, hInstance))
return 0;
new CDynLinkLibrary(MyExtDLL);
}
else if (dwReason == DLL_PROCESS_DETACH)
{
TRACE0("MyExt.DLL Terminating!\n");
// Terminate the library before destructors are called
AfxTermExtensionModule(MyExtDLL);
}
return 1; // ok
}
This code just takes care of CDynLinkLibrary creation, the key to share resources between MFC modules.
If all this are setup correctly -- and without ID clashes -- then it's simply a mather of calling:
CString str;
str.LoadString(IDS_MY_STRING_ID);
anywhere in your code, no matter where the string actually persists.
A good start point on resource IDs and numbering can be found in this link.
I've got no experience in C++ and Win API so sorry if this question is nooby. I've got DLL where I create some components, MessageBox for example. I added pragma comment to enable visual styles and it does not work (and it shouldn't as I know from this answer: windows 7 style for combobox on internet explorer toolbar, how?
Dll code(omit export and so on):
#include "stdafx.h"
#include "my-dll.h"
#include <Windows.h>
#pragma comment(linker,"\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
MYDLL_API int fnmydll(void)
{
MessageBox(NULL, L"Message", NULL, 0);
return 42;
}
Then I invoke this dll function from my app:
#include <iostream>
#include <Windows.h>
#include "my-dll.h"
int WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
fnmydll();
return 0;
}
And I've got my message box but without visual styles. As far as I understand I should activate context when my dll is invoked but MSDN has no examples how to do it. Could you please give me such example or at least explain what is going on in more details? Because I can't even understand why function BOOL GetCurrentActCtx(_Out_ HANDLE *lphActCtx); receives pointer to ACTCTX but has signature with some HANDLE type.
If you want your DLL to use visual style aware controls, i.e. comctl32 v6, even if your host application does not use it, you have to use Activation Context API. Here's an example on how to use it:
HANDLE hActCtx;
ACTCTX actCtx;
ZeroMemory(&actCtx, sizeof(actCtx));
actCtx.cbSize = sizeof(actCtx);
actCtx.hModule = hInst;
actCtx.lpResourceName = MAKEINTRESOURCE(2);
actCtx.dwFlags = ACTCTX_FLAG_HMODULE_VALID | ACTCTX_FLAG_RESOURCE_NAME_VALID;
hActCtx = CreateActCtx(&actCtx);
if (hActCtx != INVALID_HANDLE_VALUE) {
ULONG_PTR cookie;
ActivateActCtx(hActCtx, &cookie);
// Do some UI stuff here; just show a message for example
MessageBox(NULL, TEXT("Styled message box"), NULL, MB_OK);
DeactivateActCtx(0, cookie);
ReleaseActCtx(hActCtx);
}
Here hInst is the module handle of your DLL, you can save it in a global variable in DllMain or use GetModuleHandle function to get it. This sample implies your DLL stores Common Controls version 6.0 manifest in its resources with ID 2.
You can call CreateActCtx only once when your DLL initializes, and ReleaseActCtx when it's not needed any more. Call ActivateActCtx before creating any windows and call DeactivateActCtx before returning control to application.
When programming using the Windows API, I've always made the HINSTANCE from WinMain a global variable immediately. If I want to make an OK button, I'd do it like so (given global HINSTANCE g_hInstance):
return CreateWindow("BUTTON", "OK", WS_TABSTOP|WS_VISIBLE|WS_CHILD|BS_DEFPUSHBUTTON, 10, 10, 100, 30, exampleParentWindow, EXAMPLECHILDID, g_hInstance, NULL);
but lately I've been seeing the instance handle determined without having to be passed as a parameter or clogging up the global namespace, using a call to GetModuleHandle(NULL)*. So, the example above would look like this:
return CreateWindow("BUTTON", "OK", WS_TABSTOP|WS_VISIBLE|WS_CHILD|BS_DEFPUSHBUTTON, 10, 10, 100, 30, exampleParentWindow, EXAMPLECHILDID, GetModuleHandle(NULL), NULL);
*If your compiler supports it, you can write GetModuleHandle(nullptr) and the statement will have the same result.
What's the advantage (if any) of calling GetModuleHandle(NULL) over explicitly specifying the instance handle?
Fine Print: I know this has an answer, but it has not been phrased as its own question on StackOverflow.
In an EXE, it does not make any difference. hInstance from WinMain() and GetModuleHandle(NULL) both refer to the same HINSTANCE (the module of the .exe file). But it does make a difference if you are creating windows inside of a DLL instead, since you have to use the DLL's hInstance but GetModuleHandle(NULL) will still return the HINSTANCE of the EXE that loaded the DLL.
HMODULE WINAPI GetModuleHandle( _In_opt_ LPCTSTR lpModuleName );
Give the module handle of the module name passed.If you are passing NULL, the you get the module handle of the EXE which is currently running.
If you specifically name the module name, you get the module handle of that dll which is mapped to the process address space.
The use is that when you are trying to call a function exported by the dll, or trying to use a dialog template in side that dll.At that time if you use the HMODULE returned form GetMoudleHandle(NULL) your code wont work.
Just to add my two-cents to these answers. In case you need to get the module handle from within a DLL (and don't want to, or can't save it in a global variable from the DllMain call) you can use this function to get it instead:
HMODULE getThisModuleHandle()
{
//Returns module handle where this function is running in: EXE or DLL
HMODULE hModule = NULL;
::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
(LPCTSTR)getThisModuleHandle, &hModule);
return hModule;
}
One potential gain you get from using GetModuleHandle(NULL) over directly using the WinMain HINSTANCE comes more from architecture. If you want to provide a platform-independent system that runs on linux/windows/whatever you can have a layer that does platform-dependent translations. If that's the case you don't want platform dependent objects such as HINSTANCE showing up in the main application code. So, to circumvent that platform-dependence I put GetModuleHandle(NULL) in the constructor of the platform-dependent class which has the same effect that direct use of the WinMain HINSTANCE does but that abstracts that specific functionality out of the main codebase itself.
I'm developing a plugin (a dll that is loaded by other app). There's a special function that should return HWND so that app can show a dialog. The problem is that I don't know from where I can get the hInstance (it's not passed as a parameter to the function).
Looks like I'm not understanding something, I'm new to all this stuff, so forgive if the question is silly.
UPD: tried to get hInstance with getModuleHandle:
void* createLoginDialog() {
HINSTANCE hIns = (HINSTANCE) GetModuleHandle(L"comapping");
HWND hWnd = CreateWindow(L"Popup",
L"Enter login",
WS_POPUP,
20,
20,
20,
20,
NULL,
NULL,
hIns,
NULL);
return hWnd;
}
I'm still getting Access Violation.
Several ways to get it:
The first argument passed to your DllMain() entrypoint, cast to HINSTANCE
GetModuleHandle() using your DLL name, cast to HINSTANCE
VirtualQuery(), passing the address of your function. Cast the returned MEMORY_BASIC_INFORMATION.BaseAddress to HINSTANCE. Works on both 32-bit and 64-bit versions of Windows.
According to the documentation of CreateWindow, the hInstance argument is optional. This means that it's valid to pass NULL here. However, as Simon Richter points out in the comments to this answer, the argument may only be NULL the window class is registered globally.
If you're writing a DLL, you may just as well define a DllMain entry point function yourself. This function is called by Windows, passing the handle of your function as the first arugment. You can memorize this handle somewhere to reuse it when creating your window.