无法使用 WinAPI 显示窗口

Posted

技术标签:

【中文标题】无法使用 WinAPI 显示窗口【英文标题】:Can't display window with WinAPI 【发布时间】:2013-02-08 20:21:39 【问题描述】:

我知道这是一个无聊的问题,我之前已经做过一百万次了,但是我无法在我编写的 WinAPI 程序中显示一个简单的窗口。它后来使用 DirectX 在窗口上绘图,但我已经调试了程序,即使在所有 DirectX 内容开始执行之前它也无法显示窗口。我只在任务栏上看到程序图标,但没有窗口。

这是处理窗口创建的一段代码。

WNDCLASSEX wc;
    ZeroMemory(&wc, sizeof(wc));
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = (WNDPROC)WndProc;
    wc.hInstance = hInstance;
    wc.lpszClassName = title.c_str();
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hIcon = 0;
    wc.hIconSm = 0;
    wc.hbrBackground = 0;
    wc.lpszMenuName = 0;

    if(!RegisterClassEx(&wc))
    
        debug << "Failed to register window class." << std::endl;
        return 0;
    

    DWORD dwStyle, dwExStyle;
    dwStyle = WS_OVERLAPPEDWINDOW | WS_VISIBLE;
    dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;

    AdjustWindowRectEx(&windowRect, dwStyle, FALSE, dwExStyle);

    int wwidth = windowRect.right - windowRect.left;
    int wheight = windowRect.bottom - windowRect.top;

    debug << "Screensize: " << wwidth << "x" << wheight << std::endl;
    debug << "Creating program window..." << std::endl;

    HWND hWnd = CreateWindowExW(dwExStyle, wc.lpszClassName, title.c_str(), dwStyle | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0, 0, wwidth, wheight, NULL, NULL, hInstance, 0); 

    if(!hWnd)
    
        debug << "Error occured while trying to display the window.\n";
        return false;
    

    ShowWindow(hWnd, SW_SHOW);
    UpdateWindow(hWnd);

我绝望了。我开始觉得我的编程环境、库等有问题。我使用的是 VS2012/Win7,以及 VS 附带的标准 c++ 编译器。

编辑 WindowRect 来了

RECT windowRect;
    windowRect.left = 0;
    windowRect.right = g_engine->getScreenWidth(); //800
    windowRect.top = 0;
    windowRect.bottom = g_engine->getScreenHeight(); //600

这里是 DefWindowProc

LRESULT CALLBACK WndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)

if(msg == WM_DESTROY)
    return DefWindowProc(hWnd, msg, wParam, lParam);

【问题讨论】:

你有没有错误使用GetLastErrortitle 是否会在整个程序中继续存在,以使 title.c_str() 不会成为悬空指针? 如你所见,我在关键操作之前/之后写日志。我的日志文件什么也没显示,我已经调试了代码,并且 title.c_str() 似乎在 CreateWindowExW 期间存在。 您是否在 WinProc 中调用 DefWndProc 返回对应的 LRESULT?创建失败主要是由于 WM_NCCREATE 返回 false 而不是 true windowRect 在哪里定义,在调用AdjustWindowRectEx() 之前它包含什么值? 那是你的真实WndProc()吗?那么@Emilio 是对的,你的编译器应该(至少)警告你并非所有的代码路径都返回一个值。 【参考方案1】:

我遇到这个问题的大部分时间是来自WinProc 的错误返回值。

您的WinProc 可能会调用DefWndProc 而不返回其返回值。 这使得 WM_NCCREATE 被视为返回 false(而不是应该返回的 true),从而导致创建过程停止。

一个合适的windowproc应该是

LRESULT CALLBACK WndProc (HWND h, UINT u, WPARAM w, LPARAM l)

  if(...) 
  else if(...) 
  else if(...)  //prematurely return if you don't want the default behavior

  return DefWndProc(h,u,w,l);

【讨论】:

【参考方案2】:

你的 wndProc 看起来不对:

if(msg == WM_DESTROY) // <-- you should remove it and let system handle default messages 
    return DefWindowProc(hWnd, msg, wParam, lParam);

【讨论】:

以上是关于无法使用 WinAPI 显示窗口的主要内容,如果未能解决你的问题,请参考以下文章

WinAPI 鼠标点击无法正常工作

WINAPI 窗口不工作。 [关闭]

winapi查找网页对话框的子窗口标题(属性)

如何使用纯 WINAPI 在渐变背景上显示控件?

无法加载多个位图 - WinAPI [重复]

使用 gdi 在 winapi 窗口中的运行时更新颜色