feat: Windows增加分辨率适应,切换分辨率按钮修改

This commit is contained in:
2026-07-23 09:26:13 +08:00
parent 7de30eefa4
commit a1c29246d7
4 changed files with 218 additions and 44 deletions

View File

@@ -1,6 +1,7 @@
#include "flutter_window.h"
#include <optional>
#include <variant>
#include "flutter/generated_plugin_registrant.h"
@@ -27,6 +28,29 @@ bool FlutterWindow::OnCreate() {
RegisterPlugins(flutter_controller_->engine());
SetChildContent(flutter_controller_->view()->GetNativeWindow());
// 注册窗口控制通道Dart 端可请求按视频比例调整窗口尺寸。
window_channel_ =
std::make_unique<flutter::MethodChannel<flutter::EncodableValue>>(
flutter_controller_->engine()->messenger(), "app/window",
&flutter::StandardMethodCodec::GetInstance());
window_channel_->SetMethodCallHandler(
[this](const flutter::MethodCall<flutter::EncodableValue>& call,
std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>>
result) {
if (call.method_name() == "resizeToVideoAspect") {
double aspect = 0.0;
if (const auto* value = std::get_if<double>(call.arguments())) {
aspect = *value;
} else if (const auto* ivalue = std::get_if<int>(call.arguments())) {
aspect = static_cast<double>(*ivalue);
}
ResizeToVideoAspect(aspect);
result->Success();
} else {
result->NotImplemented();
}
});
flutter_controller_->engine()->SetNextFrameCallback([&]() {
this->Show();
});
@@ -47,6 +71,69 @@ void FlutterWindow::OnDestroy() {
Win32Window::OnDestroy();
}
void FlutterWindow::ResizeToVideoAspect(double aspect) {
if (aspect <= 0.0) {
return;
}
HWND hwnd = GetHandle();
if (!hwnd) {
return;
}
RECT window_rect;
RECT client_rect;
GetWindowRect(hwnd, &window_rect);
GetClientRect(hwnd, &client_rect);
const int window_w = window_rect.right - window_rect.left;
const int window_h = window_rect.bottom - window_rect.top;
const int client_w = client_rect.right - client_rect.left;
const int client_h = client_rect.bottom - client_rect.top;
// 边框(含标题栏)占用的额外像素。
const int border_w = window_w - client_w;
const int border_h = window_h - client_h;
// 保持窗口宽度不变,按比例计算客户区高度。
int target_client_w = client_w;
int target_client_h = static_cast<int>(target_client_w / aspect + 0.5);
int target_window_w = window_w;
int target_window_h = target_client_h + border_h;
// 获取窗口所在显示器的可用工作区。
HMONITOR monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
MONITORINFO monitor_info;
monitor_info.cbSize = sizeof(MONITORINFO);
GetMonitorInfo(monitor, &monitor_info);
const int work_h = monitor_info.rcWork.bottom - monitor_info.rcWork.top;
// 高度超出屏幕:改为以屏幕高度为准的合适窗口大小。
if (target_window_h > work_h) {
target_window_h = work_h;
target_client_h = target_window_h - border_h;
target_client_w = static_cast<int>(target_client_h * aspect + 0.5);
target_window_w = target_client_w + border_w;
}
// 计算位置:尽量保持当前左上角,同时确保窗口落在工作区内。
int new_left = window_rect.left;
int new_top = window_rect.top;
if (new_left + target_window_w > monitor_info.rcWork.right) {
new_left = monitor_info.rcWork.right - target_window_w;
}
if (new_top + target_window_h > monitor_info.rcWork.bottom) {
new_top = monitor_info.rcWork.bottom - target_window_h;
}
if (new_left < monitor_info.rcWork.left) {
new_left = monitor_info.rcWork.left;
}
if (new_top < monitor_info.rcWork.top) {
new_top = monitor_info.rcWork.top;
}
SetWindowPos(hwnd, nullptr, new_left, new_top, target_window_w,
target_window_h, SWP_NOZORDER | SWP_NOACTIVATE);
}
LRESULT
FlutterWindow::MessageHandler(HWND hwnd, UINT const message,
WPARAM const wparam,