win提交
This commit is contained in:
@@ -3,9 +3,132 @@
|
||||
#include <dwmapi.h>
|
||||
#include <flutter_windows.h>
|
||||
#include <shellscalingapi.h>
|
||||
#include <windowsx.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <mutex>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include "resource.h"
|
||||
|
||||
// ============================================================
|
||||
// WindowCompositionAttribute 相关定义(与 flutter_acrylic 一致)
|
||||
// 用于调用 user32.dll 的未公开 API SetWindowCompositionAttribute
|
||||
// 这是 flutter_acrylic 禁用 Mica/Acrylic 的关键调用
|
||||
// ============================================================
|
||||
typedef enum _WCA_WINDOWCOMPOSITIONATTRIB {
|
||||
WCA_ATTRIB_ACCENT_POLICY = 19,
|
||||
} WCA_WINDOWCOMPOSITIONATTRIB;
|
||||
|
||||
typedef enum _WCA_ACCENT_STATE {
|
||||
WCA_ACCENT_DISABLED = 0,
|
||||
WCA_ACCENT_ENABLE_ACRYLICBLURBEHIND = 4,
|
||||
WCA_ACCENT_ENABLE_HOSTBACKDROP = 5,
|
||||
} WCA_ACCENT_STATE;
|
||||
|
||||
typedef struct _WCA_ACCENT_POLICY {
|
||||
WCA_ACCENT_STATE AccentState;
|
||||
DWORD AccentFlags;
|
||||
DWORD GradientColor;
|
||||
DWORD AnimationId;
|
||||
} WCA_ACCENT_POLICY;
|
||||
|
||||
typedef struct _WCA_WINDOWCOMPOSITIONATTRIBDATA {
|
||||
WCA_WINDOWCOMPOSITIONATTRIB Attrib;
|
||||
PVOID pvData;
|
||||
SIZE_T cbData;
|
||||
} WCA_WINDOWCOMPOSITIONATTRIBDATA;
|
||||
|
||||
typedef BOOL(WINAPI* WCA_SetWindowCompositionAttribute)(
|
||||
HWND, WCA_WINDOWCOMPOSITIONATTRIBDATA*);
|
||||
|
||||
// ============================================================
|
||||
// debug instrumentation for window-drag-lag
|
||||
// ============================================================
|
||||
namespace {
|
||||
std::mutex g_debug_log_mutex;
|
||||
std::wstring g_debug_log_path;
|
||||
|
||||
void DebugLog(const std::string& tag, const std::string& detail) {
|
||||
// 已禁用文件日志以排除 I/O 对消息循环的干扰。
|
||||
(void)tag;
|
||||
(void)detail;
|
||||
#if 0
|
||||
auto now = std::chrono::system_clock::now();
|
||||
auto us = std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
now.time_since_epoch())
|
||||
.count();
|
||||
std::lock_guard<std::mutex> lock(g_debug_log_mutex);
|
||||
if (g_debug_log_path.empty()) {
|
||||
g_debug_log_path = L"E:\\project\\flutter\\f\\xianyan\\xianyan_drag_debug.log";
|
||||
}
|
||||
std::wofstream ofs(g_debug_log_path, std::ios::app);
|
||||
if (!ofs.is_open()) return;
|
||||
ofs << us << L" [" << std::wstring(tag.begin(), tag.end()) << L"] "
|
||||
<< std::wstring(detail.begin(), detail.end()) << L"\n";
|
||||
#endif
|
||||
}
|
||||
|
||||
// 仅记录拖拽状态关键事件,验证 EnterSizeMove/ExitSizeMove 是否被调用。
|
||||
void DragDebugLog(const std::string& line) {
|
||||
static std::mutex m;
|
||||
static std::wstring path =
|
||||
L"E:\\project\\flutter\\f\\xianyan\\xianyan_drag_state.log";
|
||||
std::lock_guard<std::mutex> lock(m);
|
||||
std::ofstream ofs(path, std::ios::app);
|
||||
if (!ofs.is_open()) return;
|
||||
auto now = std::chrono::system_clock::now();
|
||||
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
now.time_since_epoch())
|
||||
.count();
|
||||
ofs << ms << " " << line << "\n";
|
||||
}
|
||||
|
||||
const char* HitTestName(LRESULT ht) {
|
||||
switch (ht) {
|
||||
case HTNOWHERE: return "HTNOWHERE";
|
||||
case HTCLIENT: return "HTCLIENT";
|
||||
case HTCAPTION: return "HTCAPTION";
|
||||
case HTLEFT: return "HTLEFT";
|
||||
case HTRIGHT: return "HTRIGHT";
|
||||
case HTTOP: return "HTTOP";
|
||||
case HTBOTTOM: return "HTBOTTOM";
|
||||
case HTTOPLEFT: return "HTTOPLEFT";
|
||||
case HTTOPRIGHT: return "HTTOPRIGHT";
|
||||
case HTBOTTOMLEFT: return "HTBOTTOMLEFT";
|
||||
case HTBOTTOMRIGHT: return "HTBOTTOMRIGHT";
|
||||
case HTTRANSPARENT: return "HTTRANSPARENT";
|
||||
default: return "OTHER";
|
||||
}
|
||||
}
|
||||
|
||||
std::string MsgName(UINT msg) {
|
||||
switch (msg) {
|
||||
case WM_NCHITTEST: return "WM_NCHITTEST";
|
||||
case WM_NCLBUTTONDOWN: return "WM_NCLBUTTONDOWN";
|
||||
case WM_NCLBUTTONUP: return "WM_NCLBUTTONUP";
|
||||
case WM_NCMOUSEMOVE: return "WM_NCMOUSEMOVE";
|
||||
case WM_LBUTTONDOWN: return "WM_LBUTTONDOWN";
|
||||
case WM_LBUTTONUP: return "WM_LBUTTONUP";
|
||||
case WM_MOUSEMOVE: return "WM_MOUSEMOVE";
|
||||
case WM_MOVE: return "WM_MOVE";
|
||||
case WM_MOVING: return "WM_MOVING";
|
||||
case WM_SIZE: return "WM_SIZE";
|
||||
case WM_WINDOWPOSCHANGING: return "WM_WINDOWPOSCHANGING";
|
||||
case WM_WINDOWPOSCHANGED: return "WM_WINDOWPOSCHANGED";
|
||||
case WM_SYSCOMMAND: return "WM_SYSCOMMAND";
|
||||
case WM_ENTERSIZEMOVE: return "WM_ENTERSIZEMOVE";
|
||||
case WM_EXITSIZEMOVE: return "WM_EXITSIZEMOVE";
|
||||
case WM_PAINT: return "WM_PAINT";
|
||||
case WM_ERASEBKGND: return "WM_ERASEBKGND";
|
||||
default: return "MSG_" + std::to_string(msg);
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
|
||||
/// Window attribute that enables dark mode window decorations.
|
||||
@@ -17,6 +140,37 @@ namespace {
|
||||
#define DWMWA_USE_IMMERSIVE_DARK_MODE 20
|
||||
#endif
|
||||
|
||||
// DWM 过渡动画与背景材质类型(兼容旧版 SDK)
|
||||
#ifndef DWMWA_TRANSITIONS_FORCEDISABLED
|
||||
#define DWMWA_TRANSITIONS_FORCEDISABLED 3
|
||||
#endif
|
||||
#ifndef DWMWA_SYSTEMBACKDROP_TYPE
|
||||
#define DWMWA_SYSTEMBACKDROP_TYPE 38
|
||||
#endif
|
||||
#ifndef DWMWA_MICA_EFFECT
|
||||
#define DWMWA_MICA_EFFECT 1029
|
||||
#endif
|
||||
|
||||
// RtlGetVersion 用于获取真实系统版本(GetVersionExW 在 Win8.1+ 会返回兼容性版本)
|
||||
typedef LONG NTSTATUS, *PNTSTATUS;
|
||||
#define STATUS_SUCCESS (0x00000000)
|
||||
typedef NTSTATUS(WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW);
|
||||
#ifndef DWMSBT_AUTO
|
||||
#define DWMSBT_AUTO 0
|
||||
#endif
|
||||
#ifndef DWMSBT_NONE
|
||||
#define DWMSBT_NONE 1
|
||||
#endif
|
||||
#ifndef DWMSBT_MAINWINDOW
|
||||
#define DWMSBT_MAINWINDOW 3
|
||||
#endif
|
||||
#ifndef DWMSBT_TRANSIENTWINDOW
|
||||
#define DWMSBT_TRANSIENTWINDOW 4
|
||||
#endif
|
||||
#ifndef DWMSBT_TABBEDWINDOW
|
||||
#define DWMSBT_TABBEDWINDOW 2
|
||||
#endif
|
||||
|
||||
constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW";
|
||||
|
||||
/// Registry key for app theme preference.
|
||||
@@ -92,7 +246,7 @@ const wchar_t* WindowClassRegistrar::GetWindowClass() {
|
||||
WNDCLASS window_class{};
|
||||
window_class.hCursor = LoadCursor(nullptr, IDC_ARROW);
|
||||
window_class.lpszClassName = kWindowClassName;
|
||||
window_class.style = CS_HREDRAW | CS_VREDRAW;
|
||||
window_class.style = CS_DBLCLKS;
|
||||
window_class.cbClsExtra = 0;
|
||||
window_class.cbWndExtra = 0;
|
||||
window_class.hInstance = GetModuleHandle(nullptr);
|
||||
@@ -136,7 +290,8 @@ bool Win32Window::Create(const std::wstring& title,
|
||||
double scale_factor = dpi / 96.0;
|
||||
|
||||
HWND window = CreateWindow(
|
||||
window_class, title.c_str(), WS_OVERLAPPEDWINDOW,
|
||||
window_class, title.c_str(),
|
||||
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
|
||||
Scale(origin.x, scale_factor), Scale(origin.y, scale_factor),
|
||||
Scale(size.width, scale_factor), Scale(size.height, scale_factor),
|
||||
nullptr, nullptr, GetModuleHandle(nullptr), this);
|
||||
@@ -145,6 +300,8 @@ bool Win32Window::Create(const std::wstring& title,
|
||||
return false;
|
||||
}
|
||||
|
||||
DetectBackdropCapabilities(&system_backdrop_supported_,
|
||||
&mica_effect_supported_);
|
||||
UpdateTheme(window);
|
||||
|
||||
return OnCreate();
|
||||
@@ -179,6 +336,22 @@ Win32Window::MessageHandler(HWND hwnd,
|
||||
UINT const message,
|
||||
WPARAM const wparam,
|
||||
LPARAM const lparam) noexcept {
|
||||
// region debug-point parent-msg
|
||||
if (message == WM_NCHITTEST || message == WM_NCLBUTTONDOWN ||
|
||||
message == WM_NCLBUTTONUP || message == WM_NCMOUSEMOVE ||
|
||||
message == WM_LBUTTONDOWN || message == WM_LBUTTONUP ||
|
||||
message == WM_MOUSEMOVE || message == WM_MOVE || message == WM_MOVING ||
|
||||
message == WM_SIZE || message == WM_WINDOWPOSCHANGING ||
|
||||
message == WM_WINDOWPOSCHANGED || message == WM_SYSCOMMAND ||
|
||||
message == WM_ENTERSIZEMOVE || message == WM_EXITSIZEMOVE ||
|
||||
message == WM_ERASEBKGND) {
|
||||
std::ostringstream oss;
|
||||
oss << "hwnd=" << hwnd << " msg=" << MsgName(message)
|
||||
<< " wp=" << wparam << " lp=" << lparam;
|
||||
DebugLog("parent", oss.str());
|
||||
}
|
||||
// endregion debug-point parent-msg
|
||||
|
||||
switch (message) {
|
||||
case WM_DESTROY:
|
||||
window_handle_ = nullptr;
|
||||
@@ -201,9 +374,11 @@ Win32Window::MessageHandler(HWND hwnd,
|
||||
case WM_SIZE: {
|
||||
RECT rect = GetClientArea();
|
||||
if (child_content_ != nullptr) {
|
||||
// Size and position the child window.
|
||||
MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left,
|
||||
rect.bottom - rect.top, TRUE);
|
||||
// DwmExtendFrameIntoClientArea(margins={-1}) 会改变窗口帧布局,
|
||||
// 但 GetClientRect 始终返回正确的客户区尺寸(左上角为 0,0),
|
||||
// 所以 MoveWindow 从 (0,0) 开始填充整个客户区是正确的。
|
||||
// 关键:确保 bRepaint=TRUE 以立即重绘。
|
||||
MoveWindow(child_content_, 0, 0, rect.right, rect.bottom, TRUE);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -218,6 +393,30 @@ Win32Window::MessageHandler(HWND hwnd,
|
||||
UpdateTheme(hwnd);
|
||||
return 0;
|
||||
|
||||
case WM_ERASEBKGND: {
|
||||
UINT64 enter = std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
std::chrono::system_clock::now().time_since_epoch())
|
||||
.count();
|
||||
LRESULT r = DefWindowProc(hwnd, message, wparam, lparam);
|
||||
UINT64 now = std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
std::chrono::system_clock::now().time_since_epoch())
|
||||
.count();
|
||||
std::ostringstream oss;
|
||||
oss << "WM_ERASEBKGND duration_us=" << (now - enter);
|
||||
DebugLog("parent", oss.str());
|
||||
return r;
|
||||
}
|
||||
|
||||
case WM_ENTERSIZEMOVE: {
|
||||
EnterSizeMove(hwnd);
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_EXITSIZEMOVE: {
|
||||
ExitSizeMove(hwnd);
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_GETMINMAXINFO: {
|
||||
// 处理窗口最小尺寸限制
|
||||
MINMAXINFO* mmi = reinterpret_cast<MINMAXINFO*>(lparam);
|
||||
@@ -233,6 +432,61 @@ Win32Window::MessageHandler(HWND hwnd,
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
case WM_NCHITTEST: {
|
||||
// 标题栏可拖拽区域返回 HTCAPTION,让 Windows 进入原生模态拖拽循环。
|
||||
// 原生拖拽由 DWM 直接处理,不会经过 Flutter 插件链,避免 MethodChannel
|
||||
// 和 Dart setState 导致的延迟。
|
||||
POINT pt = {GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam)};
|
||||
ScreenToClient(hwnd, &pt);
|
||||
|
||||
UINT dpi = GetDpiForWindow(hwnd);
|
||||
double scale = static_cast<double>(dpi) / 96.0;
|
||||
int title_h = static_cast<int>(title_bar_height_ * scale);
|
||||
int btn_w = static_cast<int>(title_bar_button_width_ * scale);
|
||||
RECT cr;
|
||||
GetClientRect(hwnd, &cr);
|
||||
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "WM_NCHITTEST raw_screen=(" << GET_X_LPARAM(lparam) << ","
|
||||
<< GET_Y_LPARAM(lparam) << ") client=(" << pt.x << "," << pt.y
|
||||
<< ") dpi=" << dpi << " scale=" << scale
|
||||
<< " title_h=" << title_h << " btn_w=" << btn_w
|
||||
<< " cr=(" << cr.right << "," << cr.bottom << ")";
|
||||
DebugLog("parent", oss.str());
|
||||
}
|
||||
|
||||
if (cr.right <= 0 || cr.bottom <= 0) {
|
||||
DebugLog("parent", "WM_NCHITTEST fallback: empty client rect");
|
||||
break;
|
||||
}
|
||||
|
||||
if (pt.y >= 0 && pt.y < title_h &&
|
||||
pt.x >= 0 && pt.x < cr.right - btn_w) {
|
||||
std::ostringstream oss;
|
||||
oss << "WM_NCHITTEST -> HTCAPTION pt=(" << pt.x << "," << pt.y
|
||||
<< ") title_h=" << title_h << " btn_w=" << btn_w
|
||||
<< " cr=(" << cr.right << "," << cr.bottom << ")";
|
||||
DebugLog("parent", oss.str());
|
||||
return HTCAPTION;
|
||||
}
|
||||
std::ostringstream oss;
|
||||
oss << "WM_NCHITTEST -> Def pt=(" << pt.x << "," << pt.y
|
||||
<< ") title_h=" << title_h << " btn_w=" << btn_w;
|
||||
DebugLog("parent", oss.str());
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_NCLBUTTONDOWN: {
|
||||
// 标题栏 HTCAPTION 的拖拽已在 FlutterWindow::MessageHandler 中
|
||||
// 前置处理(先禁用 DWM 效果再进入原生拖拽循环)。
|
||||
// 此处仅处理非标题栏区域点击,由 DefWindowProc 处理窗口边框调整大小等。
|
||||
std::ostringstream oss;
|
||||
oss << "WM_NCLBUTTONDOWN ht=" << HitTestName(static_cast<LRESULT>(wparam));
|
||||
DebugLog("parent", oss.str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return DefWindowProc(window_handle_, message, wparam, lparam);
|
||||
@@ -260,8 +514,7 @@ void Win32Window::SetChildContent(HWND content) {
|
||||
SetParent(content, window_handle_);
|
||||
RECT frame = GetClientArea();
|
||||
|
||||
MoveWindow(content, frame.left, frame.top, frame.right - frame.left,
|
||||
frame.bottom - frame.top, true);
|
||||
MoveWindow(content, 0, 0, frame.right, frame.bottom, true);
|
||||
|
||||
SetFocus(child_content_);
|
||||
}
|
||||
@@ -321,6 +574,8 @@ LONG Win32Window::saved_window_ex_style_ = 0;
|
||||
WINDOWPLACEMENT Win32Window::saved_placement_ = {sizeof(WINDOWPLACEMENT)};
|
||||
unsigned int Win32Window::min_width_ = 400;
|
||||
unsigned int Win32Window::min_height_ = 600;
|
||||
double Win32Window::title_bar_height_ = 36.0;
|
||||
double Win32Window::title_bar_button_width_ = 138.0;
|
||||
|
||||
// ============================================================
|
||||
// 窗口管理扩展方法实现
|
||||
@@ -422,3 +677,166 @@ std::string Win32Window::GetSystemAppearance() {
|
||||
}
|
||||
return "light";
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// 拖拽时临时禁用 DWM Mica/Acrylic 合成,避免拖拽卡顿
|
||||
// ============================================================
|
||||
|
||||
void Win32Window::DetectBackdropCapabilities(bool* system_backdrop,
|
||||
bool* mica_effect) {
|
||||
*system_backdrop = false;
|
||||
*mica_effect = false;
|
||||
|
||||
// 使用 RtlGetVersion 获取真实系统版本,避免 GetVersionExW 的兼容性谎言。
|
||||
RTL_OSVERSIONINFOW osvi = {0};
|
||||
osvi.dwOSVersionInfoSize = sizeof(osvi);
|
||||
HMODULE ntdll = GetModuleHandleW(L"ntdll.dll");
|
||||
if (ntdll) {
|
||||
auto rtl_get_version = reinterpret_cast<RtlGetVersionPtr>(
|
||||
GetProcAddress(ntdll, "RtlGetVersion"));
|
||||
if (rtl_get_version && STATUS_SUCCESS != rtl_get_version(&osvi)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (osvi.dwMajorVersion < 10) {
|
||||
return;
|
||||
}
|
||||
|
||||
HWND hwnd = GetDesktopWindow();
|
||||
if (osvi.dwBuildNumber >= 22523) {
|
||||
INT probe = DWMSBT_AUTO;
|
||||
*system_backdrop = SUCCEEDED(DwmSetWindowAttribute(
|
||||
hwnd, DWMWA_SYSTEMBACKDROP_TYPE, &probe, sizeof(probe)));
|
||||
}
|
||||
if (osvi.dwBuildNumber >= 22000) {
|
||||
BOOL probe = FALSE;
|
||||
*mica_effect = SUCCEEDED(DwmSetWindowAttribute(
|
||||
hwnd, DWMWA_MICA_EFFECT, &probe, sizeof(probe)));
|
||||
}
|
||||
}
|
||||
|
||||
int Win32Window::GetCurrentBackdropType(HWND hwnd) {
|
||||
INT value = -1;
|
||||
HRESULT hr = DwmGetWindowAttribute(hwnd, DWMWA_SYSTEMBACKDROP_TYPE,
|
||||
&value, sizeof(value));
|
||||
if (SUCCEEDED(hr)) {
|
||||
return static_cast<int>(value);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Win32Window::SetBackdropType(HWND hwnd, int type) {
|
||||
INT value = static_cast<INT>(type);
|
||||
DwmSetWindowAttribute(hwnd, DWMWA_SYSTEMBACKDROP_TYPE, &value, sizeof(value));
|
||||
}
|
||||
|
||||
void Win32Window::SetTransitionsEnabled(HWND hwnd, BOOL enabled) {
|
||||
DwmSetWindowAttribute(hwnd, DWMWA_TRANSITIONS_FORCEDISABLED,
|
||||
&enabled, sizeof(enabled));
|
||||
}
|
||||
|
||||
void Win32Window::EnterSizeMove(HWND hwnd) {
|
||||
if (is_in_size_move_loop_) return;
|
||||
is_in_size_move_loop_ = true;
|
||||
|
||||
DragDebugLog("EnterSizeMove begin");
|
||||
|
||||
// ============================================================
|
||||
// 关键:调用 SetWindowCompositionAttribute(ACCENT_DISABLED)
|
||||
//
|
||||
// 这是 flutter_acrylic 的 Window.setEffect(disabled) 能立即禁用 Mica
|
||||
// 的关键调用,之前的 v4~v7 修复都遗漏了这一步。
|
||||
//
|
||||
// SetWindowCompositionAttribute 是 user32.dll 的未公开 API,
|
||||
// 通过它设置窗口的 ACCENT_POLICY 为 ACCENT_DISABLED,可以立即禁用
|
||||
// 所有窗口合成效果(包括 Mica/Acrylic)。
|
||||
//
|
||||
// 仅靠 DwmSetWindowAttribute 是不够的——它是异步的,DWM 不会立即应用
|
||||
// 变更。SetWindowCompositionAttribute 能立即生效。
|
||||
// ============================================================
|
||||
{
|
||||
HMODULE user32 = GetModuleHandleW(L"user32.dll");
|
||||
if (user32) {
|
||||
auto set_window_composition_attribute =
|
||||
reinterpret_cast<WCA_SetWindowCompositionAttribute>(
|
||||
GetProcAddress(user32, "SetWindowCompositionAttribute"));
|
||||
if (set_window_composition_attribute) {
|
||||
WCA_ACCENT_POLICY accent = {WCA_ACCENT_DISABLED, 2, 0, 0};
|
||||
WCA_WINDOWCOMPOSITIONATTRIBDATA data;
|
||||
data.Attrib = WCA_ATTRIB_ACCENT_POLICY;
|
||||
data.pvData = &accent;
|
||||
data.cbData = sizeof(accent);
|
||||
set_window_composition_attribute(hwnd, &data);
|
||||
DragDebugLog("SetWindowCompositionAttribute(ACCENT_DISABLED) called");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 使用 {0, 0, 1, 0} 而非 {0, 0, 0, 0}:
|
||||
// 与 flutter_acrylic 的 setEffect(disabled) 一致。
|
||||
// 注释:At least one margin should be non-negative in order to show
|
||||
// the DWM window shadow created by handling WM_NCCALCSIZE.
|
||||
saved_margins_ = {-1, -1, -1, -1};
|
||||
has_saved_margins_ = true;
|
||||
MARGINS drag_margins = {0, 0, 1, 0};
|
||||
DwmExtendFrameIntoClientArea(hwnd, &drag_margins);
|
||||
|
||||
// 禁用 System Backdrop(Win11 22523+)
|
||||
saved_backdrop_type_ = GetCurrentBackdropType(hwnd);
|
||||
DragDebugLog(std::string("saved_backdrop_type=") +
|
||||
std::to_string(saved_backdrop_type_));
|
||||
if (saved_backdrop_type_ > DWMSBT_NONE || saved_backdrop_type_ == -1) {
|
||||
SetBackdropType(hwnd, DWMSBT_NONE);
|
||||
}
|
||||
|
||||
// 禁用 Mica Effect(Win11 22000+)
|
||||
if (mica_effect_supported_) {
|
||||
DWORD value = FALSE;
|
||||
DwmGetWindowAttribute(hwnd, DWMWA_MICA_EFFECT, &saved_mica_enabled_,
|
||||
sizeof(saved_mica_enabled_));
|
||||
DragDebugLog(std::string("saved_mica_enabled=") +
|
||||
std::to_string(saved_mica_enabled_));
|
||||
if (saved_mica_enabled_) {
|
||||
DwmSetWindowAttribute(hwnd, DWMWA_MICA_EFFECT, &value, sizeof(value));
|
||||
}
|
||||
}
|
||||
|
||||
// 禁用 DWM 过渡动画,进一步降低合成延迟
|
||||
DwmGetWindowAttribute(hwnd, DWMWA_TRANSITIONS_FORCEDISABLED,
|
||||
&saved_transitions_enabled_,
|
||||
sizeof(saved_transitions_enabled_));
|
||||
SetTransitionsEnabled(hwnd, TRUE);
|
||||
|
||||
DragDebugLog("EnterSizeMove done");
|
||||
}
|
||||
|
||||
void Win32Window::ExitSizeMove(HWND hwnd) {
|
||||
if (!is_in_size_move_loop_) return;
|
||||
is_in_size_move_loop_ = false;
|
||||
|
||||
DragDebugLog("ExitSizeMove begin");
|
||||
|
||||
// 恢复 backdrop
|
||||
if (system_backdrop_supported_ && saved_backdrop_type_ > DWMSBT_NONE) {
|
||||
SetBackdropType(hwnd, saved_backdrop_type_);
|
||||
saved_backdrop_type_ = -1;
|
||||
}
|
||||
|
||||
// 恢复 Mica effect
|
||||
if (mica_effect_supported_ && saved_mica_enabled_) {
|
||||
DwmSetWindowAttribute(hwnd, DWMWA_MICA_EFFECT, &saved_mica_enabled_,
|
||||
sizeof(saved_mica_enabled_));
|
||||
saved_mica_enabled_ = FALSE;
|
||||
}
|
||||
|
||||
// 恢复 DWM 扩展帧边距
|
||||
if (has_saved_margins_) {
|
||||
DwmExtendFrameIntoClientArea(hwnd, &saved_margins_);
|
||||
has_saved_margins_ = false;
|
||||
}
|
||||
|
||||
// 恢复 DWM 过渡动画
|
||||
SetTransitionsEnabled(hwnd, saved_transitions_enabled_);
|
||||
|
||||
DragDebugLog("ExitSizeMove done");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user