WinApi c ++窗口不会出现oop

时间:2017-05-03 14:56:32

标签: windows oop winapi visual-c++

我正在尝试创建一个演示,其中窗口框架在其自己的类中处理并在WinMain文件中调用,我有main.cpp和window.h以及window.cpp,代码编译成功,但窗口将尽管在系统托盘中弹出了我在main.cpp中传递的窗口标题但是没有出现,这里是整个代码:

main.cpp中:

#include <Windows.h>
#include "window.h"


window* WinapiInit = new window;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE PrevhInstance, LPSTR 
lpCmdLine, int nCmdShow)
{
WinapiInit->initWindow(hInstance, 800, 600, L"DirectX 12 Demo", nCmdShow);

delete WinapiInit;

return 0;
}

window.h中

#pragma once
#include <Windows.h>

class window
{

private:
LPCWSTR m_WindowTitle;
const LPCTSTR m_WindowClassName = L"WindowClass1";

int m_WindowWidth;
int m_WindowHeight;
const int m_ScreenPosX = GetSystemMetrics(SM_CXSCREEN);
const int m_ScreenPosY = GetSystemMetrics(SM_CYSCREEN);


HWND hWnd;
WNDCLASSEX wcex;
MSG msg;

public:
void initWindow(HINSTANCE hInstance, int WindowWidth, int WindowHeight, 
LPCWSTR WindowTitle, int nCmdShow);
static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM 
lParam);
void mainLoop();

};

window.cpp

#include "window.h"


LRESULT window::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
 case WM_DESTROY:
    PostQuitMessage(0);
    ExitProcess(0);
    break;
default:
    return DefWindowProc(hWnd, uMsg, wParam, lParam);
    break;
}
return 0;
}

void window::mainLoop()
{
msg = { 0 };
while (WM_QUIT != msg.message)
{
    if (PeekMessage(&msg, hWnd, 0, 0, PM_REMOVE))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    //GAME CODE HERE
    //...

}
}

void window::initWindow(const HINSTANCE hInstance,  int WindowWidth,  int 
WindowHeight, LPCWSTR WindowTitle, const int nCmdShow)
{

m_WindowWidth = WindowWidth;
m_WindowHeight = WindowHeight;
m_WindowTitle = WindowTitle;

wcex = { 0 };
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 3);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hIcon = LoadIcon(hInstance, IDI_APPLICATION);
wcex.hIconSm = LoadIcon(hInstance, IDI_APPLICATION);
wcex.hInstance = hInstance;
wcex.lpfnWndProc = window::WndProc;
wcex.lpszMenuName = nullptr;
wcex.lpszClassName = m_WindowClassName;
wcex.style = CS_HREDRAW | CS_VREDRAW;

if (!RegisterClassEx(&wcex))
{
    MessageBox(NULL, L"RegisterClassEx Call Error!", L"ERROR" , MB_OK | 
    MB_ICONERROR);
}

hWnd = CreateWindowEx(NULL, m_WindowClassName, WindowTitle,
                      WS_OVERLAPPEDWINDOW, m_ScreenPosX, m_ScreenPosY, 
WindowWidth,
                      WindowHeight, NULL, NULL, hInstance, NULL);

if (!hWnd)
{
    MessageBox(NULL, L"CreateWindowEx Call Error!", L"ERROR", MB_OK | 
    MB_ICONERROR);
}

ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);

mainLoop();

}

究竟是什么原因导致窗口无法显示?我是面向对象编程的初学者,所以我认为这个问题在哪里,但我无法弄明白,任何帮助都会受到赞赏。

1 个答案:

答案 0 :(得分:1)

这里有很多错误,因为你设法使一个简单的应用程序非常复杂,因此很难调试,

关于您的问题最关键的是,您使用系统度量标准SM_CXSCREEN和SM_CYSCREEN初始化m_ScreenPosX和m_ScreenPosY - 根据定义,该窗口已定位在桌面的可见区域之外。

因为它看起来应该发展成为一个DirectX应用程序,你可能想要使用0,0作为位置,以及主要显示器的尺寸(在多显示器系统上将不是SM_CXSCREEN ,SM_CYSCREEN)将窗口定位在主显示屏上。

但在短期内,CW_USEDEFAULT将是用于初始开发的合理位置值。

下一个最关键的错误来源是您将消息循环包含在窗口类中。大多数 - 如果不是全部 - 用于Windows开发的OOP框架分开&#34; window&#34;来自&#34; application&#34;,即使只有一个应用程序窗口。这意味着应用程序对象拥有消息循环,并且它永远不会被hWnd过滤:发布到应用程序的消息(例如WM_QUIT)不会发送到HWND,这可能是你的WM_DESTROY处理程序也调用ExitProcess的原因。删除对ExitProcess的调用,并删除hWnd过滤,PostQuitMessage()将导致您的应用程序干净地终止。

最后,除非你只想存储一个窗口类的单例(因为游戏窗口不太可能会导致问题),你很快就会把你的整个窗口类实现为静态方法。 通常的方法是使用SetWindowLongPtr/GetWindowLongPtrGWLP_USERDATA来存储和检索静态WndProc中的this指针,以便它可以调用非静态类方法。