Magpie/Runtime/App.cpp
2021-09-02 20:57:56 +08:00

156 lines
3.9 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "pch.h"
#include "App.h"
#include "Utils.h"
const UINT App::_WM_DESTORYHOST = RegisterWindowMessage(L"MAGPIE_WM_DESTORYHOST");
bool App::Initialize(
std::shared_ptr<spdlog::logger> logger,
HINSTANCE hInst,
HWND hwndSrc
) {
_logger = logger;
_hwndSrc = hwndSrc;
_hInst = hInst;
SPDLOG_LOGGER_INFO(logger, "正在初始化 App");
// 确保只初始化一次
static bool initalized = false;
if (!initalized) {
// 初始化 COM
HRESULT hr = Windows::Foundation::Initialize(RO_INIT_MULTITHREADED);
if (FAILED(hr)) {
SPDLOG_LOGGER_CRITICAL(logger, fmt::format("初始化 COM 失败\n\tHRESULT{}", hr));
return false;
}
SPDLOG_LOGGER_INFO(logger, "初始化 COM 成功");
// 注册主窗口类
_RegisterHostWndClass();
initalized = true;
}
if (!_CreateHostWnd()) {
return false;
}
return true;
}
void App::Run() {
SPDLOG_LOGGER_INFO(_logger, "开始接收窗口消息");
while (true) {
MSG msg;
while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
if (msg.message == WM_QUIT) {
return;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
//$instance->_renderManager->Render();
}
}
// 注册主窗口类
void App::_RegisterHostWndClass() const {
WNDCLASSEX wcex = {};
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.lpfnWndProc = _HostWndProcStatic;
wcex.hInstance = _hInst;
wcex.lpszClassName = _HOST_WINDOW_CLASS_NAME;
if (!RegisterClassEx(&wcex)) {
// 忽略此错误,因为可能是重复注册产生的错误
SPDLOG_LOGGER_ERROR(_logger, fmt::format("注册主窗口类失败\n\tLastErrorCode{}", GetLastError()));
} else {
SPDLOG_LOGGER_INFO(_logger, "已注册主窗口类");
}
}
// 创建主窗口
bool App::_CreateHostWnd() {
if (FindWindow(_HOST_WINDOW_CLASS_NAME, nullptr)) {
SPDLOG_LOGGER_CRITICAL(_logger, "已存在主窗口");
return false;
}
RECT screenRect = Utils::GetScreenRect(_hwndSrc);
_hwndHost = CreateWindowEx(
WS_EX_TOPMOST | WS_EX_NOACTIVATE | WS_EX_LAYERED | WS_EX_TRANSPARENT,
_HOST_WINDOW_CLASS_NAME,
NULL, WS_CLIPCHILDREN | WS_POPUP | WS_VISIBLE,
screenRect.left,
screenRect.top,
screenRect.right - screenRect.left,
screenRect.bottom - screenRect.top,
NULL,
NULL,
_hInst,
NULL
);
if (!_hwndHost) {
SPDLOG_LOGGER_CRITICAL(_logger, fmt::format("创建主窗口失败\n\tLastErrorCode{}", GetLastError()));
return false;
}
// 设置窗口不透明
if (!SetLayeredWindowAttributes(_hwndHost, 0, 255, LWA_ALPHA)) {
SPDLOG_LOGGER_ERROR(_logger, fmt::format("SetLayeredWindowAttributes 失败\n\tLastErrorCode{}", GetLastError()));
}
// 取消置顶,这样可以使该窗口在最前
if (!ShowWindow(_hwndHost, SW_NORMAL)) {
SPDLOG_LOGGER_ERROR(_logger, fmt::format("ShowWindow 失败\n\tLastErrorCode{}", GetLastError()));
}
DWORD style = GetWindowStyle(_hwndHost);
if (!style) {
SPDLOG_LOGGER_ERROR(_logger, fmt::format("GetWindowStyle 失败\n\tLastErrorCode{}", GetLastError()));
}
style &= ~WS_EX_TOPMOST;
if (!SetWindowLong(_hwndHost, GWL_STYLE, style)) {
SPDLOG_LOGGER_ERROR(_logger, fmt::format("SetWindowLong 失败\n\tLastErrorCode{}", GetLastError()));
}
SPDLOG_LOGGER_INFO(_logger, "已创建主窗口");
return true;
}
LRESULT App::_HostWndProcStatic(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
return GetInstance()->_HostWndProc(hWnd, message, wParam, lParam);
}
LRESULT App::_HostWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
if (message == _WM_DESTORYHOST) {
DestroyWindow(_hwndHost);
return 0;
}
if (message == WM_DESTROY) {
// 有两个退出路径:
// 1. 前台窗口发生改变
// 2. 收到_WM_DESTORYMAG 消息
PostQuitMessage(0);
return 0;
} else {
return DefWindowProc(hWnd, message, wParam, lParam);
/*auto [resolved, rt] = _renderManager->WndProc(hWnd, message, wParam, lParam);
if (resolved) {
return rt;
} else {
return DefWindowProc(hWnd, message, wParam, lParam);
}*/
}
return 0;
}