fix: the problem of window message loop blocking main loop

This commit is contained in:
Haibo 2018-11-19 17:56:17 +08:00 committed by Nomango
parent 523262866a
commit 91508fd7cf
10 changed files with 260 additions and 254 deletions

View File

@ -19,17 +19,17 @@
// THE SOFTWARE. // THE SOFTWARE.
#include "Game.h" #include "Game.h"
#include "Scene.h"
#include "Transition.h"
#include "Image.h"
#include "../utils/Player.h"
#include "../math/Matrix.hpp"
#include "logs.h" #include "logs.h"
#include "render.h" #include "render.h"
#include "input.h" #include "input.h"
#include "audio.h" #include "audio.h"
#include "modules.h" #include "modules.h"
#include "Scene.h"
#include "Transition.h"
#include "../math/Matrix.hpp"
#include <thread> #include <thread>
#include <imm.h>
#pragma comment (lib ,"imm32.lib")
namespace easy2d namespace easy2d
{ {
@ -40,6 +40,8 @@ namespace easy2d
, transition_(nullptr) , transition_(nullptr)
, debug_enabled_(false) , debug_enabled_(false)
, initialized_(false) , initialized_(false)
, hwnd_(nullptr)
, window_inactived_(false)
{ {
::CoInitialize(nullptr); ::CoInitialize(nullptr);
} }
@ -62,26 +64,41 @@ namespace easy2d
debug_enabled_ = options.debug; debug_enabled_ = options.debug;
Window::Instance()->Init(options.title, options.width, options.height, options.icon, debug_enabled_); Window::Instance()->Init(
devices::Graphics::Instance()->Init(Window::Instance()->GetHandle(), debug_enabled_); options.title,
devices::Input::Instance()->Init(debug_enabled_); options.width,
options.height,
options.icon,
Game::WndProc,
debug_enabled_
);
const auto window = Window::Instance();
hwnd_ = window->GetHandle();
::SetWindowLongW(hwnd_, GWLP_USERDATA, PtrToUlong(this));
devices::Graphics::Instance()->Init(hwnd_, debug_enabled_);
devices::Input::Instance()->Init(hwnd_, window->GetContentScaleX(), window->GetContentScaleY(), debug_enabled_);
devices::Audio::Instance()->Init(debug_enabled_); devices::Audio::Instance()->Init(debug_enabled_);
// disable imm
::ImmAssociateContext(hwnd_, nullptr);
HWND console = ::GetConsoleWindow(); HWND console = ::GetConsoleWindow();
if (debug_enabled_) if (debug_enabled_)
{ {
if (console == nullptr) if (console == nullptr)
{ {
// 显示一个新控制台
if (::AllocConsole()) if (::AllocConsole())
{ {
console = ::GetConsoleWindow(); console = ::GetConsoleWindow();
// 重定向输入输出
FILE * stdoutStream, *stdinStream, *stderrStream; FILE * stdoutStream, *stdinStream, *stderrStream;
freopen_s(&stdoutStream, "conout$", "w+t", stdout); freopen_s(&stdoutStream, "conout$", "w+t", stdout);
freopen_s(&stdinStream, "conin$", "r+t", stdin); freopen_s(&stdinStream, "conin$", "r+t", stdin);
freopen_s(&stderrStream, "conout$", "w+t", stderr); freopen_s(&stderrStream, "conout$", "w+t", stderr);
// 禁用控制台关闭按钮
// disable the close button of console
HMENU hmenu = ::GetSystemMenu(console, FALSE); HMENU hmenu = ::GetSystemMenu(console, FALSE);
::RemoveMenu(hmenu, SC_CLOSE, MF_BYCOMMAND); ::RemoveMenu(hmenu, SC_CLOSE, MF_BYCOMMAND);
} }
@ -95,12 +112,6 @@ namespace easy2d
} }
} }
::SetWindowLongPtrW(
Window::Instance()->GetHandle(),
GWLP_USERDATA,
PtrToUlong(this)
);
initialized_ = true; initialized_ = true;
} }
@ -115,46 +126,14 @@ namespace easy2d
next_scene_ = nullptr; next_scene_ = nullptr;
} }
const auto window = Window::Instance(); ::ShowWindow(hwnd_, SW_SHOWNORMAL);
::ShowWindow(window->GetHandle(), SW_SHOWNORMAL); ::UpdateWindow(hwnd_);
::UpdateWindow(window->GetHandle());
window->Poll();
const int64_t min_interval = 5; MSG msg = {};
auto last = time::Now(); while (::GetMessageW(&msg, nullptr, 0, 0) && !quit_)
while (!quit_)
{ {
auto now = time::Now(); ::TranslateMessage(&msg);
auto dur = now - last; ::DispatchMessageW(&msg);
if (dur.Milliseconds() > min_interval)
{
const auto dt = now - last;
last = now;
devices::Input::Instance()->Update(
window->GetHandle(),
window->GetContentScaleX(),
window->GetContentScaleY()
);
UpdateScene(dt);
DrawScene();
window->Poll();
}
else
{
// ID2D1HwndRenderTarget 开启了垂直同步,在渲染时会等待显示器刷新,
// 它起到了非常稳定的延时作用,所以大部分时候不需要手动挂起线程进行延时。
// 下面的代码仅在一些情况下(例如窗口最小化时)挂起线程,防止占用过高 CPU 。
int64_t wait = min_interval - dur.Milliseconds();
if (wait > 1LL)
{
std::this_thread::sleep_for(std::chrono::milliseconds(wait));
}
}
} }
} }
@ -201,30 +180,30 @@ namespace easy2d
return curr_scene_; return curr_scene_;
} }
void Game::UpdateScene(Duration const& dt) void Game::Update()
{ {
static auto last = time::Now();
const auto now = time::Now();
const auto dt = now - last;
last = now;
devices::Input::Instance()->Update();
if (curr_scene_) if (curr_scene_)
{
curr_scene_->Update(dt); curr_scene_->Update(dt);
}
if (next_scene_) if (next_scene_)
{
next_scene_->Update(dt); next_scene_->Update(dt);
}
if (transition_) if (transition_)
{ {
transition_->Update(dt); transition_->Update(dt);
if (transition_->IsDone()) if (transition_->IsDone())
{
transition_ = nullptr; transition_ = nullptr;
}
else else
{
return; return;
}
} }
if (next_scene_) if (next_scene_)
@ -241,32 +220,14 @@ namespace easy2d
} }
} }
void Game::Dispatch(MouseEvent const & e) void Game::Render()
{
if (transition_)
return;
if (curr_scene_)
curr_scene_->Dispatch(e, false);
}
void Game::Dispatch(KeyEvent const & e)
{
if (transition_)
return;
if (curr_scene_)
curr_scene_->Dispatch(e, false);
}
void Game::DrawScene()
{ {
auto graphics = devices::Graphics::Instance(); auto graphics = devices::Graphics::Instance();
graphics->BeginDraw(Window::Instance()->GetHandle()); graphics->BeginDraw(hwnd_);
if (transition_) if (transition_)
{ {
transition_->Draw(); transition_->Render();
} }
else if (curr_scene_) else if (curr_scene_)
{ {
@ -292,5 +253,134 @@ namespace easy2d
} }
graphics->EndDraw(); graphics->EndDraw();
if (!window_inactived_)
::InvalidateRect(hwnd_, NULL, FALSE);
}
void Game::Dispatch(MouseEvent const & e)
{
if (transition_)
return;
if (curr_scene_)
curr_scene_->Dispatch(e, false);
}
void Game::Dispatch(KeyEvent const & e)
{
if (transition_)
return;
if (curr_scene_)
curr_scene_->Dispatch(e, false);
}
LRESULT CALLBACK Game::WndProc(HWND hwnd, UINT msg, WPARAM w_param, LPARAM l_param)
{
LRESULT result = 0;
bool was_handled = false;
Game * game = reinterpret_cast<Game*>(
static_cast<LONG_PTR>(::GetWindowLongW(hwnd, GWLP_USERDATA))
);
switch (msg)
{
case WM_PAINT:
{
PAINTSTRUCT ps;
::BeginPaint(hwnd, &ps);
game->Update();
game->Render();
::EndPaint(hwnd, &ps);
}
result = 0;
was_handled = true;
break;
case WM_LBUTTONUP:
case WM_LBUTTONDOWN:
case WM_LBUTTONDBLCLK:
case WM_MBUTTONUP:
case WM_MBUTTONDOWN:
case WM_MBUTTONDBLCLK:
case WM_RBUTTONUP:
case WM_RBUTTONDOWN:
case WM_RBUTTONDBLCLK:
case WM_MOUSEMOVE:
case WM_MOUSEWHEEL:
{
game->Dispatch(MouseEvent(msg, w_param, l_param));
}
result = 0;
was_handled = true;
break;
case WM_KEYDOWN:
case WM_KEYUP:
{
game->Dispatch(KeyEvent(msg, w_param, l_param));
}
result = 0;
was_handled = true;
break;
case WM_SIZE:
{
if (SIZE_MAXHIDE == w_param || SIZE_MINIMIZED == w_param)
game->window_inactived_ = true;
else
{
game->window_inactived_ = false;
::InvalidateRect(hwnd, nullptr, FALSE);
}
UINT width = LOWORD(l_param);
UINT height = HIWORD(l_param);
// 如果程序接收到一个 WM_SIZE 消息,这个方法将调整渲染
// 目标的大小。它可能会调用失败,但是这里可以忽略有可能的
// 错误,因为这个错误将在下一次调用 EndDraw 时产生
devices::Graphics::Instance()->Resize(width, height);
}
break;
case WM_DISPLAYCHANGE:
{
::InvalidateRect(hwnd, nullptr, FALSE);
}
result = 0;
was_handled = true;
break;
case WM_CLOSE:
{
if (game->OnClose())
{
game->Quit();
}
}
result = 0;
was_handled = true;
break;
case WM_DESTROY:
{
::PostQuitMessage(0);
}
result = 1;
was_handled = true;
break;
}
if (!was_handled)
{
result = ::DefWindowProcW(hwnd, msg, w_param, l_param);
}
return result;
} }
} }

View File

@ -89,11 +89,10 @@ namespace easy2d
// »ñÈ¡µ±Ç°³¡¾° // »ñÈ¡µ±Ç°³¡¾°
spScene const& GetCurrentScene(); spScene const& GetCurrentScene();
void DrawScene(); private:
void Render();
void UpdateScene( void Update();
Duration const& dt
);
void Dispatch( void Dispatch(
MouseEvent const& e MouseEvent const& e
@ -103,10 +102,14 @@ namespace easy2d
KeyEvent const& e KeyEvent const& e
); );
static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
private: private:
bool initialized_; bool initialized_;
bool debug_enabled_; bool debug_enabled_;
bool quit_; bool quit_;
bool window_inactived_;
HWND hwnd_;
spScene curr_scene_; spScene curr_scene_;
spScene next_scene_; spScene next_scene_;
spTransition transition_; spTransition transition_;

View File

@ -28,6 +28,9 @@ namespace easy2d
{ {
InputDevice::InputDevice() InputDevice::InputDevice()
: initialized(false) : initialized(false)
, hwnd_(nullptr)
, scale_x_(1.f)
, scale_y_(1.f)
{ {
ZeroMemory(keys_, sizeof(keys_)); ZeroMemory(keys_, sizeof(keys_));
ZeroMemory(keys_cache_, sizeof(keys_cache_)); ZeroMemory(keys_cache_, sizeof(keys_cache_));
@ -38,26 +41,30 @@ namespace easy2d
E2D_LOG("Destroying input device"); E2D_LOG("Destroying input device");
} }
void InputDevice::Init(bool debug) void InputDevice::Init(HWND hwnd, float scale_x, float scale_y, bool debug)
{ {
if (initialized) if (initialized)
return; return;
E2D_LOG("Initing input device"); E2D_LOG("Initing input device");
hwnd_ = hwnd;
scale_x_ = scale_x;
scale_y_ = scale_y;
initialized = true; initialized = true;
} }
void InputDevice::Update(HWND hwnd, float scale_x, float scale_y) void InputDevice::Update()
{ {
memcpy(keys_cache_, keys_, sizeof(keys_cache_)); memcpy(keys_cache_, keys_, sizeof(keys_cache_));
GetKeyboardState(keys_); GetKeyboardState(keys_);
POINT client_cursor_pos; POINT client_cursor_pos;
GetCursorPos(&client_cursor_pos); GetCursorPos(&client_cursor_pos);
ScreenToClient(hwnd, &client_cursor_pos); ScreenToClient(hwnd_, &client_cursor_pos);
mouse_pos_ = Point(client_cursor_pos.x * scale_x, client_cursor_pos.y * scale_y); mouse_pos_ = Point(client_cursor_pos.x * scale_x_, client_cursor_pos.y * scale_y_);
} }
bool InputDevice::IsDown(KeyCode code) bool InputDevice::IsDown(KeyCode code)

View File

@ -32,7 +32,7 @@ namespace easy2d
E2D_DECLARE_SINGLETON(InputDevice); E2D_DECLARE_SINGLETON(InputDevice);
public: public:
void Init(bool debug); void Init(HWND hwnd, float scale_x, float scale_y, bool debug);
// 检测键盘某按键是否正被按下 // 检测键盘某按键是否正被按下
bool IsDown( bool IsDown(
@ -63,12 +63,7 @@ namespace easy2d
// 获得鼠标坐标值 // 获得鼠标坐标值
Point GetMousePos(); Point GetMousePos();
// 刷新设备状态 void Update();
void Update(
HWND hwnd,
float scale_x,
float scale_y
);
protected: protected:
InputDevice(); InputDevice();
@ -76,10 +71,13 @@ namespace easy2d
~InputDevice(); ~InputDevice();
protected: protected:
bool initialized; bool initialized;
BYTE keys_[256]; HWND hwnd_;
BYTE keys_cache_[256]; float scale_x_;
Point mouse_pos_; float scale_y_;
BYTE keys_[256];
BYTE keys_cache_[256];
Point mouse_pos_;
}; };
E2D_DECLARE_SINGLETON_TYPE(InputDevice, Input); E2D_DECLARE_SINGLETON_TYPE(InputDevice, Input);

View File

@ -99,7 +99,7 @@ namespace easy2d
} }
} }
void Transition::Draw() void Transition::Render()
{ {
auto graphics = devices::Graphics::Instance(); auto graphics = devices::Graphics::Instance();

View File

@ -49,7 +49,7 @@ namespace easy2d
virtual void Update(Duration const& dt); virtual void Update(Duration const& dt);
virtual void Draw(); virtual void Render();
virtual void Stop(); virtual void Stop();

View File

@ -35,6 +35,7 @@ namespace easy2d
, fps_text_layout_(nullptr) , fps_text_layout_(nullptr)
, clear_color_(D2D1::ColorF(D2D1::ColorF::Black)) , clear_color_(D2D1::ColorF(D2D1::ColorF::Black))
, opacity_(1.f) , opacity_(1.f)
, window_occluded(false)
, initialized(false) , initialized(false)
{ {
ZeroMemory(&d2d, sizeof(D2DResources)); ZeroMemory(&d2d, sizeof(D2DResources));
@ -130,28 +131,36 @@ namespace easy2d
{ {
CreateDeviceResources(hwnd); CreateDeviceResources(hwnd);
d2d.render_target->BeginDraw(); window_occluded = !!(d2d.render_target->CheckWindowState() & D2D1_WINDOW_STATE_OCCLUDED);
d2d.render_target->Clear(clear_color_);
if (!window_occluded)
{
d2d.render_target->BeginDraw();
d2d.render_target->Clear(clear_color_);
}
} }
void GraphicsDevice::EndDraw() void GraphicsDevice::EndDraw()
{ {
HRESULT hr = d2d.render_target->EndDraw(); if (!window_occluded)
if (hr == D2DERR_RECREATE_TARGET)
{ {
// 如果 Direct3D 设备在执行过程中消失,将丢弃当前的设备相关资源 HRESULT hr = d2d.render_target->EndDraw();
// 并在下一次调用时重建资源
hr = S_OK;
fps_text_format_ = nullptr; if (hr == D2DERR_RECREATE_TARGET)
fps_text_layout_ = nullptr; {
d2d.text_renderer = nullptr; // 如果 Direct3D 设备在执行过程中消失,将丢弃当前的设备相关资源
d2d.solid_brush = nullptr; // 并在下一次调用时重建资源
d2d.render_target = nullptr; hr = S_OK;
fps_text_format_ = nullptr;
fps_text_layout_ = nullptr;
d2d.text_renderer = nullptr;
d2d.solid_brush = nullptr;
d2d.render_target = nullptr;
}
ThrowIfFailed(hr);
} }
ThrowIfFailed(hr);
} }
void GraphicsDevice::ClearImageCache() void GraphicsDevice::ClearImageCache()
@ -375,6 +384,9 @@ namespace easy2d
!d2d.render_target) !d2d.render_target)
return E_UNEXPECTED; return E_UNEXPECTED;
if (window_occluded)
return S_OK;
d2d.solid_brush->SetColor(border_color); d2d.solid_brush->SetColor(border_color);
d2d.render_target->DrawGeometry( d2d.render_target->DrawGeometry(
geometry.Get(), geometry.Get(),
@ -393,6 +405,9 @@ namespace easy2d
if (!image->GetBitmap()) if (!image->GetBitmap())
return S_OK; return S_OK;
if (window_occluded)
return S_OK;
d2d.render_target->DrawBitmap( d2d.render_target->DrawBitmap(
image->GetBitmap().Get(), image->GetBitmap().Get(),
D2D1::RectF(0.f, 0.f, image->GetWidth(), image->GetHeight()), D2D1::RectF(0.f, 0.f, image->GetWidth(), image->GetHeight()),
@ -427,6 +442,9 @@ namespace easy2d
if (!d2d.render_target) if (!d2d.render_target)
return E_UNEXPECTED; return E_UNEXPECTED;
if (window_occluded)
return S_OK;
// Do not crop bitmap // Do not crop bitmap
auto rect = D2D1::RectF(0.f, 0.f, bitmap->GetSize().width, bitmap->GetSize().height); auto rect = D2D1::RectF(0.f, 0.f, bitmap->GetSize().width, bitmap->GetSize().height);
d2d.render_target->DrawBitmap( d2d.render_target->DrawBitmap(
@ -444,6 +462,9 @@ namespace easy2d
if (!d2d.text_renderer) if (!d2d.text_renderer)
return E_UNEXPECTED; return E_UNEXPECTED;
if (window_occluded)
return S_OK;
return text_layout->Draw(nullptr, d2d.text_renderer.Get(), 0, 0); return text_layout->Draw(nullptr, d2d.text_renderer.Get(), 0, 0);
} }
@ -452,6 +473,9 @@ namespace easy2d
if (!d2d.render_target) if (!d2d.render_target)
return E_UNEXPECTED; return E_UNEXPECTED;
if (window_occluded)
return S_OK;
d2d.render_target->SetTransform(ConvertToD2DMatrix(clip_matrix)); d2d.render_target->SetTransform(ConvertToD2DMatrix(clip_matrix));
d2d.render_target->PushAxisAlignedClip( d2d.render_target->PushAxisAlignedClip(
D2D1::RectF(0, 0, clip_size.width, clip_size.height), D2D1::RectF(0, 0, clip_size.width, clip_size.height),
@ -465,6 +489,9 @@ namespace easy2d
if (!d2d.render_target) if (!d2d.render_target)
return E_UNEXPECTED; return E_UNEXPECTED;
if (window_occluded)
return S_OK;
d2d.render_target->PopAxisAlignedClip(); d2d.render_target->PopAxisAlignedClip();
return S_OK; return S_OK;
} }
@ -475,6 +502,9 @@ namespace easy2d
!d2d.solid_brush) !d2d.solid_brush)
return E_UNEXPECTED; return E_UNEXPECTED;
if (window_occluded)
return S_OK;
d2d.render_target->PushLayer( d2d.render_target->PushLayer(
D2D1::LayerParameters( D2D1::LayerParameters(
properties.area, properties.area,
@ -495,6 +525,9 @@ namespace easy2d
if (!d2d.render_target) if (!d2d.render_target)
return E_UNEXPECTED; return E_UNEXPECTED;
if (window_occluded)
return S_OK;
d2d.render_target->PopLayer(); d2d.render_target->PopLayer();
return S_OK; return S_OK;
} }

View File

@ -194,6 +194,7 @@ namespace easy2d
protected: protected:
bool initialized; bool initialized;
bool window_occluded;
float opacity_; float opacity_;
D2DResources d2d; D2DResources d2d;
D2D1_COLOR_F clear_color_; D2D1_COLOR_F clear_color_;

View File

@ -21,12 +21,7 @@
#include "window.h" #include "window.h"
#include "render.h" #include "render.h"
#include "logs.h" #include "logs.h"
#include "Game.h"
#include "KeyEvent.h"
#include "MouseEvent.h"
#include "../math/scalar.hpp" #include "../math/scalar.hpp"
#include <imm.h>
#pragma comment (lib ,"imm32.lib")
#define WINDOW_STYLE WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX & ~WS_THICKFRAME #define WINDOW_STYLE WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX & ~WS_THICKFRAME
#define REGISTER_CLASS L"Easy2DApp" #define REGISTER_CLASS L"Easy2DApp"
@ -38,8 +33,6 @@ namespace easy2d
void GetContentScale(float* scale_x, float* scale_y); void GetContentScale(float* scale_x, float* scale_y);
Rect LocateWindow(int width, int height, float scale_x, float scale_y); Rect LocateWindow(int width, int height, float scale_x, float scale_y);
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM w_param, LPARAM l_param);
} }
WindowImpl::WindowImpl() WindowImpl::WindowImpl()
@ -58,7 +51,7 @@ namespace easy2d
::DestroyWindow(handle); ::DestroyWindow(handle);
} }
void WindowImpl::Init(String title, int width, int height, LPCWSTR icon, bool debug) void WindowImpl::Init(String title, int width, int height, LPCWSTR icon, WNDPROC proc, bool debug)
{ {
if (initialized) if (initialized)
return; return;
@ -70,7 +63,7 @@ namespace easy2d
wcex.cbSize = sizeof(WNDCLASSEX); wcex.cbSize = sizeof(WNDCLASSEX);
wcex.lpszClassName = REGISTER_CLASS; wcex.lpszClassName = REGISTER_CLASS;
wcex.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; wcex.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
wcex.lpfnWndProc = WndProc; wcex.lpfnWndProc = proc;
wcex.hIcon = nullptr; wcex.hIcon = nullptr;
wcex.cbClsExtra = 0; wcex.cbClsExtra = 0;
wcex.cbWndExtra = sizeof(LONG_PTR); wcex.cbWndExtra = sizeof(LONG_PTR);
@ -123,9 +116,6 @@ namespace easy2d
throw std::runtime_error(err); throw std::runtime_error(err);
} }
// 禁用输入法
::ImmAssociateContext(handle, nullptr);
initialized = true; initialized = true;
} }
@ -220,17 +210,6 @@ namespace easy2d
return scale_y; return scale_y;
} }
void WindowImpl::Poll()
{
static MSG msg = {};
while (::PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
}
namespace namespace
{ {
void GetContentScale(float* scale_x, float* scale_y) void GetContentScale(float* scale_x, float* scale_y)
@ -276,109 +255,5 @@ namespace easy2d
static_cast<float>(height) static_cast<float>(height)
); );
} }
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM w_param, LPARAM l_param)
{
LRESULT result = 0;
bool was_handled = false;
Game * game = reinterpret_cast<Game*>(
static_cast<LONG_PTR>(::GetWindowLongPtrW(hwnd, GWLP_USERDATA))
);
switch (msg)
{
// 处理鼠标消息
case WM_LBUTTONUP:
case WM_LBUTTONDOWN:
case WM_LBUTTONDBLCLK:
case WM_MBUTTONUP:
case WM_MBUTTONDOWN:
case WM_MBUTTONDBLCLK:
case WM_RBUTTONUP:
case WM_RBUTTONDOWN:
case WM_RBUTTONDBLCLK:
case WM_MOUSEMOVE:
case WM_MOUSEWHEEL:
{
game->Dispatch(MouseEvent(msg, w_param, l_param));
}
result = 0;
was_handled = true;
break;
// 处理按键消息
case WM_KEYDOWN:
case WM_KEYUP:
{
game->Dispatch(KeyEvent(msg, w_param, l_param));
}
result = 0;
was_handled = true;
break;
// 处理窗口大小变化消息
case WM_SIZE:
{
UINT width = LOWORD(l_param);
UINT height = HIWORD(l_param);
// 如果程序接收到一个 WM_SIZE 消息,这个方法将调整渲染
// 目标的大小。它可能会调用失败,但是这里可以忽略有可能的
// 错误,因为这个错误将在下一次调用 EndDraw 时产生
devices::Graphics::Instance()->Resize(width, height);
}
break;
// 处理分辨率变化消息
case WM_DISPLAYCHANGE:
{
// 重绘客户区
::InvalidateRect(hwnd, nullptr, FALSE);
}
result = 0;
was_handled = true;
break;
// 重绘窗口
case WM_PAINT:
{
game->DrawScene();
::ValidateRect(hwnd, nullptr);
}
result = 0;
was_handled = true;
break;
// 窗口关闭消息
case WM_CLOSE:
{
if (game->OnClose())
{
game->Quit();
}
}
result = 0;
was_handled = true;
break;
// 窗口销毁消息
case WM_DESTROY:
{
::PostQuitMessage(0);
}
result = 1;
was_handled = true;
break;
}
if (!was_handled)
{
result = ::DefWindowProc(hwnd, msg, w_param, l_param);
}
return result;
}
} }
} }

View File

@ -35,6 +35,7 @@ namespace easy2d
int width, int width,
int height, int height,
LPCWSTR icon, LPCWSTR icon,
WNDPROC proc,
bool debug bool debug
); );
@ -65,18 +66,16 @@ namespace easy2d
float GetContentScaleY() const; float GetContentScaleY() const;
void Poll();
protected: protected:
WindowImpl(); WindowImpl();
~WindowImpl(); ~WindowImpl();
private: private:
bool initialized; bool initialized;
HWND handle; HWND handle;
float scale_x; float scale_x;
float scale_y; float scale_y;
}; };
E2D_DECLARE_SINGLETON_TYPE(WindowImpl, Window); E2D_DECLARE_SINGLETON_TYPE(WindowImpl, Window);