1

以下代码适用于 Window 7,但当我在 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;
}

另外,我有一个resource.rcresource.h文件链接,winres该文件符合manifest.xml提供控件版本 6 规范的文件。

好的,这就是交易,它可以在 Windows 7 上顺利运行。它在 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。

这只发生在 Windows XP 上,它在 Windows 7 上工作得很好。如果我不包括这一行,它就像没有任何问题一样工作。

这个示例的重点是让主题在 XP 和 Windows 7 上都能正常工作。(这不是一件容易的事。)

为什么 RegisterClassEx 返回 Ok,但在 Windows XP 而不是 Windows 7 上生成 GetLastError 错误?

另外,它到底在寻找什么文件?我看到其他谷歌结果说它与混乱的消息循环或窗口过程有关,但这里不是这种情况。

4

1 回答 1

2

一般错误...由于MSDN,您只能在RegisterClassEx“返回值为零”时检查 GetLastError。当RegisterClassExCreateWindowEx或任何其他函数成功时,GetLastError可能会返回垃圾,不保证会返回零(如果在返回值GetLastError部分中没有描述不同的行为)。

于 2012-08-05T21:21:34.450 回答