Files
xianyan/windows/runner/win32_window.h
Developer f7520b17b2 win提交
2026-06-22 03:50:59 +08:00

203 lines
7.5 KiB
C++
Raw Permalink 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.
#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 合成,避免拖拽卡顿
// ============================================================
// 当前是否处于系统拖拽/调整大小模态循环中
// protectedFlutterWindow 需要访问此标志,判断是否需要在
// WM_ENTERSIZEMOVE/WM_EXITSIZEMOVE 时禁用/恢复 Mica
bool is_in_size_move_loop_ = false;
// 本机是否支持 DWMWA_SYSTEMBACKDROP_TYPEWin11 22523+
bool system_backdrop_supported_ = false;
// 本机是否支持 DWMWA_MICA_EFFECTWin11 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_