WinMain/Win32 Window 未显示,但显示在任务管理器的“进程”选项卡中

WinMain/Win32 Window not displaying, but shows up in Processes tab of Task Manager

我是 c++ 的新手,我一直坚持显示 window。我没有收到任何错误,但我的 Window 没有显示在桌面上。当我打开任务管理器时,它出现在 'Proccesses' 选项卡下。我还没有找到解决此问题的任何方法,因此不胜感激。谢谢! :)

**注意:我使用的是 Microsoft Visual Studio 2012 **注意:不完全是 c++ 的新手,但更多的是创建 win32 应用程序

#include <Windows.h>
#include <stdlib.h>
#include <string.h>
#include <tchar.h>

static TCHAR WindowClass[] = L"Window";

LRESULT CALLBACK WindowProc(
    HWND   WinH,
    UINT   Msg,
    WPARAM wParam,
    LPARAM lParam
    )
{
    switch (Msg)
    {
        PAINTSTRUCT pntStruct;
        static HDC hdc;

        case WM_PAINT:
        {
            BeginPaint(
                WinH,
                &pntStruct
            );
            TextOut(hdc,
                5, 5,
                L"Hello, World!", _tcslen(L"Hello, World!"));
            //pntStruct.rcPaint
            EndPaint(
                WinH,
                &pntStruct
            );

        } break;

        case WM_SIZE:
        {

        } break;

        case WM_MOVE:
        {

        } break;

        case WM_DESTROY:
        {

        } break;

        case WM_CLOSE:
        {

        } break;

        default:
        {
            return DefWindowProc(WinH, Msg, wParam, lParam);
        } break;

        case WM_ACTIVATEAPP:
        {
            if (WM_ACTIVATEAPP)
            {
                OutputDebugStringA("WM_ACTIVEAPP->TRUE");
            }
            else
            {
                OutputDebugStringA("WM_ACTIVEAPP->FALSE");
            }
        } break;

    }

    return 0;
};


int WINAPI WinMain(
    HINSTANCE Window,
    HINSTANCE PrevInstance,
    LPSTR     Cmd,
    int       CmdShow
    )
{

    WNDCLASSEX wclass;
        //wclass.cbSize =  sizeof(WNDCLASS);
        wclass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
        wclass.lpfnWndProc = WindowProc;
        wclass.cbClsExtra = 0;
        wclass.cbWndExtra = 0;
        wclass.hInstance = Window;
        //wclass.hIcon; TODO: CREATE ICON
        //wclass.hCursor;
        //wclass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
        wclass.lpszMenuName = NULL;
        wclass.lpszClassName = (LPCTSTR)WindowClass;
//      HICON     hIconSm;
        RegisterClassEx(&wclass);

    HWND CreateWin = CreateWindow(
        WindowClass,
        L"NAME OF WINDOW",
        WS_VISIBLE | WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,//WIDTH:[TODO]->Make custom width to fit window
        CW_USEDEFAULT,//HEIGHT:[TODO]->Make custom width to fit window
        0,
        0,
        Window,
        0
    );

    ShowWindow(CreateWin, CmdShow);
    UpdateWindow(CreateWin);

    MSG message;

    while (GetMessage(&message, NULL, 0, 0) > 0)
    {
        TranslateMessage(&message);
        DispatchMessage(&message);
    };

    return 0;
};

这段代码有很多问题。

您将 WindowClass 声明为 TCHAR[],但使用 wchar_t[] 对其进行了初始化。与 TextOut()lpString 参数相同。这只有在为项目定义了 UNICODE 时才有效,否则你会得到一个编译器错误。当您使用 TCHAR 时,您需要使用 TEXT() 宏来包装字符串文字,以便它们使用正确的字符类型。否则,停止使用 TCHAR 并只对所有内容使用 Unicode APIs。如果您的代码需要同时支持 ANSI (Win9x/ME) 和 Unicode (NT4+) 编译,您只需要使用 TCHAR。没有人真正支持 Win9x/Me,所以新代码应该只关注 Unicode APIs.

您没有将 WNDCLASSEX 结构的内容归零,因此您有意注释掉但未为其赋值的所有字段(最重要的是 cbSize 字段)将包含来自堆栈的随机值。这很可能会导致 RegisterClassEx() 失败,而您并未对此进行检查。为避免此问题,请始终在使用前将 API 结构归零。这对于随时间增长的结构尤为重要(当较新的 Windows 版本引入新的结构字段时)。此类结构通常有一个 cbSize 字段,因此 API 知道您正在使用哪个版本的结构,因此您必须提供准确的值。并且您需要将所有未使用的字段归零,这样您就不会从 API.

中得到意外的行为

您没有检查 CreateWindow() 是否失败,例如 RegisterClassEx() 失败的副作用。

您的 WindowProc() 应该将未处理的消息传递给 DefWindowProc(),但您没有这样做。大多数 case 块只是丢弃消息,因此 Windows 无法处理它们。那是你真正想要的吗?我对此表示怀疑。特别是,WM_CLOSEDefWindowProc() 的默认行为是销毁 window,触发 WM_DESTROY 消息。

您的 WM_DESTROY 处理程序未调用 PostQuitMessage()WM_QUIT 消息放入调用线程的消息队列中,因此 GetMessage() 可以 return 0 中断您的消息循环并让应用程序退出。

您的 WM_PAINT 处理程序没有使用 BeginPaint() 提供给您的 HDC,您正在使用未初始化的 HDC 变量进行绘制。

综上所述,试试这样的东西:

#include <Windows.h>
#include <stdlib.h>
#include <string.h>
#include <tchar.h> // Or: remove this

static TCHAR WindowClass[] = TEXT("Window");
// or: static WCHAR WindowClass[] = L"Window";

LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
        case WM_PAINT:
        {
            static const TCHAR* HelloWorld = TEXT("Hello, World!");
            // or: const WCHAR* HelloWorld = L"Hello, World!";

            PAINTSTRUCT pntStruct = {0};
            HDC hdc = BeginPaint(hWnd, &pntStruct);

            TextOut(hdc, 5, 5, HelloWorld, _tcslen(HelloWorld));
            // or: TextOutW(hdc, 5, 5, HelloWorld, lstrlenW(HelloWorld));

            EndPaint(hWnd, &pntStruct);
            break;
        }

        case WM_SIZE:
        {
            //...
            break;
        }

        case WM_MOVE:
        {
            //...
            break;
        }

        case WM_DESTROY:
        {
            PostQuitMessage(0);
            break;
        }

        case WM_CLOSE:
        {
            //...
            break;
        }

        case WM_ACTIVATEAPP:
        {
            if (WM_ACTIVATEAPP)
            {
                OutputDebugString(TEXT("WM_ACTIVEAPP->TRUE"));
                // or: OutputDebugStringW(L"WM_ACTIVEAPP->TRUE");
            }
            else
            {
                OutputDebugString(TEXT("WM_ACTIVEAPP->FALSE"));
                // or: OutputDebugStringW(L"WM_ACTIVEAPP->FALSE");
            }

            break;
        }
    }

    return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    WNDCLASSEX wclass = {0}; // Or: WNDCLASSEXW
    wclass.cbSize = sizeof(wclass);
    wclass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
    wclass.lpfnWndProc = &WindowProc;
    wclass.cbClsExtra = 0;
    wclass.cbWndExtra = 0;
    wclass.hInstance = hInstance;
    wclass.hIcon = NULL; // TODO: CREATE ICON
    wclass.hCursor = NULL;
    wclass.hbrBackground = NULL;//(HBRUSH)(COLOR_WINDOW+1);
    wclass.lpszMenuName = NULL;
    wclass.lpszClassName = WindowClass;
    wclass.hIconSm = NULL;

    if (!RegisterClassEx(&wclass)) // Or: RegisterClassExW()
    {
        // error! Use GetLastError() to find out why...
        return 0;
    }

    HWND hCreateWin = CreateWindow( // Or: CreateWindowW()
        WindowClass,
        TEXT("NAME OF WINDOW"), // Or: L"NAME OF WINDOW"
        WS_VISIBLE | WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,//WIDTH:[TODO]->Make custom width to fit window
        CW_USEDEFAULT,//HEIGHT:[TODO]->Make custom width to fit window
        0,
        0,
        hInstance,
        0
    );

    if (!hCreateWin)    
    {
        // error! Use GetLastError() to find out why...
        return 0;
    }

    ShowWindow(hCreateWin, nCmdShow);
    UpdateWindow(hCreateWin);

    MSG message;
    while (GetMessage(&message, NULL, 0, 0) > 0)
    {
        TranslateMessage(&message);
        DispatchMessage(&message);
    };

    return 0;
};