mirror of
https://github.com/Blinue/Magpie.git
synced 2026-06-24 02:04:10 +00:00
fix: 修复部分游戏缩放后 Alt+Tab 列表中出现两个窗口的情况
This commit is contained in:
parent
9aae602d45
commit
dbedf20f34
2 changed files with 63 additions and 10 deletions
|
|
@ -153,14 +153,15 @@ bool GraphicsCaptureFrameSource::_CaptureWindow(IGraphicsCaptureItemInterop* int
|
|||
}
|
||||
|
||||
// 尝试设置源窗口样式,因为 WGC 只能捕获位于 Alt+Tab 列表中的窗口
|
||||
LONG_PTR srcWndExStyle = GetWindowLongPtr(hwndSrc, GWL_EXSTYLE);
|
||||
if ((srcWndExStyle & WS_EX_APPWINDOW) == 0) {
|
||||
LONG_PTR srcExStyle = GetWindowLongPtr(hwndSrc, GWL_EXSTYLE);
|
||||
if ((srcExStyle & WS_EX_APPWINDOW) == 0) {
|
||||
// 添加 WS_EX_APPWINDOW 样式,确保源窗口可被 Alt+Tab 选中
|
||||
if (SetWindowLongPtr(hwndSrc, GWL_EXSTYLE, srcWndExStyle | WS_EX_APPWINDOW)) {
|
||||
if (SetWindowLongPtr(hwndSrc, GWL_EXSTYLE, srcExStyle | WS_EX_APPWINDOW)) {
|
||||
Logger::Get().Info("已改变源窗口样式");
|
||||
_originalSrcWndExStyle = srcWndExStyle;
|
||||
_originalSrcExStyle = srcExStyle;
|
||||
|
||||
if (_TryCreateGraphicsCaptureItem(interop, hwndSrc)) {
|
||||
_RemoveOwnerFromAltTabList(hwndSrc);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
|
|
@ -176,6 +177,7 @@ bool GraphicsCaptureFrameSource::_CaptureWindow(IGraphicsCaptureItemInterop* int
|
|||
Logger::Get().Info("已添加任务栏图标");
|
||||
|
||||
if (_TryCreateGraphicsCaptureItem(interop, hwndSrc)) {
|
||||
_RemoveOwnerFromAltTabList(hwndSrc);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
|
|
@ -192,9 +194,15 @@ bool GraphicsCaptureFrameSource::_CaptureWindow(IGraphicsCaptureItemInterop* int
|
|||
_taskbarList->DeleteTab(hwndSrc);
|
||||
_taskbarList = nullptr;
|
||||
}
|
||||
if (_originalSrcWndExStyle) {
|
||||
SetWindowLongPtr(hwndSrc, GWL_EXSTYLE, _originalSrcWndExStyle);
|
||||
_originalSrcWndExStyle = 0;
|
||||
if (_originalSrcExStyle) {
|
||||
// 首先还原所有者窗口的样式以压制任务栏的动画
|
||||
if (_originalOwnerExStyle) {
|
||||
SetWindowLongPtr(GetWindowOwner(hwndSrc), GWL_EXSTYLE, _originalOwnerExStyle);
|
||||
_originalOwnerExStyle = 0;
|
||||
}
|
||||
|
||||
SetWindowLongPtr(hwndSrc, GWL_EXSTYLE, _originalSrcExStyle);
|
||||
_originalSrcExStyle = 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
@ -219,6 +227,43 @@ bool GraphicsCaptureFrameSource::_TryCreateGraphicsCaptureItem(IGraphicsCaptureI
|
|||
return true;
|
||||
}
|
||||
|
||||
// 部分使用 Kirikiri 引擎的游戏有着这样的架构:游戏窗口并非根窗口,它被一个尺寸为 0 的窗口
|
||||
// 所有。此时 Alt+Tab 列表中的窗口和任务栏图标实际上是所有者窗口,这会导致 WGC 捕获游戏窗
|
||||
// 口时失败。_CaptureWindow 在初次捕获失败后会将 WS_EX_APPWINDOW 样式添加到游戏窗口,这
|
||||
// 可以工作,但也导致所有者窗口和游戏窗口同时出现 Alt+Tab 列表中,引起用户的困惑。
|
||||
//
|
||||
// 此函数检测这种情况并改变所有者窗口的样式使它不会出现在 Alt+Tab 列表中。
|
||||
void GraphicsCaptureFrameSource::_RemoveOwnerFromAltTabList(HWND hwndSrc) noexcept {
|
||||
HWND hwndOwner = GetWindowOwner(hwndSrc);
|
||||
if (!hwndOwner) {
|
||||
return;
|
||||
}
|
||||
|
||||
RECT ownerRect{};
|
||||
if (!GetWindowRect(hwndOwner, &ownerRect)) {
|
||||
Logger::Get().Win32Error("GetWindowRect 失败");
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查所有者窗口尺寸
|
||||
if (ownerRect.right != ownerRect.left || ownerRect.bottom != ownerRect.top) {
|
||||
return;
|
||||
}
|
||||
|
||||
LONG_PTR ownerExStyle = GetWindowLongPtr(hwndOwner, GWL_EXSTYLE);
|
||||
if (ownerExStyle == 0) {
|
||||
Logger::Get().Win32Error("GetWindowLongPtr 失败");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!SetWindowLongPtr(hwndOwner, GWL_EXSTYLE, ownerExStyle | WS_EX_TOOLWINDOW)) {
|
||||
Logger::Get().Win32Error("SetWindowLongPtr 失败");
|
||||
return;
|
||||
}
|
||||
|
||||
_originalOwnerExStyle = ownerExStyle;
|
||||
}
|
||||
|
||||
bool GraphicsCaptureFrameSource::_CaptureMonitor(IGraphicsCaptureItemInterop* interop) {
|
||||
// WDA_EXCLUDEFROMCAPTURE 只在 Win10 20H1 及更新版本中可用
|
||||
if (!Win32Utils::GetOSVersion().Is20H1OrNewer()) {
|
||||
|
|
@ -354,8 +399,13 @@ GraphicsCaptureFrameSource::~GraphicsCaptureFrameSource() {
|
|||
}
|
||||
|
||||
// 还原源窗口样式
|
||||
if (_originalSrcWndExStyle) {
|
||||
SetWindowLongPtr(hwndSrc, GWL_EXSTYLE, _originalSrcWndExStyle);
|
||||
if (_originalSrcExStyle) {
|
||||
// 首先还原所有者窗口的样式以压制任务栏的动画
|
||||
if (_originalOwnerExStyle) {
|
||||
SetWindowLongPtr(GetWindowOwner(hwndSrc), GWL_EXSTYLE, _originalOwnerExStyle);
|
||||
}
|
||||
|
||||
SetWindowLongPtr(hwndSrc, GWL_EXSTYLE, _originalSrcExStyle);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue