大家好, 我正在使用常见控件在纯Win32 API中创建VC ++ 2008项目。现在我遇到的问题是如果我使用LoadLibrary API函数显式链接到WinSXS文件夹中的comctl32.dll(版本6.0。),我的主窗口甚至都不会显示。但是如果我在我的代码中使用#pragma注释 - :
#pragma comment(linker,"\"/manifestdependency:type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
并将comctl32.lib添加到我的项目依赖项然后运行它然后我得到我的预期输出。但是,如果我使用LoadLibrary API函数手动链接到WinSXS中的comctl32.dll,然后使用GetProcAddress Api函数获取InitCommonControls的过程地址,然后调用它,我的主窗口甚至不显示。为什么会这样? 根据定义,我应该能够加载我的DLL手动找到我想要使用的所需程序并执行它,但由于某种原因,这不会发生在这里。 这是我正在使用的代码 - :
#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;
}
如果有人想要整个项目,请给我你的邮件ID,我会将整个项目发送给他们。我想知道为什么会发生这种情况,而不是我是否应该这样做。谢谢。
答案 0 :(得分:1)
工作案例
你的清单重新引用Microsoft.Windows.Common-Controls
程序集。此程序集是一个或多个DLL和COM对象的集合,它不是.Net程序集。启动应用程序时,Windows会创建activation context。对程序集中描述的DLL或COM对象的任何引用都将重定向到请求的版本。激活上下文在调用comctl32.dll
期间保持活动状态,因此对DLL或COM对象的任何调用也将被重定向。
无法工作的案例
您从comctl32.dll
加载特定版本的\Windows\Sxs\
。这引用了其他DLL或COM对象,但是在没有激活上下文的情况下,会加载错误的DLL。而你的申请不起作用。
<强>结论强>
我不知道这是否是您案例中的具体问题,但一般来说,\Windows\Sxs
中的任何内容都打算在特定的激活上下文中运行,您不能指望它在外部工作那个背景。即使它确实发生了工作,它可能会在将来破裂。不要这样做。