c++ - WinMain/Win32 窗口不显示,但显示在任务管理器的进程选项卡中

标签 c++ winapi visual-studio-2012 winmain

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

**注意:我使用的是 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 API。如果您的代码需要同时支持 ANSI (Win9x/ME) 和 Unicode (NT4+) 编译,您只需要使用 TCHAR。没有人真正支持 Win9x/Me,因此新代码应该只关注 Unicode API。

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

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

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

您的 WM_DESTROY 处理程序未调用 PostQuitMessage()WM_QUIT 消息放入调用线程的消息队列中,因此 GetMessage( ) 可以返回 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;
};

关于c++ - WinMain/Win32 窗口不显示,但显示在任务管理器的进程选项卡中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30551850/

相关文章:

unit-testing - 为什么“全部运行”会在VS2012单元测试中导致崩溃,但不能一个一个地运行?

c++ - 如何禁止来自内部 Visual Studio 文件的警告

c++ - 调试显示不正确值的 64 位 DLL 检查器

c++ - 将对象 move 到 vector 中的正确参数类型

c++ - 在 HardwareStore 类中找不到匹配的构造函数 (C++)

c - 使用 WinAPI 的多线程。计算圆周率

c# - 如何在 visual studio 中找到要连接的 informix 数据源

c++ - 如何在 Qt 的 Linux 上获取 USB 驱动器的路径?

c++ - 消息循环在这个程序中的作用?还有几个问题

c++ - 使用 OpenGL 和 WinAPI 跳帧?