203 lines
7.5 KiB
C++
203 lines
7.5 KiB
C++
#ifndef RUNNER_WIN32_WINDOW_H_
|
||
#define RUNNER_WIN32_WINDOW_H_
|
||
|
||
#include <windows.h>
|
||
#include <dwmapi.h>
|
||
|
||
#include <functional>
|
||
#include <memory>
|
||
#include <string>
|
||
|
||
// A class abstraction for a high DPI-aware Win32 Window. Intended to be
|
||
// inherited from by classes that wish to specialize with custom
|
||
// rendering and input handling
|
||
class Win32Window {
|
||
public:
|
||
struct Point {
|
||
unsigned int x;
|
||
unsigned int y;
|
||
Point(unsigned int x, unsigned int y) : x(x), y(y) {}
|
||
};
|
||
|
||
struct Size {
|
||
unsigned int width;
|
||
unsigned int height;
|
||
Size(unsigned int width, unsigned int height)
|
||
: width(width), height(height) {}
|
||
};
|
||
|
||
Win32Window();
|
||
virtual ~Win32Window();
|
||
|
||
// Creates a win32 window with |title| that is positioned and sized using
|
||
// |origin| and |size|. New windows are created on the default monitor. Window
|
||
// sizes are specified to the OS in physical pixels, hence to ensure a
|
||
// consistent size this function will scale the inputted width and height as
|
||
// as appropriate for the default monitor. The window is invisible until
|
||
// |Show| is called. Returns true if the window was created successfully.
|
||
bool Create(const std::wstring& title, const Point& origin, const Size& size);
|
||
|
||
// Show the current window. Returns true if the window was successfully shown.
|
||
bool Show();
|
||
|
||
// Release OS resources associated with window.
|
||
void Destroy();
|
||
|
||
// Inserts |content| into the window tree.
|
||
void SetChildContent(HWND content);
|
||
|
||
// Returns the backing Window handle to enable clients to set icon and other
|
||
// window properties. Returns nullptr if the window has been destroyed.
|
||
HWND GetHandle();
|
||
|
||
// If true, closing this window will quit the application.
|
||
void SetQuitOnClose(bool quit_on_close);
|
||
|
||
// Return a RECT representing the bounds of the current client area.
|
||
RECT GetClientArea();
|
||
|
||
// Set the window frame's dark mode explicitly (called from Flutter).
|
||
static void SetDarkMode(HWND const window, bool dark_mode);
|
||
|
||
// ============================================================
|
||
// 窗口管理扩展方法(由 Flutter 侧通过 MethodChannel 调用)
|
||
// ============================================================
|
||
|
||
// 设置窗口标题
|
||
static void SetWindowTitle(HWND const window, const std::wstring& title);
|
||
|
||
// 进入/退出全屏模式
|
||
// fullscreen=true: 保存当前窗口状态,移除标题栏和边框,最大化窗口
|
||
// fullscreen=false: 恢复保存的窗口状态
|
||
static void SetFullscreen(HWND const window, bool fullscreen);
|
||
|
||
// 查询当前是否处于全屏模式
|
||
static bool IsFullscreen(HWND const window);
|
||
|
||
// 设置窗口最小尺寸(物理像素)
|
||
static void SetMinSize(HWND const window, unsigned int width,
|
||
unsigned int height);
|
||
|
||
// 执行触觉反馈(Windows 使用 MessageBeep 模拟)
|
||
static void PerformHapticFeedback(HWND const window, int feedback_type);
|
||
|
||
// 获取系统外观模式("light" 或 "dark")
|
||
static std::string GetSystemAppearance();
|
||
|
||
protected:
|
||
// Processes and route salient window messages for mouse handling,
|
||
// size change and DPI. Delegates handling of these to member overloads that
|
||
// inheriting classes can handle.
|
||
virtual LRESULT MessageHandler(HWND window,
|
||
UINT const message,
|
||
WPARAM const wparam,
|
||
LPARAM const lparam) noexcept;
|
||
|
||
// Called when CreateAndShow is called, allowing subclass window-related
|
||
// setup. Subclasses should return false if setup fails.
|
||
virtual bool OnCreate();
|
||
|
||
// Called when Destroy is called.
|
||
virtual void OnDestroy();
|
||
|
||
protected:
|
||
// ============================================================
|
||
// 拖拽时临时禁用 DWM Mica/Acrylic 合成,避免拖拽卡顿
|
||
// ============================================================
|
||
|
||
// 当前是否处于系统拖拽/调整大小模态循环中
|
||
// protected:FlutterWindow 需要访问此标志,判断是否需要在
|
||
// WM_ENTERSIZEMOVE/WM_EXITSIZEMOVE 时禁用/恢复 Mica
|
||
bool is_in_size_move_loop_ = false;
|
||
|
||
// 本机是否支持 DWMWA_SYSTEMBACKDROP_TYPE(Win11 22523+)
|
||
bool system_backdrop_supported_ = false;
|
||
|
||
// 本机是否支持 DWMWA_MICA_EFFECT(Win11 22000+)
|
||
bool mica_effect_supported_ = false;
|
||
|
||
private:
|
||
friend class WindowClassRegistrar;
|
||
|
||
// OS callback called by message pump. Handles the WM_NCCREATE message which
|
||
// is passed when the non-client area is being created and enables automatic
|
||
// non-client DPI scaling so that the non-client area automatically
|
||
// responds to changes in DPI. All other messages are handled by
|
||
// MessageHandler.
|
||
static LRESULT CALLBACK WndProc(HWND const window,
|
||
UINT const message,
|
||
WPARAM const wparam,
|
||
LPARAM const lparam) noexcept;
|
||
|
||
// Retrieves a class instance pointer for |window|
|
||
static Win32Window* GetThisFromHandle(HWND const window) noexcept;
|
||
|
||
// Update the window frame's theme to match the system theme.
|
||
static void UpdateTheme(HWND const window);
|
||
|
||
bool quit_on_close_ = false;
|
||
|
||
// window handle for top level window.
|
||
HWND window_handle_ = nullptr;
|
||
|
||
// window handle for hosted content.
|
||
HWND child_content_ = nullptr;
|
||
|
||
// ============================================================
|
||
// 窗口管理扩展状态
|
||
// ============================================================
|
||
|
||
// 全屏状态保存
|
||
static bool fullscreen_; // 是否处于全屏模式
|
||
static RECT saved_window_rect_; // 全屏前保存的窗口位置
|
||
static LONG saved_window_style_; // 全屏前保存的窗口样式
|
||
static LONG saved_window_ex_style_; // 全屏前保存的扩展样式
|
||
static WINDOWPLACEMENT saved_placement_; // 全屏前保存的窗口位置信息
|
||
|
||
// 最小尺寸限制(物理像素)
|
||
static unsigned int min_width_;
|
||
static unsigned int min_height_;
|
||
|
||
// 自定义标题栏高度(逻辑像素),用于 WM_NCHITTEST 拖拽区域
|
||
// 与 Flutter 侧 DesktopTitleBarStyle.windows().height 保持一致
|
||
static double title_bar_height_;
|
||
|
||
// 自定义标题栏右侧按钮区域宽度(逻辑像素),用于 WM_NCHITTEST 排除可点击按钮
|
||
// 与 Flutter 侧 Windows 控制按钮总宽度(46 * 3 = 138)保持一致
|
||
static double title_bar_button_width_;
|
||
|
||
// 拖拽前保存的 backdrop 类型,拖拽结束恢复
|
||
// -1 表示尚未记录;0=none, 2=tabbed, 3=mica, 4=transient(acrylic)
|
||
int saved_backdrop_type_ = -1;
|
||
|
||
// 拖拽前 Mica 启用状态,拖拽结束恢复
|
||
BOOL saved_mica_enabled_ = FALSE;
|
||
|
||
// 拖拽前 DWM 扩展帧边距,拖拽结束恢复
|
||
MARGINS saved_margins_ = {0, 0, 0, 0};
|
||
bool has_saved_margins_ = false;
|
||
|
||
// 拖拽前 DWM 过渡动画状态,拖拽结束恢复
|
||
BOOL saved_transitions_enabled_ = TRUE;
|
||
|
||
// 检测并缓存系统支持的 backdrop 能力
|
||
static void DetectBackdropCapabilities(bool* system_backdrop,
|
||
bool* mica_effect);
|
||
|
||
// 获取当前 DWM backdrop 类型(若支持),否则返回 -1
|
||
static int GetCurrentBackdropType(HWND hwnd);
|
||
|
||
// 设置 DWM backdrop 类型
|
||
static void SetBackdropType(HWND hwnd, int type);
|
||
|
||
// 设置 DWM 过渡动画启用/禁用
|
||
static void SetTransitionsEnabled(HWND hwnd, BOOL enabled);
|
||
|
||
protected:
|
||
// 进入/退出拖拽循环时调用(子类可覆写以在拖拽前后执行自定义逻辑)
|
||
virtual void EnterSizeMove(HWND hwnd);
|
||
virtual void ExitSizeMove(HWND hwnd);
|
||
};
|
||
|
||
#endif // RUNNER_WIN32_WINDOW_H_
|