WGC API的缺点是,绑定窗口都会有窗口线

; https://www.autohotkey.com/boards/viewtopic.php?f=6&t=96161
#NoEnv
SetBatchLines -1
SetWorkingDir %A_ScriptDir%
; 适用于 win10 1903 >= 18362 以及硬件加速窗口。

Return

F1::
window_handle := WinExist("ahk_class AHKEditor")
计时()
Critical
Loop 50
    hBitmap := WGCAPI后台窗口截图(window_handle)
Critical Off
ToolTip % "耗时:" Round(计时()) " 毫秒"   ; 一次次截图:9~20,连续截:7
; Gui, Destroy
; Gui, Add, Picture, , HBITMAP:%hBitmap%
; Gui, Show
Return


; hideBorder := true    ; 从捕获的窗口中删除框架,仅适用于winver >= 20348
WGCAPI后台窗口截图(window_handle, captureCursor=1, hideBorder=0) {
    Static
  Static IClosable := "{30D5A829-7FA4-4026-83BB-D75BAE4EA99E}"
      , PixelFormat32bppRGB := 0x22009
      , D3D11_MAP_READ := 1

    DllCall("DeleteObject", "ptr", hBitmap)
    ; , DllCall("gdiplus\GdipDisposeImage", "ptr", pBitmap)
    , DllCall("QueryPerformanceCounter", "int64*", StartTime)
    if !init {
        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 无法捕捉到目标的窗口。`nError: %hr%
            ExitApp
        }
        DllCall(NumGet(NumGet(frame_pool+0)+10*A_PtrSize), "ptr", frame_pool, "ptr", capture_item, "ptr*", session)    ; Direct3D11CaptureFramePool.CreateCaptureSession
        if captureCursor  ; Win10 1903无效=18362
            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)
            , 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, "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("gdiplus\GdipCreateHBITMAPFromBitmap", "ptr", pBitmap, "ptr*", hBitmap, "uint", 0xffffffff)
    , 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 hBitmap
}

CreateClass(string, interface, ByRef Class) {
    DllCall("Combase.dll\WindowsCreateString", "wstr", string, "uint", StrLen(string), "ptr*", 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 不支持此类接口
        else if (result = 0x80040154)
            msgbox 未注册的Class
        else
            msgbox error: %result%
        ExitApp
    }
    DllCall("Combase.dll\WindowsDeleteString", "ptr", hString)
}


计时() {
     Static
     if 开始=
          DllCall("QueryPerformanceFrequency", "Int64*", 频率), DllCall("QueryPerformanceCounter", "Int64*", 开始)
      else
          DllCall("QueryPerformanceCounter", "Int64*", 结束), 耗时:=(结束 - 开始)/频率*1000, 开始:=""
      Return 耗时
}

 

声明:站内资源为整理优化好的代码上传分享与学习研究,如果是开源代码基本都会标明出处,方便大家扩展学习路径。请不要恶意搬运,破坏站长辛苦整理维护的劳动成果。本站为爱好者分享站点,所有内容不作为商业行为。如若本站上传内容侵犯了原著者的合法权益,请联系我们进行删除下架。