infine windows消息循环-c++
infine windows message loop - c++
我试图创建这个窗口类,它创建并显示一个窗口。当我运行这个类时,GetMessage会继续发送WM_PAINT消息,任务管理器会向我显示仅来自进程的大约50%的CPU使用率。
main.cpp:
#include "Window.h"
int WINAPI WinMain(
HINSTANCE /* hInstance */,
HINSTANCE /* hPrevInstance */,
LPSTR /* lpCmdLine */,
int /* nCmdShow */
)
{
Window::GlobalInitialize();
Window window(L"abcd", 500, 500);
if (SUCCEEDED(window.Initialize()))
window.RunMessageLoop();
Window::GlobalTerminate();
return 0;
}
窗口.h:
#ifndef WINDOW_HEADER
#define WINDOW_HEADER
#include <Windows.h>
#include <functional>
#pragma comment(lib, "d2d1.lib")
class Window;
typedef std::function<void(Window *window, UINT id, LPCWSTR message)> ErrorCallback;
class Window {
public:
#define ERROR_FAILED_HINSTANCE 1
#define ERROR_FAILED_HINSTANCE_STR L"Failed to retrieve hInstance"
#define ERROR_FAILED_REGISTER 2
#define ERROR_FAILED_REGISTER_STR L"Failed to register window class"
#define ERROR_FAILED_CREATION 3
#define ERROR_FAILED_CREATION_STR L"Failed to create window"
typedef std::function<HRESULT(Window *window)> WEOnCreate;
typedef std::function<HRESULT(Window *window)> WEOnDestroy;
typedef std::function<HRESULT(Window *window)> WEOnRender;
typedef std::function<HRESULT(Window *window, UINT width, UINT height)> WEOnResize;
typedef std::function<HRESULT(Window *window, UINT horizontalResolution, UINT verticalResolution)> WEOnScreenResolutionChange;
Window(LPCWSTR title, UINT width, UINT height);
~Window();
HRESULT SetSize(UINT width, UINT height);
HRESULT SetTitle(LPCWSTR title);
inline UINT GetWidth() { return _width; }
inline UINT GetHeight() { return _height; }
inline LPCWSTR GetTitle() { return _title; }
inline HWND GetHandle() { return hWnd; }
inline void SetOnCreateCallback(WEOnCreate fun) { _onCreate = fun; }
inline void SetOnDestroyCallback(WEOnDestroy fun) { _onDestroy = fun; }
inline void SetOnRenderCallback(WEOnRender fun) { _onRender = fun; }
inline void SetOnResizeCallback(WEOnResize fun) { _onResize = fun; }
inline void SetOnScreenResolutionChangeCallback(WEOnScreenResolutionChange fun) { _onResChange = fun; }
inline void SetExtraAllocatedSpace(void *ptr) { extra = ptr; }
inline void *GetExtraAllocatedSpace() { return extra; }
inline void Terminate() { if (hWnd) DestroyWindow(hWnd); }
static inline void SetErrorCallback(ErrorCallback fun) { _errorCallback = fun; }
HRESULT Initialize();
void RunMessageLoop();
static HRESULT GlobalInitialize();
static HRESULT GlobalTerminate();
private:
static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
static inline void throwError(Window *window, UINT id, LPCWSTR message) {
if (_errorCallback)
_errorCallback(window, id, message);
}
WEOnCreate _onCreate;
WEOnDestroy _onDestroy;
WEOnRender _onRender;
WEOnResize _onResize;
WEOnScreenResolutionChange _onResChange;
static ErrorCallback _errorCallback;
static LPCWSTR szClassName;
static HINSTANCE hInstance;
HWND hWnd;
int _width, _height;
LPCWSTR _title;
void *extra;
};
#endif
Window.cpp:
#include "Window.h"
//Initialize static variables
ErrorCallback Window::_errorCallback = nullptr;
LPCWSTR Window::szClassName = L"WindowClass";
HINSTANCE Window::hInstance;
Window::Window(LPCWSTR title = L"Window", UINT width = 640, UINT height = 480) :
_onCreate(nullptr),
_onDestroy(nullptr),
_onRender(nullptr),
_onResize(nullptr),
hWnd(NULL),
extra(NULL),
_width(width),
_height(height),
_title(title) {}
Window::~Window() {
if (hWnd) {
DestroyWindow(hWnd);
hWnd = NULL;
}
}
HRESULT Window::GlobalInitialize() {
// Retreive hInstance
hInstance = GetModuleHandle(NULL);
if (!hInstance) {
throwError(NULL, ERROR_FAILED_HINSTANCE, ERROR_FAILED_HINSTANCE_STR);
return E_FAIL;
}
// Create window class
WNDCLASSEX wcex = {};
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = Window::WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = sizeof(LONG_PTR);
wcex.hInstance = hInstance;
wcex.hbrBackground = NULL;
wcex.lpszMenuName = NULL;
wcex.hCursor = LoadCursor(NULL, IDI_APPLICATION);
wcex.lpszClassName = szClassName;
if (!RegisterClassEx(&wcex)) {
throwError(NULL, ERROR_FAILED_REGISTER, ERROR_FAILED_REGISTER_STR);
return E_FAIL;
}
return S_OK;
}
HRESULT Window::GlobalTerminate() {
if (UnregisterClass(szClassName, hInstance))
return S_OK;
else
return E_FAIL;
}
void Window::RunMessageLoop() {
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
HRESULT Window::Initialize() {
// Create the window
hWnd = CreateWindow(
szClassName,
_title,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
_width,
_height,
NULL,
NULL,
hInstance,
this
);
if (!hWnd) {
throwError(this, ERROR_FAILED_CREATION, ERROR_FAILED_CREATION_STR);
return E_FAIL;
}
// Show and render the window
ShowWindow(hWnd, SW_SHOW);
UpdateWindow(hWnd);
return S_OK;
}
LRESULT CALLBACK Window::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
if (message == WM_CREATE) {
LPCREATESTRUCT pcs = (LPCREATESTRUCT)lParam;
Window *window = (Window *)pcs->lpCreateParams;
::SetWindowLongPtr(hWnd, GWLP_USERDATA, PtrToUlong(window));
if (window->_onCreate != nullptr)
window->_onCreate(window);
}
Window *pWnd = reinterpret_cast<Window *>(static_cast<LONG_PTR>(GetWindowLongPtr(hWnd, GWLP_USERDATA)));
HRESULT hr = S_OK;
if (!pWnd) {
return DefWindowProc(hWnd, message, wParam, lParam);
}
switch (message) {
case WM_PAINT:
{
if (pWnd->_onRender)
hr = pWnd->_onRender(pWnd);
else
hr = S_OK;
}
break;
case WM_SIZE:
{
if (pWnd->_onResize)
hr = pWnd->_onResize(pWnd, LOWORD(lParam), HIWORD(lParam));
else
hr = S_OK;
}
break;
case WM_DISPLAYCHANGE:
{
if (pWnd->_onResChange)
hr = pWnd->_onResChange(pWnd, LOWORD(lParam), HIWORD(lParam));
else
hr = S_OK;
}
break;
case WM_DESTROY:
{
if (pWnd->_onDestroy && FAILED(pWnd->_onDestroy(pWnd)))
break;
}
PostQuitMessage(0);
hWnd = NULL;
break;
default:
hr = DefWindowProc(hWnd, message, wParam, lParam);
}
return hr;
}
HRESULT Window::SetSize(UINT width, UINT height) {
if (hWnd)
if (!::SetWindowPos(hWnd, 0, 0, 0, width, height, SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER))
return E_FAIL;
_width = width;
_height = height;
return S_OK;
}
HRESULT Window::SetTitle(LPCWSTR title) {
if (hWnd)
if (!::SetWindowText(hWnd, title))
return E_FAIL;
_title = title;
return S_OK;
}
我希望有人能帮助我,因为一切看起来都很好(窗户甚至开得很好)。
首先,您似乎将窗口过程视为COM方法,但窗口过程不会返回HRESULT
,而是返回LRESULT
,每个消息的含义不同。
在WM_PAINT
的情况下,不可能返回指示"我这次不需要绘画"的值。只要窗口的一部分被标记为脏,系统就会发送WM_PAINT
消息,而将脏区域标记为"已绘制"的方法是调用BeginPaint
和EndPaint
。如果您不这样做,系统将继续认为您的窗口是脏的,并继续发送WM_PAINT
消息。
您还没有显示_onRender
函数的源代码,但您将WM_PAINT
处理设置为可选的(即,如果没有任何调用SetOnRenderCallback
,则不会注册回调),这意味着您可能没有正确处理WM_PAINT
。至少,如果您不自己绘制,您应该将消息传递给DefWindowProc
,以便进行默认处理。
相关文章:
- 如何循环打印顶点结构
- 如何在C++中从两个单独的for循环中添加两个数组
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 正在尝试了解输入验证循环
- std::map<struct,struct>::find 找不到匹配项,但是如果我循环通过 begin() 到 end(),我在那里看到匹配项
- 循环后如何继续阅读
- Ardunio UNO解决了多个重叠的定时器循环
- Eigen如何在容器循环中干净地附加矩阵
- 在某些循环内使用vector.push_back时出现分段错误
- 我正在使用嵌套的while循环来解析具有多行的文本文件,但由于某种原因,它只通过第一行,我不知道为什么
- 为什么我的for循环不能正确获取argv
- 如何声明特征矩阵,然后通过嵌套循环初始化它
- while循环中while循环的时间复杂度是多少
- C++中的高效循环缓冲区,它将被传递给C样式数组函数参数
- 为什么在这个代码结束循环中没有得到结束
- 在基于范围的for循环中使用结构化绑定声明
- 用于C++中带有数组和指针的循环
- 循环中的随机函数
- 是什么阻止DOMTimerCoordinator::NextID进入无休止的循环
- 在循环C++中指定字符串之后,不会打印该字符串