c++ - Common Dialogs DLL 无法手动加载

标签 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,我会将整个项目发送给他们。我想知道为什么会发生这种情况,而不是我是否应该这样做。谢谢。

最佳答案

工作案例

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

不工作的案例

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

结论

我不知道这是否是您遇到的具体问题,但一般来说,\Windows\Sxs 中的任何内容都旨在在特定的激活上下文中运行,您可以不要指望它能在那种环境之外工作。即使它确实起作用了,它也可能在未来崩溃。不要这样做。

关于c++ - Common Dialogs DLL 无法手动加载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11079228/

相关文章:

delphi - 了解 Delphi 中硬盘的速度有多快

visual-studio - VS 2005 未检测到 C++ 项目头文件中的更改

c++ - C++ 中模板化别名的 Typedef

c++ - 如何在 Mac 上编译 C++ 文件?

c++ - ShowWindow() 立即隐藏 SW_HIDE 窗口,没有效果

C++ WinAPI 需要帮助卡在通过左键单击任务栏以编程方式使窗口最小化

c++ - 为什么我得到 C2883 : function declaration conflicts with - introduced by using-delcaration when overriding only one overload from a base class?

c++ - 让 dll 包含在 Visual Studio 中工作

c++ - IN6_SET_ADDR_UNSPECIFIED 未在此范围内声明

c++ - 使用 `Command terminated` 时为 `cin`