0

I have a DLL that may display a dialog window using the following MFC code:

void ShowMyDialog()
{
    BOOL bInitted = SUCCEEDED(::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE));

    INITCOMMONCONTROLSEX InitCtrls;
    InitCtrls.dwSize = sizeof(InitCtrls);
    InitCtrls.dwICC = ICC_WIN95_CLASSES;
    InitCommonControlsEx(&InitCtrls);
    //InitCommonControls();    //Tried also with just this call

    AfxEnableControlContainer();

    HMODULE hDll = NULL;
    if(GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
        (LPCWSTR) ShowMyDialog,
        &hDll) &&
        hDll)
    {
        AfxSetResourceHandle(hDll);

        CMyDialog dl;       //Derived from CDialog
        dl.DoModal();
    }

    if(bInitted)
        ::CoUninitialize();
}

This works, but the dialog shown doesn't have visual styles enabled:

enter image description here

I found this article on how to enable visual styles for a DLL. So I added the resource file with suggested manifest content:

enter image description here

and gave it resource ID of 123:

enter image description here

But still no cigar. What am I missing here?

c00000fd
  • 20,994
  • 29
  • 177
  • 400
  • Resource ID 123 comes from the section "Using ComCtl32 Version 6 in Control Panel or a DLL That Is Run by RunDll32.exe". Is this DLL is a Control Panel page? If so, then 123 is necessary, and something else is wrong. If this is a DLL that is run by rundll32.dll, [it should be converted to a normal ordinary program](https://blogs.msdn.microsoft.com/oldnewthing/20130104-00/?p=5643). If neither of the two are correct, then you're looking at the wrong section. You likely want "Adding Visual Style Support to an Extension, Plug-in, MMC Snap-in or a DLL That Is Brought into a Process" instead. – andlabs Jan 18 '17 at 03:46
  • Yes, I agree those section names are not good. – andlabs Jan 18 '17 at 03:46
  • @DavisHeffernan: Thank you for pointing it out. Wow. Who could've thought that one needs to use those `CreateActCtx` APIs? – c00000fd Jan 18 '17 at 08:37
  • If you were using raw Win32 then you could get away with `ISOLATION_AWARE_ENABLED` but I don't think MFC is going to fall for that. – David Heffernan Jan 18 '17 at 09:43

1 Answers1

1

I don't think that will work. When AppWizard generates a project, when it includes the Common controls 6, it uses a pragma similar to this:

#pragma comment(linker,"\"/manifestdependency:type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

When you have a manifest embedded in an EXE, for it to be default loaded by the manifest loader, it has to have an ID of 0. You have some other ID, so you don't stand a chance of it working.

My simple suggestion would to be generate a test MFC App Wizard application and copy the #pragma directive from that project. Usually the App Wizard puts it in the stdafx.h file, but you can generally put it in any source file you want.

Also, as a side comment, in your InitInstance() method, call the AfxOleInit() instead of calling CoInitializeEx() in your ShowMyDialog() function. I'd also put the AfxEnableControlContainer() in InitInsance() as well. Of course, it has to be before your ShowMyDialog() is called.

Joseph Willcoxson
  • 5,853
  • 1
  • 15
  • 29
  • The resource ID 123 comes from the section "Using ComCtl32 Version 6 in Control Panel or a DLL That Is Run by RunDll32.exe". If this DLL is a Control Panel page, then 123 is necessary. If this is a DLL that is run by rundll32.dll, [it should be converted to a normal ordinary program](https://blogs.msdn.microsoft.com/oldnewthing/20130104-00/?p=5643). The OP specifically said they were making a DLL, so while your advice is correct about executables, it doesn't answer the question. I commented above with more guidance. – andlabs Jan 18 '17 at 03:42
  • @andlabs: well, I can't control which process this DLL can be loaded into. – c00000fd Jan 18 '17 at 03:47
  • @c00000fd this isn't about what process the DLL gets loaded into; it's about what the intended use case of the DLL is. What is the intended use case? The part that you read, and I presume you read it by accident because again, the section names are bad, was about DLLs that are *intended to* be run by the Control Panel system or by rundll32.dll. I'm not aware of anything in Windows that requires you to use rundll32.dll... – andlabs Jan 18 '17 at 03:48
  • @andlabs: Oh, so what you're saying is that to apply visual styles the loader looks in the process and not my DLL for the manifest file, hah? So I have to tailor it for a specific process and that I can't just assume that "any process" can load my DLL. Right? – c00000fd Jan 18 '17 at 03:51
  • @c00000fd no, I'm saying the way your DLL is loaded depends on what loads it. If you are simply writing a DLL that is loaded into most programs, then the part about isolation awareness in the section underneath the one that said use 123 is the one that applies to you. But if you are writing a Control Panel page, then the part about using resource ID 123 applies to you, because Control Panel pages are somehow loaded differently. I'm not a Windows team member so I would not know how or why. So are you writing a Control Panel page, or are you writing a DLL for a specific app, and if so, which? – andlabs Jan 18 '17 at 03:53
  • @andlabs: Yeah. I see. I can't change the exe itself. This particular DLL loads as a `custom action` for an MSI installer. – c00000fd Jan 18 '17 at 03:56
  • Okay. In that case I would suggest following the instructions in the "Adding Visual Style Support to an Extension, Plug-in, MMC Snap-in or a DLL That Is Brought into a Process" section of that MSDN page. The tl;dr version is that the resource ID should be `ISOLATIONAWARE_MANIFEST_RESOURCE_ID` (whose value is `2`) and you compile your DLL with the C/C++ preprocessor macro `ISOLATION_AWARE_ENABLED` defined to `1` before including any header files. Hopefully that'll work with Windows Installer. – andlabs Jan 18 '17 at 04:02
  • See [RT_MANIFEST resource, and ISOLATION_AWARE_ENABLED](https://blogs.msdn.microsoft.com/junfeng/2007/06/26/rt_manifest-resource-and-isolation_aware_enabled/) on MSDN. – Remy Lebeau Jan 18 '17 at 05:03