我正在尝试创建一个演示,其中窗口框架在其自己的类中处理并在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();
}
究竟是什么原因导致窗口无法显示?我是面向对象编程的初学者,所以我认为这个问题在哪里,但我无法弄明白,任何帮助都会受到赞赏。
答案 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/GetWindowLongPtr
和GWLP_USERDATA
来存储和检索静态WndProc中的this
指针,以便它可以调用非静态类方法。