1

次のコードはWindows7で機能しますが、Windows XPで実行すると、Windowsから返されるエラーメッセージ「システムは指定されたファイルを見つけることができません」で失敗します。

#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include <uxtheme.h>
#include <string>

const char g_szClassName[] = "myWindowClass";
const char title[] = "Window Title\0";

COLORREF        WinColor;
HFONT       defaultFont;
NONCLIENTMETRICSA   Metrics;
DWORD       dwVersion;
DWORD       dwMajorVersion;
DWORD       dwMinorVersion;
HBRUSH      hBrushColor;

bool LastError = false;
bool W32Error (const char * Msgtext);

// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch(msg)
    {

    case WM_NCCREATE:
    {
        Metrics.cbSize = sizeof(NONCLIENTMETRICS);
        SystemParametersInfo (SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &Metrics, 0);
        defaultFont = (HFONT) CreateFontIndirect (& Metrics.lfMessageFont);
        return TRUE;
    }
    break;

    case WM_CTLCOLORSTATIC: {
        dwVersion = GetVersion();
        dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
        dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion)));
        if ( (IsAppThemed()) && (dwMajorVersion < 6) ) {
            WinColor = GetSysColor(COLOR_WINDOW);
            SetBkColor((HDC)wParam, WinColor);
            return (LRESULT)hBrushColor;
        }
    }
    break;

    case WM_CREATE: {
        HWND hButton = CreateWindowEx(
            0,
            "BUTTON", "Button",
                WS_TABSTOP      |
                WS_VISIBLE      |
                WS_CHILD        |
                BS_NOTIFY       |
                BS_PUSHBUTTON,
            10, 10, 96, 32, hwnd,
            (HMENU)50,
            GetModuleHandle(NULL),
            NULL);
        if (W32Error ("Button Creation Failed\nReason:")) exit (1);
        return TRUE;
    }
    break;

    case WM_CLOSE:
        DestroyWindow(hwnd);
        break;

    case WM_DESTROY:
        PostQuitMessage(0);
        break;

    default:
        return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPSTR lpCmdLine, int nCmdShow)
{
    WNDCLASSEX wc;
    HWND hwnd;
    MSG Msg;

    // Initialize common controls.
    INITCOMMONCONTROLSEX icc;
    icc.dwSize = sizeof(icc);
    icc.dwICC = ICC_WIN95_CLASSES       |
                ICC_COOL_CLASSES    |
                ICC_INTERNET_CLASSES|
                ICC_LINK_CLASS  |
                ICC_STANDARD_CLASSES|
                ICC_PROGRESS_CLASS  |
                ICC_USEREX_CLASSES;
    InitCommonControlsEx(&icc);

    //Step 1: Registering the Window Class
    wc.cbSize        = sizeof(WNDCLASSEX);
    wc.style         = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc   = WndProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = hInstance;
    wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    wc.lpszMenuName  = NULL;
    wc.lpszClassName = g_szClassName;
    wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);

    // see if something is going on before the window registration takes place....
    if (W32Error ("Previous Check for Error?\nReason:")) exit (1);

    if(!RegisterClassEx(&wc))
    {
        MessageBox(NULL, "Window Registration Failed!", "Error!",
            MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }
    if (W32Error ("Window Registration Failed\nReason:")) exit (1);

    // Step 2: Creating the Window
    hwnd = CreateWindowEx(
        WS_EX_CLIENTEDGE,
        g_szClassName,
        "The title of my window",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
        NULL, NULL, hInstance, NULL);
    if (W32Error ("Window Creation Failed\nReason:")) exit (1);

    if(hwnd == NULL)
    {
        MessageBox(NULL, "Window Creation Failed!", "Error!",
            MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    SendMessageA(hwnd, WM_SETFONT, WPARAM (defaultFont), TRUE);
    SendMessageA(hwnd, WM_SETTEXT, WPARAM(NULL) , LPARAM (title));

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    // Step 3: The Message Loop
    while(GetMessage(&Msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }
    return Msg.wParam;
}


bool W32Error (const char * Msgtext)
{
    LPTSTR errorText = NULL;
    DWORD   dwLastError = GetLastError();
    if (!dwLastError) {
        LastError = false;
        return LastError;
    }
    // use system message tables to retrieve error text
    // allocate buffer on local heap for error text
    // Important! will fail otherwise, since we're not (and CANNOT) pass insertion parameters
    FormatMessageA(
        FORMAT_MESSAGE_FROM_SYSTEM     |
        FORMAT_MESSAGE_ALLOCATE_BUFFER |
        FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL,                           // unused with FORMAT_MESSAGE_FROM_SYSTEM
        dwLastError,
        MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
        (LPTSTR)&errorText,             // output
        0,                              // minimum size for output buffer
        0);                             // arguments - see note
        if ( NULL != errorText ) {
            std::string Message;
            Message += Msgtext;
            Message += "\n";
            Message += errorText;
            MessageBoxA(NULL, (LPCSTR)Message.c_str(), "An Internal Error Occurred", MB_OK);
            LocalFree(errorText);
            errorText = NULL;
            LastError = true;
        } else {
            LastError = false;
        }
        return LastError;
}

追加として、コントロールバージョン6仕様を提供するに準拠するとにリンクされたファイルがresource.rcあります。resource.hwinresmanifest.xml

さて、これが取引です。これはWindows7で問題なく実行されます。そして、私が行に入れない限り、それはXPで実行されます if (W32Error ("Window Registration Failed\nReason:")) exit (1); (基本的に、それは含む私のエラーチェックルーチンを呼び出しますGetLastError()

   if(!RegisterClassEx(&wc))
    {
        MessageBox(NULL, "Window Registration Failed!", "Error!",
            MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }
    if (W32Error ("Window Registration Failed\nReason:")) exit (1);

その行を含めると、「システムは指定されたファイルを見つけることができません」というエラーが表示されます。RegisterClassExからの戻り値はifブロックに入らないため、RegisterClassExはOkを返します。

これはWindowsXPでのみ発生し、Windows 7でも問題なく動作します。この行を含めないと、何も問題がないかのように動作します。

このサンプルのポイントは、テーマをXPとWindows 7の両方で正しく機能させることです(簡単な作業ではありません)。

RegisterClassExがOkを返すのに、Windows7ではなくWindowsXPでGetLastErrorのエラーが生成されるのはなぜですか?

また、とにかくどのファイルを探していますか?私は他のグーグルの結果がそれが台無しにされたメッセージループまたはウィンドウ手順に関係していると言うのを見ました、しかしそれはここではそうではありません。

4

1 に答える 1

2

一般的な間違い... MSDNRegisterClassExが原因で、 「戻り値がゼロ」の場合にのみGetLastErrorをチェックできます。RegisterClassExまたはCreateWindowExまたは他の関数が成功すると、ガベージGetLastErrorが返される可能性があり、GetLastErrorゼロを返す保証はありません(異なる動作が戻り値のセクションで説明されていない場合)。

于 2012-08-05T21:21:34.450 に答える