Capture window or monitor with WindowsGraphicsCapture API.

Post your working scripts, libraries and tools for AHK v1.1 and older
malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Capture window or monitor with WindowsGraphicsCapture API.

Post by malcev » 30 Oct 2021, 09:56

Works on win10 build >= 19041 and also with hardware accelerated windows.
https://blogs.windows.com/windowsdeveloper/2019/09/16/new-ways-to-do-screen-capture/

Code: Select all

window_handle := 0x290538
; captureCursor := true
; hideBorder := true   ; removes frame from captured window, only for winver >= 20348

f11::
DllCall("QueryPerformanceCounter", "int64*", StartTime)
a := a_tickcount
if !init
{
   setbatchlines -1
   DllCall("LoadLibrary","str","DXGI")
   DllCall("LoadLibrary","str","D3D11")
   DllCall("LoadLibrary","str","Dwmapi")
   DllCall("LoadLibrary", "str", "gdiplus")
   VarSetCapacity(si, A_PtrSize = 8 ? 24 : 16, 0), si := Chr(1)
   DllCall("gdiplus\GdiplusStartup", "ptr*", pToken, "ptr", &si, "ptr", 0)
   VarSetCapacity(rect, 16, 0)
   DllCall("Dwmapi.dll\DwmGetWindowAttribute", "ptr", window_handle, "uint", DWMWA_EXTENDED_FRAME_BOUNDS := 9, "ptr", &rect, "uint", 16)
   width := NumGet(rect, 8, "int") - NumGet(rect, 0, "int")
   height := NumGet(rect, 12, "int") - NumGet(rect, 4, "int")
   DllCall("D3D11\D3D11CreateDevice", "ptr", 0, "int", D3D_DRIVER_TYPE_HARDWARE := 1, "ptr", 0, "uint", D3D11_CREATE_DEVICE_BGRA_SUPPORT := 0x20, "ptr", 0, "uint", 0, "uint", D3D11_SDK_VERSION := 7, "ptr*", d3d_device, "ptr*", 0, "ptr*", d3d_context)
   dxgiDevice := ComObjQuery(d3d_device, IID_IDXGIDevice := "{54ec77fa-1377-44e6-8c32-88fd5f44c84c}")
   DllCall("D3D11\CreateDirect3D11DeviceFromDXGIDevice", "ptr", dxgiDevice, "ptr*", inspectable)
   device := ComObjQuery(inspectable, IDirect3DDevice := "{A37624AB-8D5F-4650-9D3E-9EAE3D9BC670}")
   CreateClass("Windows.Graphics.Capture.Direct3D11CaptureFramePool", IDirect3D11CaptureFramePoolStatics := "{7784056a-67aa-4d53-ae54-1088d5a8ca21}", Direct3D11CaptureFramePoolStatics)
   DllCall(NumGet(NumGet(Direct3D11CaptureFramePoolStatics+0)+6*A_PtrSize), "ptr", Direct3D11CaptureFramePoolStatics, "ptr", device, "int", B8G8R8A8UIntNormalized := 87, "int", numberOfBuffers := 2, "int64", (height << 32) | width, "ptr*", frame_pool)   ; Direct3D11CaptureFramePool.Create
   CreateClass("Windows.Graphics.Capture.GraphicsCaptureItem", IGraphicsCaptureItemStatics := "{A87EBEA5-457C-5788-AB47-0CF1D3637E74}", GraphicsCaptureItemStatics)
   interop_factory := ComObjQuery(GraphicsCaptureItemStatics, IGraphicsCaptureItemInterop := "{3628E81B-3CAC-4C60-B7F4-23CE0E0C3356}")
   VarSetCapacity(GUID, 16, 0)
   DllCall("ole32\CLSIDFromString", "wstr", IGraphicsCaptureItem := "{79c3f95b-31f7-4ec2-a464-632ef5d30760}", "ptr", &GUID)
   hr := DllCall(NumGet(NumGet(interop_factory+0)+3*A_PtrSize), "ptr", interop_factory, "ptr", window_handle, "ptr", &GUID, "ptr*", capture_item, "uint")   ; IGraphicsCaptureItemInterop::CreateForWindow
   if hr
   {
      msgbox Cannot capture such a window.`nError: %hr%
      ExitApp
   }
   DllCall(NumGet(NumGet(frame_pool+0)+10*A_PtrSize), "ptr", frame_pool, "ptr", capture_item, "ptr*", session)   ; Direct3D11CaptureFramePool.CreateCaptureSession
   if (captureCursor != 1)
   {
      session2 := ComObjQuery(session, IGraphicsCaptureSession2 := "{2c39ae40-7d2e-5044-804e-8b6799d4cf9e}")
      DllCall(NumGet(NumGet(session2+0)+7*A_PtrSize), "ptr", session2, "int", 0)   ; GraphicsCaptureSession.IsCursorCaptureEnabled put
   }
   if (hideBorder = 1) and (StrSplit(A_OSVersion, ".")[3] >= 20348)
   {
      session3 := ComObjQuery(session, IGraphicsCaptureSession3 := "{f2cdd966-22ae-5ea1-9596-3a289344c3be}")
      DllCall(NumGet(NumGet(session3+0)+7*A_PtrSize), "ptr", session3, "int", 0)   ; GraphicsCaptureSession.IsBorderRequired put
   }
   DllCall(NumGet(NumGet(session+0)+6*A_PtrSize), "ptr", session)   ; GraphicsCaptureSession.StartCapture
}
loop
{
   DllCall(NumGet(NumGet(frame_pool+0)+7*A_PtrSize), "ptr", frame_pool, "ptr*", frame)   ; Direct3D11CaptureFramePool.TryGetNextFrame
   if (frame != 0)
   {
      DllCall(NumGet(NumGet(frame+0)+7*A_PtrSize), "ptr", frame, "int64*", SystemRelativeTime)   ; Direct3D11CaptureFrame.SystemRelativeTime
      if !init or (SystemRelativeTime >= StartTime)
         break
      Close := ComObjQuery(frame, IClosable := "{30D5A829-7FA4-4026-83BB-D75BAE4EA99E}")
      DllCall(NumGet(NumGet(Close+0)+6*A_PtrSize), "ptr", Close)   ; Close
      ObjRelease(Close)
      ObjRelease(frame)
   }
}
if !init
{
   DllCall(NumGet(NumGet(frame+0)+6*A_PtrSize), "ptr", frame, "ptr*", surface)   ; Direct3D11CaptureFrame.Surface
   access := ComObjQuery(surface, IDirect3DDxgiInterfaceAccess := "{A9B3D012-3DF2-4EE3-B8D1-8695F457D3C1}")
   VarSetCapacity(GUID, 16, 0)
   DllCall("ole32\CLSIDFromString", "wstr", IID_ID3D11Texture2D := "{6f15aaf2-d208-4e89-9ab4-489535d34f9c}", "ptr", &GUID)
   DllCall(NumGet(NumGet(access+0)+3*A_PtrSize), "ptr", access, "ptr", &GUID, "ptr*", texture)   ; IDirect3DDxgiInterfaceAccess::GetInterface
   VarSetCapacity(captured_texture_desc, 44, 0)
   DllCall(NumGet(NumGet(texture+0)+10*A_PtrSize), "ptr", texture, "ptr", &captured_texture_desc)   ; ID3D11Texture2D::GetDesc
   NumPut(D3D11_USAGE_STAGING := 3, captured_texture_desc, 28, "uint")   ; Usage
   NumPut(0, captured_texture_desc, 32, "uint")   ; BindFlags
   NumPut(D3D11_CPU_ACCESS_READ := 0x20000, captured_texture_desc, 36, "uint")   ; CPUAccessFlags
   NumPut(0, captured_texture_desc, 40, "uint")   ; MiscFlags
   DllCall(NumGet(NumGet(d3d_device+0)+5*A_PtrSize), "ptr", d3d_device, "ptr", &captured_texture_desc, "ptr", 0, "ptr*", user_texture)   ; ID3D11Device::CreateTexture2D
   init := 1 
}
DllCall(NumGet(NumGet(d3d_context+0)+47*A_PtrSize), "ptr", d3d_context, "ptr", user_texture, "ptr", texture)   ; ID3D11DeviceContext::CopyResource
VarSetCapacity(D3D11_MAPPED_SUBRESOURCE, 8+A_PtrSize, 0)
DllCall(NumGet(NumGet(d3d_context+0)+14*A_PtrSize), "ptr", d3d_context, "ptr", user_texture, "uint", 0, "uint", D3D11_MAP_READ := 1, "uint", 0, "ptr", &D3D11_MAPPED_SUBRESOURCE)   ; ID3D11DeviceContext::Map
pBits := NumGet(D3D11_MAPPED_SUBRESOURCE, 0, "ptr")
pitch := NumGet(D3D11_MAPPED_SUBRESOURCE, A_PtrSize, "uint")
msgbox % a_tickcount - a
DllCall("gdiplus\GdipCreateBitmapFromScan0", "int", width, "int", height, "int", pitch, "int", PixelFormat32bppRGB := 0x22009, "ptr", pBits, "ptr*", pBitmap)
DllCall("gdiplus\GdipCreateHBITMAPFromBitmap", "ptr", pBitmap, "ptr*", hBitmap, "uint", 0xffffffff)
Gui, Destroy
Gui, Add, Picture, vpic, HBITMAP:%hBitmap%
Gui, Show
DllCall("gdiplus\GdipDisposeImage", "ptr", pBitmap)
DllCall("DeleteObject", "ptr", hBitmap)
DllCall(NumGet(NumGet(d3d_context+0)+15*A_PtrSize), "ptr", d3d_context, "ptr", user_texture, "uint", 0)   ; ID3D11DeviceContext::Unmap
Close := ComObjQuery(frame, IClosable := "{30D5A829-7FA4-4026-83BB-D75BAE4EA99E}")
DllCall(NumGet(NumGet(Close+0)+6*A_PtrSize), "ptr", Close)   ; Close
ObjRelease(Close)
ObjRelease(frame)
return



CreateClass(string, interface, ByRef Class)
{
   CreateHString(string, hString)
   VarSetCapacity(GUID, 16)
   DllCall("ole32\CLSIDFromString", "wstr", interface, "ptr", &GUID)
   result := DllCall("Combase.dll\RoGetActivationFactory", "ptr", hString, "ptr", &GUID, "ptr*", Class, "uint")
   if (result != 0)
   {
      if (result = 0x80004002)
         msgbox No such interface supported
      else if (result = 0x80040154)
         msgbox Class not registered
      else
         msgbox error: %result%
      ExitApp
   }
   DeleteHString(hString)
}

CreateHString(string, ByRef hString)
{
    DllCall("Combase.dll\WindowsCreateString", "wstr", string, "uint", StrLen(string), "ptr*", hString)
}

DeleteHString(hString)
{
   DllCall("Combase.dll\WindowsDeleteString", "ptr", hString)
}
Example with capturing active window: (slow):

Code: Select all

; captureCursor := true
; hideBorder := true   ; removes frame from captured window, only for winver >= 20348

f11::
if !init
{
   setbatchlines -1
   DllCall("LoadLibrary","str","DXGI")
   DllCall("LoadLibrary","str","D3D11")
   DllCall("LoadLibrary","str","Dwmapi")
   DllCall("LoadLibrary", "str", "gdiplus")
   VarSetCapacity(si, A_PtrSize = 8 ? 24 : 16, 0), si := Chr(1)
   DllCall("gdiplus\GdiplusStartup", "ptr*", pToken, "ptr", &si, "ptr", 0)
   DllCall("D3D11\D3D11CreateDevice", "ptr", 0, "int", D3D_DRIVER_TYPE_HARDWARE := 1, "ptr", 0, "uint", D3D11_CREATE_DEVICE_BGRA_SUPPORT := 0x20, "ptr", 0, "uint", 0, "uint", D3D11_SDK_VERSION := 7, "ptr*", d3d_device, "ptr*", 0, "ptr*", d3d_context)
   dxgiDevice := ComObjQuery(d3d_device, IID_IDXGIDevice := "{54ec77fa-1377-44e6-8c32-88fd5f44c84c}")
   DllCall("D3D11\CreateDirect3D11DeviceFromDXGIDevice", "ptr", dxgiDevice, "ptr*", inspectable)
   device := ComObjQuery(inspectable, IDirect3DDevice := "{A37624AB-8D5F-4650-9D3E-9EAE3D9BC670}")
   CreateClass("Windows.Graphics.Capture.Direct3D11CaptureFramePool", IDirect3D11CaptureFramePoolStatics := "{7784056a-67aa-4d53-ae54-1088d5a8ca21}", Direct3D11CaptureFramePoolStatics)
   CreateClass("Windows.Graphics.Capture.GraphicsCaptureItem", IGraphicsCaptureItemStatics := "{A87EBEA5-457C-5788-AB47-0CF1D3637E74}", GraphicsCaptureItemStatics)
   interop_factory := ComObjQuery(GraphicsCaptureItemStatics, IGraphicsCaptureItemInterop := "{3628E81B-3CAC-4C60-B7F4-23CE0E0C3356}")
   VarSetCapacity(GraphicsCaptureItemGUID, 16, 0)
   DllCall("ole32\CLSIDFromString", "wstr", IGraphicsCaptureItem := "{79c3f95b-31f7-4ec2-a464-632ef5d30760}", "ptr", &GraphicsCaptureItemGUID)
   VarSetCapacity(D3D11Texture2DGUID, 16, 0)
   DllCall("ole32\CLSIDFromString", "wstr", IID_ID3D11Texture2D := "{6f15aaf2-d208-4e89-9ab4-489535d34f9c}", "ptr", &D3D11Texture2DGUID)
   init := 1
}
window_handle := WinExist("A")
VarSetCapacity(rect, 16, 0)
DllCall("Dwmapi.dll\DwmGetWindowAttribute", "ptr", window_handle, "uint", DWMWA_EXTENDED_FRAME_BOUNDS := 9, "ptr", &rect, "uint", 16)
width := NumGet(rect, 8, "int") - NumGet(rect, 0, "int")
height := NumGet(rect, 12, "int") - NumGet(rect, 4, "int")
DllCall(NumGet(NumGet(Direct3D11CaptureFramePoolStatics+0)+6*A_PtrSize), "ptr", Direct3D11CaptureFramePoolStatics, "ptr", device, "int", B8G8R8A8UIntNormalized := 87, "int", numberOfBuffers := 2, "int64", (height << 32) | width, "ptr*", frame_pool)   ; Direct3D11CaptureFramePool.Create
hr := DllCall(NumGet(NumGet(interop_factory+0)+3*A_PtrSize), "ptr", interop_factory, "ptr", window_handle, "ptr", &GraphicsCaptureItemGUID, "ptr*", capture_item, "uint")   ; IGraphicsCaptureItemInterop::CreateForWindow
if hr
{
   msgbox Cannot capture such a window.`nError: %hr%
   ObjReleaseClose(frame_pool)
   return
}
DllCall(NumGet(NumGet(frame_pool+0)+10*A_PtrSize), "ptr", frame_pool, "ptr", capture_item, "ptr*", session)   ; Direct3D11CaptureFramePool.CreateCaptureSession
if (captureCursor != 1)
{
   session2 := ComObjQuery(session, IGraphicsCaptureSession2 := "{2c39ae40-7d2e-5044-804e-8b6799d4cf9e}")
   DllCall(NumGet(NumGet(session2+0)+7*A_PtrSize), "ptr", session2, "int", 0)   ; GraphicsCaptureSession.IsCursorCaptureEnabled put
}
if (hideBorder = 1) and (StrSplit(A_OSVersion, ".")[3] >= 20348)
{
   session3 := ComObjQuery(session, IGraphicsCaptureSession3 := "{f2cdd966-22ae-5ea1-9596-3a289344c3be}")
   DllCall(NumGet(NumGet(session3+0)+7*A_PtrSize), "ptr", session3, "int", 0)   ; GraphicsCaptureSession.IsBorderRequired put
}
DllCall(NumGet(NumGet(session+0)+6*A_PtrSize), "ptr", session)   ; GraphicsCaptureSession.StartCapture
loop
{
   DllCall(NumGet(NumGet(frame_pool+0)+7*A_PtrSize), "ptr", frame_pool, "ptr*", frame)   ; Direct3D11CaptureFramePool.TryGetNextFrame
   if (frame != 0)
      break
}
DllCall(NumGet(NumGet(frame+0)+6*A_PtrSize), "ptr", frame, "ptr*", surface)   ; Direct3D11CaptureFrame.Surface
access := ComObjQuery(surface, IDirect3DDxgiInterfaceAccess := "{A9B3D012-3DF2-4EE3-B8D1-8695F457D3C1}")
DllCall(NumGet(NumGet(access+0)+3*A_PtrSize), "ptr", access, "ptr", &D3D11Texture2DGUID, "ptr*", texture)   ; IDirect3DDxgiInterfaceAccess::GetInterface
VarSetCapacity(captured_texture_desc, 44, 0)
DllCall(NumGet(NumGet(texture+0)+10*A_PtrSize), "ptr", texture, "ptr", &captured_texture_desc)   ; ID3D11Texture2D::GetDesc
NumPut(D3D11_USAGE_STAGING := 3, captured_texture_desc, 28, "uint")   ; Usage
NumPut(0, captured_texture_desc, 32, "uint")   ; BindFlags
NumPut(D3D11_CPU_ACCESS_READ := 0x20000, captured_texture_desc, 36, "uint")   ; CPUAccessFlags
NumPut(0, captured_texture_desc, 40, "uint")   ; MiscFlags
DllCall(NumGet(NumGet(d3d_device+0)+5*A_PtrSize), "ptr", d3d_device, "ptr", &captured_texture_desc, "ptr", 0, "ptr*", user_texture)   ; ID3D11Device::CreateTexture2D
DllCall(NumGet(NumGet(d3d_context+0)+47*A_PtrSize), "ptr", d3d_context, "ptr", user_texture, "ptr", texture)   ; ID3D11DeviceContext::CopyResource
VarSetCapacity(D3D11_MAPPED_SUBRESOURCE, 8+A_PtrSize, 0)
DllCall(NumGet(NumGet(d3d_context+0)+14*A_PtrSize), "ptr", d3d_context, "ptr", user_texture, "uint", 0, "uint", D3D11_MAP_READ := 1, "uint", 0, "ptr", &D3D11_MAPPED_SUBRESOURCE)   ; ID3D11DeviceContext::Map
pBits := NumGet(D3D11_MAPPED_SUBRESOURCE, 0, "ptr")
pitch := NumGet(D3D11_MAPPED_SUBRESOURCE, A_PtrSize, "uint")
DllCall("gdiplus\GdipCreateBitmapFromScan0", "int", width, "int", height, "int", pitch, "int", PixelFormat32bppRGB := 0x22009, "ptr", pBits, "ptr*", pBitmap)
DllCall("gdiplus\GdipCreateHBITMAPFromBitmap", "ptr", pBitmap, "ptr*", hBitmap, "uint", 0xffffffff)
Gui, Destroy
Gui, Add, Picture, vpic, HBITMAP:%hBitmap%
Gui, Show
DllCall("gdiplus\GdipDisposeImage", "ptr", pBitmap)
DllCall("DeleteObject", "ptr", hBitmap)
DllCall(NumGet(NumGet(d3d_context+0)+15*A_PtrSize), "ptr", d3d_context, "ptr", user_texture, "uint", 0)   ; ID3D11DeviceContext::Unmap
ObjReleaseClose(frame_pool)
ObjRelease(capture_item)
ObjReleaseClose(session)
if session2
{
   ObjReleaseClose(session2)
   session2 := ""
}
if session3
{
   ObjReleaseClose(session3)
   session3 := ""
}
ObjReleaseClose(frame)
ObjReleaseClose(surface)
ObjReleaseClose(access)
ObjRelease(texture)
ObjRelease(user_texture)
return



CreateClass(string, interface, ByRef Class)
{
   CreateHString(string, hString)
   VarSetCapacity(GUID, 16)
   DllCall("ole32\CLSIDFromString", "wstr", interface, "ptr", &GUID)
   result := DllCall("Combase.dll\RoGetActivationFactory", "ptr", hString, "ptr", &GUID, "ptr*", Class, "uint")
   if (result != 0)
   {
      if (result = 0x80004002)
         msgbox No such interface supported
      else if (result = 0x80040154)
         msgbox Class not registered
      else
         msgbox error: %result%
      ExitApp
   }
   DeleteHString(hString)
}

CreateHString(string, ByRef hString)
{
    DllCall("Combase.dll\WindowsCreateString", "wstr", string, "uint", StrLen(string), "ptr*", hString)
}

DeleteHString(hString)
{
   DllCall("Combase.dll\WindowsDeleteString", "ptr", hString)
}

ObjReleaseClose(ByRef Object)
{
   Close := ComObjQuery(Object, IClosable := "{30D5A829-7FA4-4026-83BB-D75BAE4EA99E}")
   DllCall(NumGet(NumGet(Close+0)+6*A_PtrSize), "ptr", Close)   ; Close
   ObjRelease(Close)
   ObjRelease(Object)
   Object := ""
}
Example with capturing monitor and saving it to file:

Code: Select all

hMonitor := DllCall("MonitorFromPoint", "int64", 0, "uint", MONITOR_DEFAULTTOPRIMARY := 1, "ptr")
width := a_screenwidth
height := a_screenheight
extension := "jpg"
filename := "test"
; captureCursor := true
; hideBorder := true   ; removes frame from captured window, only for winver >= 20348
return

f11::
DllCall("QueryPerformanceCounter", "int64*", StartTime)
if !init
{
   setbatchlines -1
   DllCall("LoadLibrary","str","DXGI")
   DllCall("LoadLibrary","str","D3D11")
   DllCall("LoadLibrary", "str", "gdiplus")
   VarSetCapacity(si, A_PtrSize = 8 ? 24 : 16, 0), si := Chr(1)
   DllCall("gdiplus\GdiplusStartup", "ptr*", pToken, "ptr", &si, "ptr", 0)
   DllCall("gdiplus\GdipGetImageEncodersSize", "uint*", count:=0, "uint*", size:=0)
   VarSetCapacity(ci, size)
   DllCall("gdiplus\GdipGetImageEncoders", "uint", count, "uint", size, "ptr", &ci)
   if !(count && size)
      throw Exception("Could not get a list of image codec encoders on this system.")
   Loop % count
      EncoderExtensions := StrGet(NumGet(ci, (idx:=(48+7*A_PtrSize)*(A_Index-1))+32+3*A_PtrSize, "uptr"), "UTF-16")
         until InStr(EncoderExtensions, "*." extension)
   if !(pCodec := &ci + idx)
      throw Exception("Could not find a matching encoder for the specified file format.")

   DllCall("D3D11\D3D11CreateDevice", "ptr", 0, "int", D3D_DRIVER_TYPE_HARDWARE := 1, "ptr", 0, "uint", D3D11_CREATE_DEVICE_BGRA_SUPPORT := 0x20, "ptr", 0, "uint", 0, "uint", D3D11_SDK_VERSION := 7, "ptr*", d3d_device, "ptr*", 0, "ptr*", d3d_context)
   dxgiDevice := ComObjQuery(d3d_device, IID_IDXGIDevice := "{54ec77fa-1377-44e6-8c32-88fd5f44c84c}")
   DllCall("D3D11\CreateDirect3D11DeviceFromDXGIDevice", "ptr", dxgiDevice, "ptr*", inspectable)
   device := ComObjQuery(inspectable, IDirect3DDevice := "{A37624AB-8D5F-4650-9D3E-9EAE3D9BC670}")
   CreateClass("Windows.Graphics.Capture.Direct3D11CaptureFramePool", IDirect3D11CaptureFramePoolStatics := "{7784056a-67aa-4d53-ae54-1088d5a8ca21}", Direct3D11CaptureFramePoolStatics)
   DllCall(NumGet(NumGet(Direct3D11CaptureFramePoolStatics+0)+6*A_PtrSize), "ptr", Direct3D11CaptureFramePoolStatics, "ptr", device, "int", B8G8R8A8UIntNormalized := 87, "int", numberOfBuffers := 2, "int64", (height << 32) | width, "ptr*", frame_pool)   ; Direct3D11CaptureFramePool.Create
   CreateClass("Windows.Graphics.Capture.GraphicsCaptureItem", IGraphicsCaptureItemStatics := "{A87EBEA5-457C-5788-AB47-0CF1D3637E74}", GraphicsCaptureItemStatics)
   interop_factory := ComObjQuery(GraphicsCaptureItemStatics, IGraphicsCaptureItemInterop := "{3628E81B-3CAC-4C60-B7F4-23CE0E0C3356}")
   VarSetCapacity(GUID, 16, 0)
   DllCall("ole32\CLSIDFromString", "wstr", IGraphicsCaptureItem := "{79c3f95b-31f7-4ec2-a464-632ef5d30760}", "ptr", &GUID)
   DllCall(NumGet(NumGet(interop_factory+0)+4*A_PtrSize), "ptr", interop_factory, "ptr", hMonitor, "ptr", &GUID, "ptr*", capture_item)   ; IGraphicsCaptureItemInterop::CreateForMonitor
   DllCall(NumGet(NumGet(frame_pool+0)+10*A_PtrSize), "ptr", frame_pool, "ptr", capture_item, "ptr*", session)   ; Direct3D11CaptureFramePool.CreateCaptureSession
   if (captureCursor != 1)
   {
      session2 := ComObjQuery(session, IGraphicsCaptureSession2 := "{2c39ae40-7d2e-5044-804e-8b6799d4cf9e}")
      DllCall(NumGet(NumGet(session2+0)+7*A_PtrSize), "ptr", session2, "int", 0)   ; GraphicsCaptureSession.IsCursorCaptureEnabled put
   }
   if (hideBorder = 1) and (StrSplit(A_OSVersion, ".")[3] >= 20348)
   {
      session3 := ComObjQuery(session, IGraphicsCaptureSession3 := "{f2cdd966-22ae-5ea1-9596-3a289344c3be}")
      DllCall(NumGet(NumGet(session3+0)+7*A_PtrSize), "ptr", session3, "int", 0)   ; GraphicsCaptureSession.IsBorderRequired put
   }
   DllCall(NumGet(NumGet(session+0)+6*A_PtrSize), "ptr", session)   ; GraphicsCaptureSession.StartCapture
}
loop
{
   DllCall(NumGet(NumGet(frame_pool+0)+7*A_PtrSize), "ptr", frame_pool, "ptr*", frame)   ; Direct3D11CaptureFramePool.TryGetNextFrame
   if (frame != 0)
   {
      DllCall(NumGet(NumGet(frame+0)+7*A_PtrSize), "ptr", frame, "int64*", SystemRelativeTime)   ; Direct3D11CaptureFrame.SystemRelativeTime
      if !init or (SystemRelativeTime >= StartTime)
         break
      Close := ComObjQuery(frame, IClosable := "{30D5A829-7FA4-4026-83BB-D75BAE4EA99E}")
      DllCall(NumGet(NumGet(Close+0)+6*A_PtrSize), "ptr", Close)   ; Close
      ObjRelease(Close)
      ObjRelease(frame)
   }
}
if !init
{
   DllCall(NumGet(NumGet(frame+0)+6*A_PtrSize), "ptr", frame, "ptr*", surface)   ; Direct3D11CaptureFrame.Surface
   access := ComObjQuery(surface, IDirect3DDxgiInterfaceAccess := "{A9B3D012-3DF2-4EE3-B8D1-8695F457D3C1}")
   VarSetCapacity(GUID, 16, 0)
   DllCall("ole32\CLSIDFromString", "wstr", IID_ID3D11Texture2D := "{6f15aaf2-d208-4e89-9ab4-489535d34f9c}", "ptr", &GUID)
   DllCall(NumGet(NumGet(access+0)+3*A_PtrSize), "ptr", access, "ptr", &GUID, "ptr*", texture)   ; IDirect3DDxgiInterfaceAccess::GetInterface
   VarSetCapacity(captured_texture_desc, 44, 0)
   DllCall(NumGet(NumGet(texture+0)+10*A_PtrSize), "ptr", texture, "ptr", &captured_texture_desc)   ; ID3D11Texture2D::GetDesc
   NumPut(D3D11_USAGE_STAGING := 3, captured_texture_desc, 28, "uint")   ; Usage
   NumPut(0, captured_texture_desc, 32, "uint")   ; BindFlags
   NumPut(D3D11_CPU_ACCESS_READ := 0x20000, captured_texture_desc, 36, "uint")   ; CPUAccessFlags
   NumPut(0, captured_texture_desc, 40, "uint")   ; MiscFlags
   DllCall(NumGet(NumGet(d3d_device+0)+5*A_PtrSize), "ptr", d3d_device, "ptr", &captured_texture_desc, "ptr", 0, "ptr*", user_texture)   ; ID3D11Device::CreateTexture2D
   init := 1 
}
DllCall(NumGet(NumGet(d3d_context+0)+47*A_PtrSize), "ptr", d3d_context, "ptr", user_texture, "ptr", texture)   ; ID3D11DeviceContext::CopyResource
VarSetCapacity(D3D11_MAPPED_SUBRESOURCE, 8+A_PtrSize, 0)
DllCall(NumGet(NumGet(d3d_context+0)+14*A_PtrSize), "ptr", d3d_context, "ptr", user_texture, "uint", 0, "uint", D3D11_MAP_READ := 1, "uint", 0, "ptr", &D3D11_MAPPED_SUBRESOURCE)   ; ID3D11DeviceContext::Map
pBits := NumGet(D3D11_MAPPED_SUBRESOURCE, 0, "ptr")
pitch := NumGet(D3D11_MAPPED_SUBRESOURCE, A_PtrSize, "uint")
DllCall("gdiplus\GdipCreateBitmapFromScan0", "int", width, "int", height, "int", pitch, "int", PixelFormat32bppRGB := 0x22009, "ptr", pBits, "ptr*", pBitmap)
DllCall("gdiplus\GdipSaveImageToFile", "ptr", pBitmap, "wstr", filename "." extension, "ptr", pCodec, "uint", 0)
DllCall("gdiplus\GdipDisposeImage", "ptr", pBitmap)
DllCall(NumGet(NumGet(d3d_context+0)+15*A_PtrSize), "ptr", d3d_context, "ptr", user_texture, "uint", 0)   ; ID3D11DeviceContext::Unmap
Close := ComObjQuery(frame, IClosable := "{30D5A829-7FA4-4026-83BB-D75BAE4EA99E}")
DllCall(NumGet(NumGet(Close+0)+6*A_PtrSize), "ptr", Close)   ; Close
ObjRelease(Close)
ObjRelease(frame)
return



CreateClass(string, interface, ByRef Class)
{
   CreateHString(string, hString)
   VarSetCapacity(GUID, 16)
   DllCall("ole32\CLSIDFromString", "wstr", interface, "ptr", &GUID)
   result := DllCall("Combase.dll\RoGetActivationFactory", "ptr", hString, "ptr", &GUID, "ptr*", Class, "uint")
   if (result != 0)
   {
      if (result = 0x80004002)
         msgbox No such interface supported
      else if (result = 0x80040154)
         msgbox Class not registered
      else
         msgbox error: %result%
      ExitApp
   }
   DeleteHString(hString)
}

CreateHString(string, ByRef hString)
{
    DllCall("Combase.dll\WindowsCreateString", "wstr", string, "uint", StrLen(string), "ptr*", hString)
}

DeleteHString(hString)
{
   DllCall("Combase.dll\WindowsDeleteString", "ptr", hString)
}
Last edited by malcev on 19 Apr 2023, 19:43, edited 5 times in total.

doubledave22
Posts: 343
Joined: 08 Jun 2019, 17:36

Re: Capture window with WindowsGraphicsCapture API.

Post by doubledave22 » 30 Oct 2021, 10:14

Awesome work! I don't know how you do it.

edit: forgot to change hwnd.

Thanks for taking the time to look at this! <3<3

doubledave22
Posts: 343
Joined: 08 Jun 2019, 17:36

Re: Capture window with WindowsGraphicsCapture API.

Post by doubledave22 » 30 Oct 2021, 10:44

There's definitely some quirks with this not really your fault but possibly solvable? I noticed in this script and from someone posting theirs here: https://www.generacodice.com/en/articolo/4457654/screen-capture-specific-window that the captured window gets a yellow border. Any way to get rid of this?

Also noticing that it's hard to capture a different window after the first is captured. This could be related to the above issue as well. Is is possible to change windows after first call? I changed over to this:

Code: Select all

f11::
window_handle := Winexist("A")
...
Lastly I am getting the no valid com object error for the one application that I'm having the most issues with.
Spoiler
This particular application window is no longer seen by any screen capture apps (OBSStudio, Windows snipping/printscreen, gyazo, etc) so not really sure if this would work anyway. However I have tested with other softwares I had problems with previously and it did work nicely. Let me know if any of the above issues are solvable

doubledave22
Posts: 343
Joined: 08 Jun 2019, 17:36

Re: Capture window with WindowsGraphicsCapture API.

Post by doubledave22 » 30 Oct 2021, 11:27

Tried cleaning things up a bit. Can switch windows nicely now. Only real issue that remains is the yellow border

Code: Select all

f11::
pBitmap := CreateForWindow(Winexist("A"))
DisplayBitmap(pBitmap)
DllCall("gdiplus\GdipDisposeImage", "ptr", pBitmap)
return

CreateForWindow(hwnd)
{
	Static DWMWA_EXTENDED_FRAME_BOUNDS := 9, D3D_DRIVER_TYPE_HARDWARE := 1, D3D11_CREATE_DEVICE_BGRA_SUPPORT := 0x20, D3D11_SDK_VERSION := 7
	, B8G8R8A8UIntNormalized := 87, numberOfBuffers := 2, D3D11_MAP_READ := 1, PixelFormat32bppRGB := 0x22009, D3D11_USAGE_STAGING := 3
	, D3D11_CPU_ACCESS_READ := 0x20000
	, IDirect3D11CaptureFramePoolStatics := "{7784056a-67aa-4d53-ae54-1088d5a8ca21}"
	, IDirect3DDevice := "{A37624AB-8D5F-4650-9D3E-9EAE3D9BC670}"
	, IID_IDXGIDevice := "{54ec77fa-1377-44e6-8c32-88fd5f44c84c}"
	, IGraphicsCaptureItemStatics := "{A87EBEA5-457C-5788-AB47-0CF1D3637E74}"
	, IGraphicsCaptureItemInterop := "{3628E81B-3CAC-4C60-B7F4-23CE0E0C3356}"
	, IGraphicsCaptureItem := "{79c3f95b-31f7-4ec2-a464-632ef5d30760}"
	, IGraphicsCaptureSession2 := "{2c39ae40-7d2e-5044-804e-8b6799d4cf9e}"
	, IClosable := "{30D5A829-7FA4-4026-83BB-D75BAE4EA99E}"
	, IDirect3DDxgiInterfaceAccess := "{A9B3D012-3DF2-4EE3-B8D1-8695F457D3C1}"
	, IID_ID3D11Texture2D := "{6f15aaf2-d208-4e89-9ab4-489535d34f9c}"
	
	DllCall("QueryPerformanceCounter", "int64*", StartTime)
	if !init
	{
		setbatchlines -1
		DllCall("LoadLibrary","str","DXGI")
		DllCall("LoadLibrary","str","D3D11")
		DllCall("LoadLibrary","str","Dwmapi")
		DllCall("LoadLibrary", "str", "gdiplus")
		VarSetCapacity(si, A_PtrSize = 8 ? 24 : 16, 0), si := Chr(1)
		DllCall("gdiplus\GdiplusStartup", "ptr*", pToken, "ptr", &si, "ptr", 0)
		VarSetCapacity(rect, 16, 0)
		DllCall("Dwmapi.dll\DwmGetWindowAttribute", "ptr", hwnd, "uint", DWMWA_EXTENDED_FRAME_BOUNDS, "ptr", &rect, "uint", 16)
		width := NumGet(rect, 8, "int") - NumGet(rect, 0, "int")
		height := NumGet(rect, 12, "int") - NumGet(rect, 4, "int")
		DllCall("D3D11\D3D11CreateDevice", "ptr", 0, "int", D3D_DRIVER_TYPE_HARDWARE, "ptr", 0, "uint", D3D11_CREATE_DEVICE_BGRA_SUPPORT, "ptr", 0, "uint", 0, "uint", D3D11_SDK_VERSION, "ptr*", d3d_device, "ptr*", 0, "ptr*", d3d_context)
		dxgiDevice := ComObjQuery(d3d_device, IID_IDXGIDevice)
		DllCall("D3D11\CreateDirect3D11DeviceFromDXGIDevice", "ptr", dxgiDevice, "ptr*", inspectable)
		device := ComObjQuery(inspectable, IDirect3DDevice)
		CreateClass("Windows.Graphics.Capture.Direct3D11CaptureFramePool", IDirect3D11CaptureFramePoolStatics, Direct3D11CaptureFramePoolStatics)
		DllCall(NumGet(NumGet(Direct3D11CaptureFramePoolStatics+0)+6*A_PtrSize), "ptr", Direct3D11CaptureFramePoolStatics, "ptr", device, "int", B8G8R8A8UIntNormalized, "int", numberOfBuffers, "int64", (height << 32) | width, "ptr*", frame_pool)   ; Direct3D11CaptureFramePool.Create
		CreateClass("Windows.Graphics.Capture.GraphicsCaptureItem", IGraphicsCaptureItemStatics, GraphicsCaptureItemStatics)
		interop_factory := ComObjQuery(GraphicsCaptureItemStatics, IGraphicsCaptureItemInterop)
		VarSetCapacity(GUID, 16, 0)
		DllCall("ole32\CLSIDFromString", "wstr", IGraphicsCaptureItem, "ptr", &GUID)
		DllCall(NumGet(NumGet(interop_factory+0)+3*A_PtrSize), "ptr", interop_factory, "ptr", hwnd, "ptr", &GUID, "ptr*", capture_item)   ; IGraphicsCaptureItemInterop::CreateForWindow

		DllCall(NumGet(NumGet(frame_pool+0)+10*A_PtrSize), "ptr", frame_pool, "ptr", capture_item, "ptr*", session)   ; Direct3D11CaptureFramePool.CreateCaptureSession
		if (captureCursor != 1)
		{
		  session2 := ComObjQuery(session, IGraphicsCaptureSession2)
		  DllCall(NumGet(NumGet(session2+0)+7*A_PtrSize), "ptr", session2, "int", 0)   ; GraphicsCaptureSession.IsCursorCaptureEnabled put
		}
		;   if (showBorder != 1)   ; cannot test winver should be >= 20348 
		;   {
		;      CreateClass("Windows.Graphics.Capture.GraphicsCaptureAccess", IGraphicsCaptureAccessStatics := "{743ed370-06ec-5040-a58a-901f0f757095}", GraphicsCaptureAccessStatics)
		;      msgbox % session3 := ComObjQuery(session, IGraphicsCaptureSession3 := "{f2cdd966-22ae-5ea1-9596-3a289344c3be}")
		;      msgbox % DllCall(NumGet(NumGet(session3+0)+6*A_PtrSize), "ptr", session3, "int*", bool)   ; GraphicsCaptureSession.IsBorderRequired get
		;      msgbox % bool
		;      msgbox % DllCall(NumGet(NumGet(session3+0)+7*A_PtrSize), "ptr", session3, "int", 0)   ; GraphicsCaptureSession.IsBorderRequired put
		;   }
		DllCall(NumGet(NumGet(session+0)+6*A_PtrSize), "ptr", session)   ; GraphicsCaptureSession.StartCapture
	}
	loop
	{
		DllCall(NumGet(NumGet(frame_pool+0)+7*A_PtrSize), "ptr", frame_pool, "ptr*", frame)   ; Direct3D11CaptureFramePool.TryGetNextFrame
		if (frame != 0)
		{
			DllCall(NumGet(NumGet(frame+0)+7*A_PtrSize), "ptr", frame, "int64*", SystemRelativeTime)   ; Direct3D11CaptureFrame.SystemRelativeTime
			if !init or (SystemRelativeTime >= StartTime)
			 break
			Close := ComObjQuery(frame, IClosable)
			DllCall(NumGet(NumGet(Close+0)+6*A_PtrSize), "ptr", Close)   ; Close
			ObjRelease(Close)
			ObjRelease(frame)
	    }
	}
	if !init
	{
		DllCall(NumGet(NumGet(frame+0)+6*A_PtrSize), "ptr", frame, "ptr*", surface)   ; Direct3D11CaptureFrame.Surface
		access := ComObjQuery(surface, IDirect3DDxgiInterfaceAccess)
		VarSetCapacity(GUID, 16, 0)
		DllCall("ole32\CLSIDFromString", "wstr", IID_ID3D11Texture2D, "ptr", &GUID)
		DllCall(NumGet(NumGet(access+0)+3*A_PtrSize), "ptr", access, "ptr", &GUID, "ptr*", texture)   ; IDirect3DDxgiInterfaceAccess::GetInterface
		VarSetCapacity(captured_texture_desc, 44, 0)
		DllCall(NumGet(NumGet(texture+0)+10*A_PtrSize), "ptr", texture, "ptr", &captured_texture_desc)   ; ID3D11Texture2D::GetDesc
		NumPut(D3D11_USAGE_STAGING, captured_texture_desc, 28, "uint")   ; Usage
		NumPut(0, captured_texture_desc, 32, "uint")   ; BindFlags
		NumPut(D3D11_CPU_ACCESS_READ, captured_texture_desc, 36, "uint")   ; CPUAccessFlags
		NumPut(0, captured_texture_desc, 40, "uint")   ; MiscFlags
		DllCall(NumGet(NumGet(d3d_device+0)+5*A_PtrSize), "ptr", d3d_device, "ptr", &captured_texture_desc, "ptr", 0, "ptr*", user_texture)   ; ID3D11Device::CreateTexture2D
		init := 1 
	}
	DllCall(NumGet(NumGet(d3d_context+0)+47*A_PtrSize), "ptr", d3d_context, "ptr", user_texture, "ptr", texture)   ; ID3D11DeviceContext::CopyResource
	VarSetCapacity(D3D11_MAPPED_SUBRESOURCE, 8+A_PtrSize, 0)
	DllCall(NumGet(NumGet(d3d_context+0)+14*A_PtrSize), "ptr", d3d_context, "ptr", user_texture, "uint", 0, "uint", D3D11_MAP_READ, "uint", 0, "ptr", &D3D11_MAPPED_SUBRESOURCE)   ; ID3D11DeviceContext::Map
	pBits := NumGet(D3D11_MAPPED_SUBRESOURCE, 0, "ptr")
	pitch := NumGet(D3D11_MAPPED_SUBRESOURCE, A_PtrSize, "uint")
	DllCall("gdiplus\GdipCreateBitmapFromScan0", "int", width, "int", height, "int", pitch, "int", PixelFormat32bppRGB, "ptr", pBits, "ptr*", pBitmap)
	DllCall(NumGet(NumGet(d3d_context+0)+15*A_PtrSize), "ptr", d3d_context, "ptr", user_texture, "uint", 0)   ; ID3D11DeviceContext::Unmap
	Close := ComObjQuery(frame, IClosable)
	DllCall(NumGet(NumGet(Close+0)+6*A_PtrSize), "ptr", Close)   ; Close
	ObjRelease(Close)
	ObjRelease(frame)
	return pBitmap
}

DisplayBitmap(pBitmap)
{
	Gui, 99:+LastFoundExist
	IfWinExist
		gui, 99: Destroy
	
	DllCall("gdiplus\GdipCreateHBITMAPFromBitmap", "ptr", pBitmap, "ptr*", hBitmap, "uint", 0xffffffff)

	Gui,99: Add, Picture,0xE, HBITMAP:%hBitmap%
	Gui,99: Show

	DllCall("DeleteObject", "ptr", hBitmap)
}

CreateClass(string, interface, ByRef Class)
{
   CreateHString(string, hString)
   VarSetCapacity(GUID, 16)
   DllCall("ole32\CLSIDFromString", "wstr", interface, "ptr", &GUID)
   result := DllCall("Combase.dll\RoGetActivationFactory", "ptr", hString, "ptr", &GUID, "ptr*", Class, "uint")
   if (result != 0)
   {
      if (result = 0x80004002)
         msgbox No such interface supported
      else if (result = 0x80040154)
         msgbox Class not registered
      else
         msgbox error: %result%
      ExitApp
   }
   DeleteHString(hString)
}

CreateHString(string, ByRef hString)
{
    DllCall("Combase.dll\WindowsCreateString", "wstr", string, "uint", StrLen(string), "ptr*", hString)
}

DeleteHString(hString)
{
   DllCall("Combase.dll\WindowsDeleteString", "ptr", hString)
}
edit: ^^ this needs a lot of work since basically ignoring init completely to allow switching of windows.

malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: Capture window with WindowsGraphicsCapture API.

Post by malcev » 30 Oct 2021, 11:40

You do not free objects in Your code.
I added example in 1 post.
Yellow border You can remove only from win version >= 20348.
Therefore need to wait.

malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: Capture window with WindowsGraphicsCapture API.

Post by malcev » 30 Oct 2021, 11:51

This particular application window is no longer seen by any screen capture apps
I think that any application can be captured, just need to use right algorithm.

doubledave22
Posts: 343
Joined: 08 Jun 2019, 17:36

Re: Capture window with WindowsGraphicsCapture API.

Post by doubledave22 » 30 Oct 2021, 12:03

malcev wrote:
30 Oct 2021, 11:51
This particular application window is no longer seen by any screen capture apps
I think that any application can be captured, just need to use right algorithm.
That's what it said in the docs for this api, just getting the comobject error i put in spoiler when trying so that's a bit beyond me for now.

Tried the active window example and it's definitely a lot slower (4x or so) so I'm sure there's optimizations to be made. Perhaps some others can take a look too. I will revisit in the future when the yellow border can be removed. Thanks again!

malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: Capture window with WindowsGraphicsCapture API.

Post by malcev » 30 Oct 2021, 12:18

Tried the active window example and it's definitely a lot slower (4x or so) so I'm sure there's optimizations to be made
No.
There is cannot be any optimization.
When You change window You need to recreate practically all objects.
This api is not for capturing different windows in random order.
About Your error I think You just cannot get GraphicsCaptureItem for Your window.
https://docs.microsoft.com/en-us/window ... eforwindow

doubledave22
Posts: 343
Joined: 08 Jun 2019, 17:36

Re: Capture window with WindowsGraphicsCapture API.

Post by doubledave22 » 30 Oct 2021, 12:24

malcev wrote:
30 Oct 2021, 12:18
Tried the active window example and it's definitely a lot slower (4x or so) so I'm sure there's optimizations to be made
No.
There is cannot be any optimization.
When You change window You need to recreate all objects.
This api is not for capturing different windows in random order.
About Your error I think You just cannot get GraphicsCaptureItem for Your window.
https://docs.microsoft.com/en-us/window ... eforwindow
I see. Could I open a class instance for each window I want to monitor and then use the faster example? Or can I only monitor one window (or display) at a time with this api?

Btw, I tried testing the Simple Screen Recorder app based on this api and it can't pick up the problem application window either (shows all black).

malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: Capture window with WindowsGraphicsCapture API.

Post by malcev » 30 Oct 2021, 12:26

You can try to run several ahk scripts with the same code.

guest3456
Posts: 3454
Joined: 09 Oct 2013, 10:31

Re: Capture window with WindowsGraphicsCapture API.

Post by guest3456 » 30 Oct 2021, 14:23

why is the active window slower?


malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: Capture window with WindowsGraphicsCapture API.

Post by malcev » 30 Oct 2021, 14:35

Because when We change window We need to destroy and recreate frame_pool and other objects.

Chappier
Posts: 44
Joined: 21 Aug 2021, 21:58

Re: Capture window with WindowsGraphicsCapture API.

Post by Chappier » 21 Jan 2022, 14:37

Run a notepad, set transparency on it, capture with your function

Code: Select all

WinSet, Transparent, 100, Untitled - Notepad
WinSet, AlwaysOnTop, On, Untitled - Notepad
Then save the image to disk:

Code: Select all

DllCall("gdiplus\GdipCreateBitmapFromScan0", "int", width, "int", height, "int", pitch, "int", PixelFormat32bppRGB := 0x22009, "ptr", pBits, "ptr*", pBitmap)
But the saved picture doesn't contain the same transparency as the window.
Doesn't support transparency?


Chappier
Posts: 44
Joined: 21 Aug 2021, 21:58

Re: Capture window with WindowsGraphicsCapture API.

Post by Chappier » 22 Jan 2022, 14:08

Thanks, i have read it but I don't understand much about how its work.
I wonder if you could add support to this option in your function?

malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: Capture window with WindowsGraphicsCapture API.

Post by malcev » 22 Jan 2022, 14:17

Make 2 screenshots with black background and white background, after that calculate alpha channel value for each pixel.
I do not need it and not interested in doing this.

malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: Capture window or monitor with WindowsGraphicsCapture API.

Post by malcev » 17 Mar 2023, 13:50

Added example for capturing monitor.

refrain
Posts: 5
Joined: 17 Mar 2023, 00:18

Re: Capture window or monitor with WindowsGraphicsCapture API.

Post by refrain » 07 Apr 2023, 01:34

Yes, the code works fine on Win10 but fails on Win7 at this line. Any way to make work across Win7 and Win10?
malcev wrote:
30 Oct 2021, 09:56

Code: Select all

   device := ComObjQuery(inspectable, IDirect3DDevice := "{A37624AB-8D5F-4650-9D3E-9EAE3D9BC670}")

malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: Capture window or monitor with WindowsGraphicsCapture API.

Post by malcev » 07 Apr 2023, 03:48

This api does not work on Win7.

refrain
Posts: 5
Joined: 17 Mar 2023, 00:18

Re: Capture window or monitor with WindowsGraphicsCapture API.

Post by refrain » 07 Apr 2023, 23:37

Thanks for your reply!

Still looking forward to win7 solutions.
malcev wrote:
07 Apr 2023, 03:48
This api does not work on Win7.

Post Reply

Return to “Scripts and Functions (v1)”