Winapi 有没有办法将PrintWindow与控件一起使用?(使用AutoIt)

Winapi 有没有办法将PrintWindow与控件一起使用?(使用AutoIt),winapi,controls,gdi+,autoit,screen-capture,Winapi,Controls,Gdi+,Autoit,Screen Capture,我有一小段脚本,但当我使用PrintWindow时,它只返回一个黑色捕获: PrintWindow()使用窗口句柄可以正常工作,但不使用控制句柄 (或者有没有办法只捕获窗口的底部或中间的东西而不需要捕获整个窗口并切割它?)< /P> 自动IT脚本: Local $hWnd = ControlGetHandle("[CLASS:Notepad]","","Edit1") Local $pos = ControlGetPos($hWnd,"","") ;MsgBox($MB_OK, "OK", $p

我有一小段脚本,但当我使用PrintWindow时,它只返回一个黑色捕获:

PrintWindow()使用窗口句柄可以正常工作,但不使用控制句柄

(或者有没有办法只捕获窗口的底部或中间的东西而不需要捕获整个窗口并切割它?)< /P> 自动IT脚本:

Local $hWnd = ControlGetHandle("[CLASS:Notepad]","","Edit1")
Local $pos = ControlGetPos($hWnd,"","")
;MsgBox($MB_OK, "OK", $pos[0])
Local $Width = $pos[2]
Local $Height = $pos[3]

Local $hDC = _WinAPI_GetDC($hWnd)
Local $memDC = _WinAPI_CreateCompatibleDC($hDC)
Local $memBmp = _WinAPI_CreateCompatibleBitmap($hDC, $Width, $Height)
_WinAPI_SelectObject ($memDC, $memBmp)
;DllCall("User32.dll","int","PrintWindow","hwnd",$hWnd,"hwnd",$memDC,"int",0)
;_WinAPI_BitBlt($hDC, 0, 0, $Width, $Height, $memDC, 0,0, $SRCCOPY)
_WinAPI_BitBlt($memDC, 0, 0, $Width, $Height, $hDC, 0,0, $SRCCOPY) ;this is working now!

_GDIPlus_Startup()
Local $hBMP=_GDIPlus_BitmapCreateFromHBITMAP($memBmp)
Local $hHBITMAP=_GDIPlus_BitmapCreateHBITMAPFromBitmap($hBMP)

_WinAPI_DeleteObject($hDC)
_WinAPI_ReleaseDC($hWnd, $hDC)
_WinAPI_DeleteDC($memDC)
_WinAPI_DeleteObject ($memBmp)
_WinAPI_DeleteDC($hDC)

$sPath = @ScriptDir & '\capture.bmp'
_WinAPI_SaveHBITMAPToFile($sPath, $hHBITMAP)

最简单-拍摄整个窗口的快照,然后剪切图像的所需部分(例如控件)。控件通过PrintWindow显示黑色图像的原因之一是控件的CS_PARENTDC

我有一小段脚本,但当我使用PrintWindow时,它只返回一个黑色捕获:

首先,我不知道您使用的语言,但您的代码和问题非常清楚,我可以尝试提供解决方案

在我看来,
PrintWindow
的第二个参数是错误的(它是
HWND
,但应该是
HDC

第二,您的代码中存在GDI泄漏,但我已经纠正了它->请在代码中查看我的注释。长话短说,每次您
在设备上下文中选择对象时,您都会“推出”在该选择之前“站在那里”的原始对象。必须保存并“放回”原始对象。否则,随着时间的推移,内存将耗尽,应用程序将冻结。只要在谷歌上搜索“GDI泄密”,你就会找到我所描述内容的详细解释

第三,您当然会得到黑色捕获,因为您的初始HDC是空的->您需要将
memDC
的内容传输到
HDC
。要做到这一点,您需要使用函数。正如我所说的,我不知道您使用的语言,但我已经尝试在下面的插图中为您提供伪代码,以便您可以了解一些操作的线索

Local $hWnd = ControlGetHandle("[CLASS:Notepad]","","Edit1")
Local $pos = ControlGetPos($hWnd,"","")
;MsgBox($MB_OK, "OK", $pos[0])
Local $Width = $pos[2]
Local $Height = $pos[3]

Local $hDC = _WinAPI_GetDC($hWnd)
Local $memDC = _WinAPI_CreateCompatibleDC($hDC)
Local $memBmp = _WinAPI_CreateCompatibleBitmap($hDC, $Width, $Height)

Local $bmpOriginal = _WinAPI_SelectObject ($memDC, $memBmp)  ;store original DC bitmap 

DllCall("User32.dll","int","PrintWindow","hwnd",$hWnd,
    "hdc",  ; I think this is an error, this parameter is of type HDC
    $memDC,"int",0)

DllCall("User32.dll","int","BitBlt", "hdc", memDC, 
    ... , ; fill in the rest of parameters
    "hdc" , hDC, 
    ... ) ; fill in the rest of parameters. Your last parameter should be SRCCOPY!

; when done with the DC, first select back the original bitmap
_WinAPI_SelectObject( $memDC, $bmpOriginal ) 
; now we can delete memory bitmap since it is no longer needed
_WinAPI_DeleteObject( $memBmp )
; delete memory DC since we performed proper cleanup
_WinAPI_DeleteDC( $memDC )
; release window's DC
_WinAPI_ReleaseDC( $hwnd, $hDC )
我希望这会有所帮助,如果您还有其他问题,请留下评论,我将尽力提供帮助

(或者,有没有办法只捕获窗户的底部或中间的东西?)< /P> 是的,但首先我需要知道上述方法是否适用于您。如果您仍然需要阅读第二部分,请留下评论,并将尽力帮助您


祝你好运

谢谢,我修复了我的代码,但是我仍然有一个黑色位图,没有任何可见的内容,我的函数PrintWindow可以很好地使用windows句柄,只是当我添加控件句柄时它不起作用。问题是你是从你自己的应用程序访问编辑控件,而不是从记事本。你想做的事很难。若你们可以挂接到记事本并截取,你们可以把你们的绘图代码放在那个处理程序中,希望它能工作。如果我是你,我会在网上搜索windows钩子教程。@shuji:很遗憾,我对WinAPI不太在行:(我仍然祝你好运。我已经把你的问题投了高票,希望你能得到足够的分数来开始悬赏……如果我发现了什么,我会留下评论……你知道吗,我在代码中发现了错误:BitBlt的第一个参数必须是目标$memDC,稍后保存。之后代码工作正常。谢谢:)@shuji:我很高兴你成功了!向你致意。我真的不在乎这是否更难,因为在高分辨率显示器中,截图和剪切需要很长时间。如果你能想出解决问题的方法,我很想听听,谢谢。也许下面的演示对你有用(按钮“PrintWindow\M”执行我的建议:()。