Jump to content

How to capture the hidden program window?


Recommended Posts

How to capture the hidden program window?
For example:

#include <ScreenCapture.au3>
$runPID = Run ("C:\OK.exe", "C:\",@SW_HIDE)
$runPID = WinGetHandleFromPID($runPID) 
$hBmp = _ScreenCapture_CaptureWnd ("C:\OK.jpg", $runPID)

Func WinGetHandleFromPID($iSearchPID, $tolerance = 2000)
    Sleep($tolerance); give the Window a chance to load
    Local $aList = WinList()
    For $i = 1 To $aList[0][0]
        If WinGetProcess($aList[$i][1]) = $iSearchPID Then Return $aList[$i][1]
    Next
    Return SetError(1, 0, False)
EndFunc   ;==>WinGetHandleFromPID

Unable to capture the hidden window, ask how to solve? You can be given code?

Thank you Very Much!!!!!

Edited by ioripalm
Link to comment
Share on other sites

Welcome to Autoit and the forum!
Did you read the help file for _ScreenCapture_CaptureWnd? The second parameter is a handle to the window to be captured not a process ID.

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2024-07-28 - Version 1.6.3.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki
Task Scheduler (2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki

Standard UDFs:
Excel - Example Scripts - Wiki
Word - Wiki

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to comment
Share on other sites

I tried this

#include <ScreenCapture.au3>

Local $iPID = Run("notepad.exe", "", @SW_HIDE)
Local $hWnd = WinGetHandleFromPID($iPID)
If IsHWnd($hWnd) Then
    _ScreenCapture_CaptureWnd(@ScriptDir & "\OK.jpg", $hWnd)
    ShellExecute(@ScriptDir & "\OK.jpg")
    ConsoleWrite("Success" & @CR)
Else
    ConsoleWrite("Error" & @CR)
EndIf
ProcessClose($iPID)
Exit

Func WinGetHandleFromPID($iSearchPID, $tolerance = 2000)
    Sleep($tolerance); give the Window a chance to load
    Local $aList = WinList()
    For $i = 1 To $aList[0][0]
        If WinGetProcess($aList[$i][1]) = $iSearchPID Then Return $aList[$i][1]
    Next
    Return SetError(1, 0, False)
EndFunc   ;==>WinGetHandleFromPID

It works fine without the @SW_HIDE, saves a screenshot of the Notepad window.

with the @SW_HIDE, it just saves a screenshot of the area of the desktop where Notepad window would be

I looked inside the <ScreenCapture> Include, and it looks to me like _ScreenCapture_CaptureWnd isn't designed for non-visible windows.

It basically just gets the location and size of the window, and then calls _ScreenCapture_Capture to capture an image of that area of the screen.

 

Edited by guestscripter
Link to comment
Share on other sites

I think the name of the function says it all: It captures what is on the screen. If you can't see it it can't be captured.

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2024-07-28 - Version 1.6.3.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki
Task Scheduler (2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki

Standard UDFs:
Excel - Example Scripts - Wiki
Word - Wiki

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to comment
Share on other sites

Agreed. And ScreenCapture is great as it is, top of the hat and all.

Though then maybe there exists a different/better function someone has created for capturing windows without showing them to the user?

 

One workaround that came to mind with ScreenCapture:

WinSetState($hWnd, "", @SW_SHOW)
    _ScreenCapture_CaptureWnd(@ScriptDir & "\OK.jpg", $hWnd)
    WinSetState($hWnd, "", @SW_HIDE)

Which then just briefly has the Window appear.

Link to comment
Share on other sites

Why capture a hidden window at all? Is it for debugging reasons?
If yes, there could be other ways to debug the script.

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2024-07-28 - Version 1.6.3.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki
Task Scheduler (2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki

Standard UDFs:
Excel - Example Scripts - Wiki
Word - Wiki

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to comment
Share on other sites

Why capture a hidden window at all? Is it for debugging reasons?
If yes, there could be other ways to debug the script.

Fair question...

How about to capture the state of a "control" that cannot be accessed with something like WinGetText

I suppose IUIAutomation may be the direction to go...

 

Edit: better example of use maybe: Capturing Internet Explorer's rendering of a web page to an image file in the background

Edited by guestscripter
Link to comment
Share on other sites

Why capture a hidden window at all? Is it for debugging reasons?
If yes, there could be other ways to debug the script.

Maybe I do not know the expression, how to get to a hidden window screenshot, of course _ScreenCapture_CaptureWnd can not do, I ask how can we get to a hidden window screenshot?

Link to comment
Share on other sites

Welcome to Autoit and the forum!
Did you read the help file for _ScreenCapture_CaptureWnd? The second parameter is a handle to the window to be captured not a process ID.

I modified the code, if _ScreenCapture_CaptureWnd can not achieve their goals, how to do the job it?

Link to comment
Share on other sites

I do not know if the job of capturing a hidden window can be done at all.
I wanted to know why you need to capture a hidden window? What is it for?
Maybe there are other ways to achieve what you want to do.

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2024-07-28 - Version 1.6.3.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki
Task Scheduler (2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki

Standard UDFs:
Excel - Example Scripts - Wiki
Word - Wiki

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to comment
Share on other sites

  • 4 weeks later...

You can use the _WinAPI_PrintWindow function to capture a window which is behind other windows. I used that function in my Windows Screenshooter app (https://www.autoitscript.com/forum/topic/122941-autoit-windows-screenshooter-v179-build-2015-02-25).

 

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

  • 1 month later...

You can use the _WinAPI_PrintWindow function to capture a window which is behind other windows. I used that function in my Windows Screenshooter app (https://www.autoitscript.com/forum/topic/122941-autoit-windows-screenshooter-v179-build-2015-02-25).

I try this:

#include <GuiConstantsEx.au3>
#include <GDIPlus.au3>
Global Const $dll = DllOpen("user32.dll")
Global Const $g32_dll = DllOpen("gdi32.dll")
Global $hDC_Region, $hObj, $hMemDC, $memBitmap, $aFullScreen, $hFullScreen,$hBMP,$hBitmap_s
$hFullScreen = WinGetHandle("[TITLE:Program Manager;CLASS:Progman]")
$aFullScreen = WinGetPos($hFullScreen)
_Main()
Func _Main()
    _GDIPlus_Startup()
    Local $hGUI, $hBMP, $hBitmap, $hGraphic
;~  $runPID = Run("C:\WINDOWS\NOTEPAD.exe")
    $runPID = Run("C:\WINDOWS\NOTEPAD.exe","",@SW_HIDE)
    $hWnd = WinGetHandleFromPID($runPID)

    Sleep(200)

    $hBMP = Capture_Window($hWnd,667,420)
    
    $hGUI = GUICreate("TEST", 800, 600)
    GUISetState()

    $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hGUI)
    _GDIPlus_GraphicsDrawImage($hGraphic, $hBMP, 0, 0)

    _GDIPlus_GraphicsDispose($hGraphic)
    _GDIPlus_BitmapDispose($hBitmap)
    _WinAPI_DeleteObject($hBMP)

    _GDIPlus_Shutdown()

    Do
    Until GUIGetMsg() = $GUI_EVENT_CLOSE
EndFunc   ;==>_Main

Func Capture_Window($hWnd, $w, $h)
    _GDIPlus_BitmapDispose($hBMP) ;otherwise memory leak
    _WinAPI_DeleteObject($hBitmap_s)
    $undo_chk = False
    Local $hDC_Capture = _WinAPI_GetDC(HWnd($hWnd))

    Local $hMemDC = _WinAPI_CreateCompatibleDC($hDC_Capture)

    $hBitmap_s = _WinAPI_CreateCompatibleBitmap($hDC_Capture, $w, $h)

    Local $hObjectOld = _WinAPI_SelectObject($hMemDC, $hBitmap_s)

    DllCall($g32_dll, "int", "SetStretchBltMode", "hwnd", $hDC_Capture, "uint", 4)
    Local $at = DllCall($dll, "int", "PrintWindow", "hwnd", $hWnd, "handle", $hMemDC, "int", 0)

    _WinAPI_DeleteDC($hMemDC)
    _WinAPI_SelectObject($hMemDC, $hObjectOld)
    _WinAPI_ReleaseDC($hWnd, $hDC_Capture)

    Local $c1 = $aFullScreen[2] - @DesktopWidth, $c2 = $aFullScreen[3] - @DesktopHeight
    Local $wc1 = $w - $c1, $hc2 = $h - $c2

    If (($wc1 > 1 And $wc1 < $w) Or ($w - @DesktopWidth > 1) Or ($hc2 > 7 And $hc2 < $h) Or ($h - @DesktopHeight > 1)) And (BitAND(WinGetState(HWnd($hWnd)), 32) = 32) Then
        Local $hBmp_t = _GDIPlus_BitmapCreateFromHBITMAP($hBitmap_s)

        $hBMP = _GDIPlus_BitmapCloneArea($hBmp_t, 8, 8, $w - 16, $h - 16)
        _GDIPlus_BitmapDispose($hBmp_t)
    Else
        $hBMP = _GDIPlus_BitmapCreateFromHBITMAP($hBitmap_s)
    EndIf
Return $hBMP
EndFunc   ;==>Capture_Window

Func WinGetHandleFromPID($iSearchPID, $tolerance = 2000)
    Sleep($tolerance); give the Window a chance to load
    Local $aList = WinList()
    For $i = 1 To $aList[0][0]
        If WinGetProcess($aList[$i][1]) = $iSearchPID Then Return $aList[$i][1]
    Next
    Return SetError(1, 0, False)
EndFunc   ;==>WinGetHandleFromPID

But it not work,Please help me! Thank you !

Link to comment
Share on other sites

With hidden I mean other windows have overlapped partly or completely the window. Capturing windows with the flag @SW_HIDE is not possible this way.

I assume that hidden windows with @SW_HIDE falg cannot be captured at all.

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

With hidden I mean other windows have overlapped partly or completely the window. Capturing windows with the flag @SW_HIDE is not possible this way.

I assume that hidden windows with @SW_HIDE falg cannot be captured at all.

Thank You Very Much!

If you find a good way, please give me a message!

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...