Magpie/tools/WindowCase/WindowBase.h
Xu d01956e3a7
源窗口位于前台时始终置顶缩放窗口 (#1259)
* feat: 模拟中途置顶的窗口

* fix: 按钮随 DPI 缩放

* fix: 始终置顶

* fix: 修复切换前台窗口

* feat: 删除置顶选项

* refactor: 检查逻辑

* refactor: 用更简单的方式将缩放窗口置于源窗口之前

* fix: 支持源窗口中途置顶

* refactor: 小优化

* fix: 修复特定操作下意外将源窗口置顶

* fix: 提高取消置顶的可靠性

* fix: 调试模式下不置顶

* chore: WindowCase 支持模拟弹窗

* fix: 不要把被禁用的窗口设为前台

* feat: WindowCase 支持模拟“模拟模态弹窗”

* chore: 避免大量错误日志

* fix: 优化 Z 顺序维护

* fix: 不再使用 SWP_NOOWNERZORDER

* fix: 修复消息弹窗可能影响窗口 Z 顺序

* refactor: 小优化

* chore: 添加注释

* chore: 添加注释

* fix: 小优化

* chore: 小优化
2025-08-21 17:49:05 +08:00

91 lines
1.8 KiB
C++

#pragma once
template <typename T>
class WindowBaseT {
public:
WindowBaseT() noexcept = default;
WindowBaseT(const WindowBaseT&) = delete;
WindowBaseT(WindowBaseT&&) noexcept = default;
HWND Handle() const noexcept {
return _hWnd;
}
operator bool() const noexcept {
return _hWnd;
}
void Destroy() const noexcept {
if (_hWnd) {
DestroyWindow(_hWnd);
}
}
protected:
// 确保无法通过基类指针删除这个对象
~WindowBaseT() noexcept {
Destroy();
}
static LRESULT CALLBACK _WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
if (msg == WM_NCCREATE) {
WindowBaseT* that = (WindowBaseT*)(((CREATESTRUCT*)lParam)->lpCreateParams);
assert(that && !that->_hWnd);
that->_hWnd = hWnd;
SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)that);
} else if (T* that = (T*)GetWindowLongPtr(hWnd, GWLP_USERDATA)) {
return that->_MessageHandler(msg, wParam, lParam);
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
LRESULT _MessageHandler(UINT msg, WPARAM wParam, LPARAM lParam) noexcept {
switch (msg) {
case WM_CREATE:
{
// 出于简单性考虑,不处理 DPI 更改
_dpiScale = GetDpiForWindow(Handle()) / double(USER_DEFAULT_SCREEN_DPI);
_hUIFont = CreateFont(
std::lround(20 * _DpiScale()),
0,
0,
0,
FW_NORMAL,
FALSE,
FALSE,
FALSE,
DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY,
DEFAULT_PITCH | FF_DONTCARE,
L"Microsoft YaHei UI"
);
return 0;
}
case WM_DESTROY:
{
_hWnd = NULL;
return 0;
}
}
return DefWindowProc(_hWnd, msg, wParam, lParam);
}
HFONT _UIFont() const noexcept {
return _hUIFont;
}
double _DpiScale() const noexcept {
return _dpiScale;
}
private:
HWND _hWnd = NULL;
HFONT _hUIFont = NULL;
double _dpiScale = 1.0;
};