22
33#if MAA_FRAMEPOOL_SCREENCAP_AVAILABLE
44
5+ #include < dwmapi.h>
56#include < windows.graphics.capture.interop.h>
67#include < windows.graphics.directx.direct3d11.interop.h>
78#include < winrt/Windows.Foundation.Metadata.h>
@@ -110,46 +111,33 @@ std::optional<cv::Mat> FramePoolScreencap::screencap()
110111
111112 cv::Mat raw (texture_desc_.Height , texture_desc_.Width , CV_8UC4, mapped.pData , mapped.RowPitch );
112113
113- // 先按 alpha 通道裁剪掉四周 alpha != 255 的边框
114- cv::Mat alpha_channel;
115- cv::extractChannel (raw, alpha_channel, 3 );
116-
117- cv::Mat alpha_bin;
118- cv::threshold (alpha_channel, alpha_bin, UCHAR_MAX - 1 , UCHAR_MAX, cv::THRESH_BINARY);
119-
120- cv::Rect alpha_roi = cv::boundingRect (alpha_bin);
121- if (alpha_roi.empty ()) {
122- LogError << " No opaque pixels found" ;
123- return std::nullopt ;
124- }
125- cv::Mat trimmed = raw (alpha_roi);
126-
127- // 获取窗口客户区矩形(相对于窗口)
128114 RECT client_rect = { 0 };
129115 if (!GetClientRect (hwnd_, &client_rect)) {
130116 LogError << " GetClientRect failed" ;
131117 return std::nullopt ;
132118 }
133119
134- // 将客户区左上角转换为屏幕坐标
135120 POINT client_top_left = { client_rect.left , client_rect.top };
136121 if (!ClientToScreen (hwnd_, &client_top_left)) {
137122 LogError << " ClientToScreen failed" ;
138123 return std::nullopt ;
139124 }
140125
141- // 获取窗口矩形(屏幕坐标)
142- RECT window_rect = { 0 };
143- if (!GetWindowRect (hwnd_, &window_rect)) {
144- LogError << " GetWindowRect failed" ;
145- return std::nullopt ;
126+ // 使用 DWM 实际可视帧边界,排除 GetWindowRect 中包含的不可见 DWM 阴影区域,
127+ // 以正确计算 WGC 捕获画面中的边框偏移
128+ RECT frame_rect = { 0 };
129+ HRESULT hr = DwmGetWindowAttribute (hwnd_, DWMWA_EXTENDED_FRAME_BOUNDS, &frame_rect, sizeof (frame_rect));
130+ if (FAILED (hr)) {
131+ LogWarn << " DwmGetWindowAttribute failed, falling back to GetWindowRect" << VAR (hr);
132+ if (!GetWindowRect (hwnd_, &frame_rect)) {
133+ LogError << " GetWindowRect failed" ;
134+ return std::nullopt ;
135+ }
146136 }
147137
148- // 计算边框位置,减去 alpha 裁剪的偏移
149- int border_left = client_top_left.x - window_rect.left - alpha_roi.x ;
150- int border_top = client_top_left.y - window_rect.top - alpha_roi.y ;
138+ int border_left = client_top_left.x - frame_rect.left ;
139+ int border_top = client_top_left.y - frame_rect.top ;
151140
152- // 获取客户区大小
153141 int client_width = client_rect.right - client_rect.left ;
154142 int client_height = client_rect.bottom - client_rect.top ;
155143
@@ -159,22 +147,21 @@ std::optional<cv::Mat> FramePoolScreencap::screencap()
159147 if (border_top < 0 ) {
160148 border_top = 0 ;
161149 }
162- if (client_width > trimmed .cols ) {
163- client_width = trimmed .cols ;
150+ if (client_width > raw .cols ) {
151+ client_width = raw .cols ;
164152 }
165- if (border_left + client_width > trimmed .cols ) {
166- border_left = trimmed .cols - client_width;
153+ if (border_left + client_width > raw .cols ) {
154+ border_left = raw .cols - client_width;
167155 }
168- if (client_height > trimmed .rows ) {
169- client_height = trimmed .rows ;
156+ if (client_height > raw .rows ) {
157+ client_height = raw .rows ;
170158 }
171- if (border_top + client_height > trimmed .rows ) {
172- border_top = trimmed .rows - client_height;
159+ if (border_top + client_height > raw .rows ) {
160+ border_top = raw .rows - client_height;
173161 }
174162
175- // 裁剪出客户区(去掉边框)
176163 cv::Rect client_roi (border_left, border_top, client_width, client_height);
177- cv::Mat image = trimmed (client_roi);
164+ cv::Mat image = raw (client_roi);
178165
179166 cv::Mat result = bgra_to_bgr (image);
180167 cached_image_ = result.clone ();
0 commit comments