Common Dialogs DLL无法手动加载

时间:2012-06-18 08:26:23

标签: c++ winapi visual-c++

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

1 个答案:

答案 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中的任何内容都打算在特定的激活上下文中运行,您不能指望它在外部工作那个背景。即使它确实发生了工作,它可能会在将来破裂。不要这样做。