Hello everyone,
I am making a VC++ 2008 project in pure Win32 API which uses common controls. Now the problem that I am facing is if I explicitly link to the comctl32.dll(version 6.0.) in the WinSXS folder using the LoadLibrary API function, my main window does not even display. But if I use the #pragma comment in my code as such -:
#pragma comment(linker,"\"/manifestdependency:type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
and add the comctl32.lib to my project dependencies then run it then I get my expected output. But if I link manually to the comctl32.dll in the WinSXS using LoadLibrary API function and then get the procedure address of InitCommonControls using the GetProcAddress Api function and then call it my main window does not even display. Why is this happening?
By definition I should be able to load my dll manually locate the required procedure that I want to use and execute it, but for some reason this is not happening here.
this is the code that I am using -:
#include <Windows.h>
#include <CommCtrl.h>
#include "resource.h"
LRESULT CALLBACK WindowFunc(HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK DialogFunc(HWND, UINT, WPARAM, LPARAM);
char szWinName[]="Timer Main Window";
HWND hDlg=NULL;
HINSTANCE hInst;
int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE hPrevInst,
LPSTR lpszArgs, int nWinMode)
{
HWND hwnd;
MSG msg;
WNDCLASSEX wndclass;
HMODULE hmod=NULL;
void (*InitCommonControls)(void)=NULL;
wndclass.cbSize=sizeof(WNDCLASSEX);
wndclass.hInstance=hThisInst;
wndclass.lpszClassName=szWinName;
wndclass.lpfnWndProc=WindowFunc;
wndclass.style=0;
wndclass.hIcon=LoadIcon(hThisInst,MAKEINTRESOURCE(IDI_ICON1));
wndclass.hIconSm=LoadIcon(hThisInst,MAKEINTRESOURCE(IDI_ICON2));
wndclass.hCursor=LoadCursor(NULL,IDC_ARROW);
wndclass.lpszMenuName=NULL;
wndclass.cbClsExtra=0;
wndclass.cbWndExtra=0;
wndclass.hbrBackground=(HBRUSH) GetStockObject(LTGRAY_BRUSH);
if(!RegisterClassEx(&wndclass)) return 0;
/*Initialize the common controls for WinXP look and feel*/
hmod=LoadLibrary("C:\\WINDOWS\\WinSxS\\x86_Microsoft.Windows.Common-Controls_6595b64144ccf1df_6.0.2600.6028_x-ww_61e65202\\comctl32.dll");
if (!hmod)
{ MessageBox(NULL,"dll not loaded","error",MB_ICONERROR);
}
InitCommonControls=(void (*)(void)) GetProcAddress(hmod,
"InitCommonControls");
if(InitCommonControls==NULL){
MessageBox(NULL,"no entry point","error",MB_ICONERROR);
}
(*InitCommonControls)();
//FreeLibrary(hmod);
//hmod=NULL;
hInst=hThisInst;
hwnd=CreateWindow(
szWinName,
"Auto Timer (Work in progress)",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hThisInst,
NULL
);
while(GetMessage(&msg, NULL, 0, 0)>0)
{ if (!hDlg||!IsDialogMessage(hDlg,&msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
}
LRESULT CALLBACK WindowFunc(HWND hwnd, UINT message, WPARAM wparam,
LPARAM lparam)
{
switch(message){
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_CREATE:
hDlg=CreateDialog(hInst,MAKEINTRESOURCE(IDD_FORMVIEW),
hwnd,(DLGPROC)DialogFunc);
break;
default:
return DefWindowProc(hwnd,message,wparam,lparam);
}
return 0;
}
BOOL CALLBACK DialogFunc(HWND hwnd, UINT message,
WPARAM wparam, LPARAM lparam)
{
switch(message)
{
case WM_INITDIALOG:
SendMessage(hwnd,WM_SETICON, ICON_SMALL ,
(LPARAM)LoadIcon(hInst,MAKEINTRESOURCE(IDI_ICON2)));
break;
case WM_CTLCOLORSTATIC:
return (INT_PTR)GetStockObject(WHITE_BRUSH);
case WM_CLOSE:
DestroyWindow(hwnd);
hDlg=NULL;
PostQuitMessage(0);
return TRUE;
}
return FALSE;
}
If anyone wants the entire project please give me your mail id and I will send the entire project to them. I want to know exactly why this is happening not whether I should do it or not.Thank You.
The working case
Your manifest refences the
Microsoft.Windows.Common-Controlsassembly. This assembly is a collection of one or more DLLs and COM objects, it is not a .Net assembly. When your application is launched Windows creates an activation context. Any references to a DLL or COM object that is described in the assembly are redirected to the requested version. The activation context remains active during calls intocomctl32.dll, so any calls it makes to DLLs or COM objects will also be redirected.The not-working case
You load a specific version of
comctl32.dllfrom\Windows\Sxs\. This references other DLLs or COM objects but, in the absence of an activation context, the wrong ones are loaded. And your application doesn’t work.Conclusion
I don’t know if this is the specific problem in your case, but in general anything that lives in
\Windows\Sxsis intended to run in a particular activation context, and you can’t expect it to work outside of that context. Even if it did happen to work, it might break in the future. Don’t do this.