Skip to content

Commit 92a2e95

Browse files
committed
Replace Win32 screenshot with cross-platform Slate capture
- Remove Windows.h include and all Win32 API calls (PrintWindow, BitBlt, GetDIBits, HWND, HDC, HBITMAP) - Use FSlateApplication::TakeScreenshot for window mode capture - Works on Windows, Linux, and macOS without platform-specific code - Captures Blueprint graphs, Material editors, Data Tables, and all Slate-rendered UI panels - Viewport mode still uses ReadPixels (unchanged, always cross-platform)
1 parent e52db97 commit 92a2e95

1 file changed

Lines changed: 10 additions & 61 deletions

File tree

Source/UnrealMCPBridge/Private/Commands/EpicUnrealMCPEditorCommands.cpp

Lines changed: 10 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,6 @@
1212
#include "IImageWrapperModule.h"
1313
#include "Framework/Application/SlateApplication.h"
1414

15-
#include "Windows/AllowWindowsPlatformTypes.h"
16-
#include <Windows.h>
17-
#include "Windows/HideWindowsPlatformTypes.h"
1815

1916
#include "GameFramework/Actor.h"
2017
#include "Engine/Selection.h"
@@ -589,7 +586,7 @@ TSharedPtr<FJsonObject> FEpicUnrealMCPEditorCommands::HandleTakeScreenshot(
589586

590587
if (Mode == TEXT("window"))
591588
{
592-
// Capture the entire active editor window via Windows API (DWM)
589+
// Find the active editor window
593590
TSharedPtr<SWindow> Window = FSlateApplication::Get().GetActiveTopLevelWindow();
594591

595592
// Fall back to the first visible window if editor lost focus
@@ -608,68 +605,20 @@ TSharedPtr<FJsonObject> FEpicUnrealMCPEditorCommands::HandleTakeScreenshot(
608605
return FEpicUnrealMCPCommonUtils::CreateErrorResponse(TEXT("No editor window found"));
609606
}
610607

611-
TSharedPtr<FGenericWindow> NativeWindow = Window->GetNativeWindow();
612-
if (!NativeWindow.IsValid())
613-
{
614-
return FEpicUnrealMCPCommonUtils::CreateErrorResponse(TEXT("No native OS window handle"));
615-
}
616-
617-
HWND Hwnd = reinterpret_cast<HWND>(NativeWindow->GetOSWindowHandle());
618-
if (!Hwnd)
619-
{
620-
return FEpicUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Invalid OS window handle"));
621-
}
622-
623-
// Client area dimensions (excludes OS title bar / borders)
624-
RECT ClientRect;
625-
::GetClientRect(Hwnd, &ClientRect);
626-
Width = ClientRect.right - ClientRect.left;
627-
Height = ClientRect.bottom - ClientRect.top;
628-
629-
if (Width <= 0 || Height <= 0)
630-
{
631-
return FEpicUnrealMCPCommonUtils::CreateErrorResponse(
632-
TEXT("Window has invalid size (may be minimized)"));
633-
}
634-
635-
// Create a memory DC + bitmap to receive the capture
636-
HDC WindowDC = ::GetDC(Hwnd);
637-
HDC MemDC = ::CreateCompatibleDC(WindowDC);
638-
HBITMAP HBitmap = ::CreateCompatibleBitmap(WindowDC, Width, Height);
639-
HBITMAP OldBitmap = static_cast<HBITMAP>(::SelectObject(MemDC, HBitmap));
640-
641-
// PW_RENDERFULLCONTENT captures D3D/DWM content
642-
const UINT PW_RENDERFULLCONTENT_FLAG = 0x00000002;
643-
BOOL bCaptured = ::PrintWindow(Hwnd, MemDC, PW_RENDERFULLCONTENT_FLAG);
608+
// Use Slate TakeScreenshot — cross-platform, captures the full editor window
609+
// including BP graphs, material editors, data tables, and all Slate UI
610+
FIntVector Size;
611+
bool bCaptureSuccess = FSlateApplication::Get().TakeScreenshot(
612+
Window.ToSharedRef(), Pixels, Size);
644613

645-
if (!bCaptured)
646-
{
647-
::BitBlt(MemDC, 0, 0, Width, Height, WindowDC, 0, 0, SRCCOPY);
648-
}
649-
650-
// Read pixel data from the bitmap (top-down BGRA)
651-
BITMAPINFOHEADER BMI = {};
652-
BMI.biSize = sizeof(BITMAPINFOHEADER);
653-
BMI.biWidth = Width;
654-
BMI.biHeight = -Height;
655-
BMI.biPlanes = 1;
656-
BMI.biBitCount = 32;
657-
BMI.biCompression = BI_RGB;
658-
659-
Pixels.SetNum(Width * Height);
660-
::GetDIBits(MemDC, HBitmap, 0, Height, Pixels.GetData(),
661-
reinterpret_cast<BITMAPINFO*>(&BMI), DIB_RGB_COLORS);
662-
663-
::SelectObject(MemDC, OldBitmap);
664-
::DeleteObject(HBitmap);
665-
::DeleteDC(MemDC);
666-
::ReleaseDC(Hwnd, WindowDC);
667-
668-
if (Pixels.Num() == 0)
614+
if (!bCaptureSuccess || Pixels.Num() == 0)
669615
{
670616
return FEpicUnrealMCPCommonUtils::CreateErrorResponse(
671617
TEXT("Failed to capture editor window"));
672618
}
619+
620+
Width = Size.X;
621+
Height = Size.Y;
673622
}
674623
else
675624
{

0 commit comments

Comments
 (0)