CreateWindowEx,GetLastError,Windows 7和XP奇怪和奇​​怪的行为

时间:2012-08-05 18:56:09

标签: winapi windows-7 error-handling windows-xp

以下代码适用于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相关联,符合提供控件版本6规范的manifest.xml

好的,所以这是交易,这在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生成错误?

此外,它还在寻找什么文件?我已经看到其他谷歌的结果说它与搞乱的消息循环或窗口程序有关,但这不是这里的情况。

1 个答案:

答案 0 :(得分:2)

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