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アセンブリを参照します。このアセンブリは、1 つ以上の DLL および COM オブジェクトのコレクションであり、.Net アセンブリではありません。アプリケーションが起動されると、Windows はアクティベーション コンテキストを作成します。アセンブリに記述されている DLL または COM オブジェクトへの参照は、要求されたバージョンにリダイレクトされます。アクティベーション コンテキストは へcomctl32.dllの呼び出し中もアクティブなままなので、DLL または COM オブジェクトに対する呼び出しもリダイレクトされます。

動かないケース

comctl32.dllfromの特定のバージョンをロードします\Windows\Sxs\。これは他の DLL または COM オブジェクトを参照しますが、アクティベーション コンテキストがない場合、間違ったものが読み込まれます。そして、あなたのアプリケーションは機能しません。

結論

これがあなたの場合の特定の問題であるかどうかはわかりませんが、一般に、存在\Windows\Sxsするものは特定のアクティベーションコンテキストで実行されることを意図しており、そのコンテキストの外で動作することは期待できません. たまたま動いたとしても、将来壊れるかもしれません。これをしないでください。

于 2012-06-18T18:01:28.523 に答える