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

标签 winapi controls gdi+ autoit screen-capture

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

PrintWindow() 对于窗口句柄可以正常工作,但不能与控制句柄一起工作。

(或者有没有办法只捕获窗口的底部或中间的部分,而不需要捕获整个窗口并剪切它?)

AutoIt 脚本:

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)

最佳答案

I have this little piece of script but when I use PrintWindow it's only returning a black capture:

首先,我不知道您使用的语言,但是您的代码和问题足够清晰,我可以尝试提供解决方案。

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

其次,您的代码中存在 GDI 泄漏,但我已更正它 -> 请参阅代码中的评论。长话短说,每次您SelectObject将某些内容放入设备上下文时,您都会“推出”在该选择之前“站在那里”的原始对象。必须保存该原始对象并“放回”。如果没有,那么您的内存将随着时间的推移而耗尽,并且您的应用程序将卡住。只需 Google 搜索“GDI 泄漏”,您就会找到我所描述内容的详细解释。

第三,当然你会捕获黑色,因为你的初始 HDC 是空的 -> 你需要将 memDC 的内容传输到 hDC 中。为此,您需要使用 BitBlt功能。正如我所说,我不知道您使用的语言,但我尝试在下图中为您提供伪代码,以便您可以了解该怎么做。

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 )

希望这对您有所帮助,如果您还有其他问题,请发表评论,我会尽力提供帮助。

(Or is there a way to capture only the bottom part of the window or something in the middle?)

是的,但首先我需要知道上述方法是否适合您。如果您仍然需要第二部分,请发表评论,我们会尽力帮助您。

致以诚挚的问候,祝你好运!

关于winapi - 有没有办法将 PrintWindow 与控件一起使用? (使用 AutoIt),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27045876/

相关文章:

c++ - 以编程方式重新启动所有崩溃服务的服务程序

c++ - 用 win32 api C++ 打开 jpeg

c++ - 获取电池设备名称

c++ - HBITMAP 可以包含 alpha channel 信息吗?

c# Draw Image (Scaled) to Graphics,插值不正确。修复?

c++ - win32 c++ 所有者绘制带有透明图像的按钮

.net - 如何重置 .NET Windows Forms TextBox BackColor 属性?

c# - 当我尝试制作自定义文本框时,密码字符不起作用

c# - 将 Size.Width 和 Size.Height 转换为毫米

multithreading - Silverlight-延误行动之火-