#ifndef RUNNER_FLUTTER_WINDOW_H_ #define RUNNER_FLUTTER_WINDOW_H_ #include #include #include #include #include "win32_window.h" // A window that does nothing but host a Flutter view. class FlutterWindow : public Win32Window { public: // Creates a new FlutterWindow hosting a Flutter view running |project|. explicit FlutterWindow(const flutter::DartProject& project); virtual ~FlutterWindow(); protected: // Win32Window: bool OnCreate() override; void OnDestroy() override; LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept override; private: // The project to run. flutter::DartProject project_; // The Flutter instance hosted in this window. std::unique_ptr flutter_controller_; // Windows platform MethodChannel for theme control. std::unique_ptr> platform_channel_; // 窗口控制 MethodChannel(窗口大小预设菜单等) std::unique_ptr> window_control_channel_; // 弹出原生窗口大小预设菜单(TrackPopupMenuEx) // 返回 true 表示用户选择了某个尺寸,false 表示用户取消了菜单 bool ShowWindowSizeMenu(HWND hwnd); // Subclass ID for the Flutter child window (WM_NCHITTEST → HTTRANSPARENT) static const UINT_PTR kChildSubclassId = 12345; // Subclass callback: forward title-bar hit-test to parent window so the // parent can return HTCAPTION and Windows performs native modal dragging. static LRESULT CALLBACK ChildWndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam, UINT_PTR subclass_id, DWORD_PTR ref_data); // ============================================================ // 原生拖拽状态:SC_MOVE 模态循环期间绕过插件链 + 子窗口消息拦截 // // 根因(经 v1~v8 验证): // 1. 手动 SetWindowPos 拖拽不触发 DWM "live drag" 优化 // 2. 完全禁用 Mica 能解决卡顿(v8 验证),但临时禁用 Mica(v4~v7)失败 // 3. v4~v7 失败的原因:EnterSizeMove 遗漏了 SetWindowCompositionAttribute // (ACCENT_DISABLED) 调用——这是 flutter_acrylic 的 setEffect(disabled) // 能立即禁用 Mica 的关键。仅靠 DwmSetWindowAttribute 是异步的,不生效。 // // 修复(v9): // - WM_NCLBUTTONDOWN(HTCAPTION) 时调用 EnterSizeMove 禁用 Mica // (现在包含 SetWindowCompositionAttribute(ACCENT_DISABLED),能立即生效) // - SWP_FRAMECHANGED 强制 DWM 同步应用变更 // - DefWindowProc 进入 SC_MOVE 模态循环 // - DefWindowProc 返回后调用 ExitSizeMove 恢复 Mica + SWP_FRAMECHANGED // - 模态循环期间绕过插件链 + 子窗口消息拦截(v8) // ============================================================ static bool is_in_native_drag_; }; #endif // RUNNER_FLUTTER_WINDOW_H_