1

大家好,我正在使用通用控件的纯 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,我会将整个项目发送给他们。我想确切地知道为什么会发生这种情况,而不是我是否应该这样做。谢谢。

4

1 回答 1

1

工作案例

您的清单引用Microsoft.Windows.Common-Controls程序集。此程序集是一个或多个 DLL 和 COM 对象的集合,它不是 .Net 程序集。当您的应用程序启动时,Windows 会创建一个激活上下文。对程序集中描述的 DLL 或 COM 对象的任何引用都将重定向到请求的版本。激活上下文在调用 期间保持活动状态comctl32.dll,因此它对 DLL 或 COM 对象的任何调用也将被重定向。

不工作的情况

您加载特定版本的comctl32.dllfrom \Windows\Sxs\。这引用了其他 DLL 或 COM 对象,但在没有激活上下文的情况下,会加载错误的对象。而且您的应用程序不起作用。

结论

我不知道这是否是您的具体问题,但一般来说,存在的任何东西\Windows\Sxs都旨在在特定的激活上下文中运行,并且您不能期望它在该上下文之外工作。即使它确实起作用了,它也可能在未来破裂。不要这样做。

于 2012-06-18T18:01:28.523 回答