Page 1 sur 1

[..] Prendre une capture d'écran d'une fênetre non visible

Posté : mer. 16 oct. 2019 11:45
par franco
Bonjour.

Actuellement, je code un script, et au sein de celui ci, j'aurais besoin d'ouvrir un programme, de le rendre non visible, et de capturer la fenêtre...

Quand je dis "non visible", et non pas "invisible", je parle de déplacer la fenêtre hors champ, avec un petit winmove...


Après recherche, pour faire une capture simple, j'ai pris l'exemple avec le bloc note, que voici :
#include <ScreenCapture.au3>
#include <GUIConstantsEx.au3>

$img = @DesktopDir & "\img.jpg"
FileDelete($img)

$hWnd = "[CLASS:Notepad]"
ProcessClose("notepad.exe")
Run("notepad.exe")
WinWait($hWnd)
$objCurrentWindow = WinGetHandle($hWnd)
WinActivate($hWnd)
;~ WinSetState($hWnd,"",@SW_HIDE)
;~ sleep(1000)
_ScreenCapture_CaptureWnd($img, $objCurrentWindow)
ShellExecute($img)
Ca fonctionne.


Mais si je fais un WinMove pour mettre la fenêtre hors champ, on voit sur l'image, la fenetre coupé en deux.
En gros, on voit 'l'hors champ' ^^

Comment faire pour capturer une fenêtre, sans qu'elle soit visible ? Telle est la question.

Ce que j'ai fait, au final :
#include <ScreenCapture.au3>
#include <GUIConstantsEx.au3>

$img = @DesktopDir & "\img.jpg"
FileDelete($img)

$hWnd = "[CLASS:Notepad]"
ProcessClose("notepad.exe")
Run("notepad.exe")
WinWait($hWnd)
$objCurrentWindow = WinGetHandle($hWnd)
WinActivate($hWnd)
WinMove($hWnd,"",-500,-500)
;~ WinSetState($hWnd,"",@SW_HIDE)
sleep(1000)
_ScreenCapture_CaptureWnd($img, $objCurrentWindow)
ShellExecute($img)
Ce que j'aimerais trouvé, et que je vais essayer de trouver, c'est comment ouvrir une fenêtre d'un programme directement non visible, et que je puisse capturer son image.


Merci de vouloir m'aider à trouver des pistes...
++

Re: [..] Prendre une capture d'écran d'une fênetre non visible

Posté : jeu. 17 oct. 2019 18:40
par walkson
Bonjour,
Je ne suis pas sûr de moi mais il me semble qu'une fenêtre hors bureau ne peut pas être capturer.
La solution est de la faire glisser sur le bureau, la capturer et de la faire glisser hors bureau comme ceci
#include <ScreenCapture.au3>
#include <GUIConstantsEx.au3>
HotKeySet("!x","capture"); alt x
HotKeySet("^x","MyTest"); ctrl x =>> exit
Global $pid
$img = @DesktopDir & "\img.jpg"
FileDelete($img)

Global $hWnd = "[CLASS:Notepad]"
ProcessClose("notepad.exe")
Run("notepad.exe")
WinWait($hWnd)
WinActivate($hWnd)
ControlSetText($hWnd,"","Edit1", "coucou")
Global $apos = WinGetPos($hWnd)
WinMove($hWnd,"",$apos[2] - @DesktopWidth,$apos[3] - @DesktopHeight)
While 1
   Sleep(100)
WEnd

Func capture()
$handle = WinMove($hWnd,"",$apos[0] ,$apos[1] )
;Sleep(150)
_ScreenCapture_CaptureWnd($img, $handle)
WinMove($hWnd,"",$apos[2] - @DesktopWidth,$apos[3] - @DesktopHeight)
Sleep(2000)
$pid = ShellExecute($img)
EndFunc
Func MyTest()
WinMove($hWnd,"",$apos[0] ,$apos[1] )
WinClose($hWnd)
ProcessClose($pid)
Exit
EndFunc

Re: [..] Prendre une capture d'écran d'une fênetre non visible

Posté : jeu. 17 oct. 2019 18:49
par walkson
Il y a aussi la solution @SW_HIDE et @SW_SHOW mais elle semble plus lente et donc plus visible que WinMove()

Re: [..] Prendre une capture d'écran d'une fênetre non visible

Posté : jeu. 17 oct. 2019 19:31
par mikell
Du forum US : ça crée un DC qui autorise la capture
#include <GDIPlus.au3>
#include <WinAPI.au3>
#include <ScreenCapture.au3>

_GDIPlus_Startup()

$hGUI = WinGetHandle("AutoIt Help")
WinMove($hGUI, "", @DesktopWidth-100, @DesktopHeight)

$iWidth = _WinAPI_GetWindowWidth($hGUI)
$iHeight = _WinAPI_GetWindowHeight($hGUI)
_WinCapture($hGUI, $iWidth, $iHeight)

Sleep(2000)
WinMove($hGUI, "", 100, 100)


Func _WinCapture($hWnd, $iWidth = -1, $iHeight = -1)
    Local $iH, $iW, $hDDC, $hCDC, $hBMP

    If $iWidth = -1 Then $iWidth = _WinAPI_GetWindowWidth($hWnd)
    If $iHeight = -1 Then $iHeight = _WinAPI_GetWindowHeight($hWnd)

    $hDDC = _WinAPI_GetDC($hWnd)
    $hCDC = _WinAPI_CreateCompatibleDC($hDDC)
    $hBMP = _WinAPI_CreateCompatibleBitmap($hDDC, $iWidth, $iHeight)
    _WinAPI_SelectObject($hCDC, $hBMP)

    DllCall("User32.dll", "int", "PrintWindow", "hwnd", $hWnd, "hwnd", $hCDC, "int", 0)
    _WinAPI_BitBlt($hCDC, 0, 0, $iW, $iH, $hDDC, 0, 0, 0x00330008)

    _WinAPI_ReleaseDC($hWnd, $hDDC)
    _WinAPI_DeleteDC($hCDC)

    _ScreenCapture_SaveImage(@DesktopDir&"\window.jpg", $hBMP, False)

    Return $hBMP
EndFunc   ;==>_WinCapture

Re: [..] Prendre une capture d'écran d'une fênetre non visible

Posté : ven. 18 oct. 2019 14:26
par walkson
Heureux de m'être trompé :mrgreen: .Voilà une fonction que je vais archiver !
Par contre, si la fenêtre est minimisée, la fonction échoue. (capture uniquement la barre des titres)
A vérifier sous win 10 si Aero peek est activé car il se peut que la fonction échoue aussi s'il ne l'est pas (je suis sous win 7)

[Édit] #include <GDIPlus.au3> et _GDIPlus_Startup() sont inutiles

Re: [..] Prendre une capture d'écran d'une fênetre non visible

Posté : ven. 18 oct. 2019 21:31
par walkson
Je ne veux pas polluer le post de Franco mais comme il semble être parti en WE, j'en profite :mrgreen:
Si la fonction marche bien, j'obtiens des résultats étranges si j'utilise le handle du Hbitmap pour le mettre sur un label, exemple
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include <WinAPI.au3>
#include <ScreenCapture.au3>
FileDelete(@DesktopDir&"\window.jpg")
$pid = ShellExecute(@ProgramFilesDir & "\AutoIt3\AutoIt.chm")
ProcessWait("hh.exe")
$hGUI = WinGetHandle("AutoIt Help")
WinMove($hGUI, "", @DesktopWidth-100, @DesktopHeight)
WinSetState($hGUI, "",@SW_RESTORE)

$aArray = _WinCapture($hGUI,-1,-1,True)
Sleep(2000)
WinMove($hGUI, "", 100, 100)
ShellExecuteWait(@DesktopDir&"\window.jpg")
Gui($aArray[0],$aArray[1],$aArray[2])

Func _WinCapture($hWnd, $iWidth = -1, $iHeight = -1, $save = False)
    Local $iH, $iW, $hDDC, $hCDC, $hBMP, $aArray[3]

    If $iWidth = -1 Then $iWidth = _WinAPI_GetWindowWidth($hWnd)
    If $iHeight = -1 Then $iHeight = _WinAPI_GetWindowHeight($hWnd)

    $hDDC = _WinAPI_GetDC($hWnd)
    $hCDC = _WinAPI_CreateCompatibleDC($hDDC)
    $hBMP = _WinAPI_CreateCompatibleBitmap($hDDC, $iWidth, $iHeight)
    _WinAPI_SelectObject($hCDC, $hBMP)

    DllCall("User32.dll", "int", "PrintWindow", "hwnd", $hWnd, "hwnd", $hCDC, "int", 0)
    _WinAPI_BitBlt($hCDC, 0, 0, $iW, $iH, $hDDC, 0, 0, $SRCCOPY)
    _WinAPI_ReleaseDC($hWnd, $hDDC)
    _WinAPI_DeleteDC($hCDC)
   If $save = True Then _ScreenCapture_SaveImage(@DesktopDir&"\window.jpg", $hBMP, False)
   ;_WinAPI_SaveHBITMAPToFile(@DesktopDir & "\aa.bmp", $hBMP)
   $aArray[0] = $hBMP
   $aArray[1] = $iWidth
   $aArray[2] = $iHeight
    Return $aArray
EndFunc   ;==>_WinCapture
Func Gui($hBMP,$iWidth,$iHeight)

Global $Form1 = GUICreate("", $iWidth,$iHeight, -1, -1)
Global $Label1 = GUICtrlCreateLabel("", 0, 0, $iWidth,$iHeight,BitOR($SS_CENTERIMAGE,$SS_BITMAP),$WS_EX_CLIENTEDGE)
GUISetState(@SW_SHOW)
;_WinAPI_DeleteObject(_SendMessage(GUICtrlGetHandle($Label1), $STM_SETIMAGE, 0, $hBMP))
$hb = GUICtrlSendMsg($Label1, $STM_SETIMAGE, $IMAGE_BITMAP, $hBMP)
If $hb Then _WinAPI_DeleteObject($hb)
_WinAPI_DeleteObject($hBMP)
While 1
 $nMsg = GUIGetMsg()
 Switch $nMsg
  Case $GUI_EVENT_CLOSE
   Exit

 EndSwitch
WEnd
EndFunc
Bien que j'ai essayé plusieurs méthodes, j'obtiens le même résultat incomplet sur la Gui et je suis incapable de résoudre le problème alors que l'image enregistrée est normal ?!?...
On est bien loin du problème de Franco mais allez !, osons en espérant qu'il prolonge son WE :oops:

Re: [..] Prendre une capture d'écran d'une fênetre non visible

Posté : ven. 18 oct. 2019 21:47
par mikell
Pardon, je n'avais posté que la version édulcorée :mrgreen:
#NoTrayIcon
#include <GDIPlus.au3>
#include <WinAPI.au3>
#include <ScreenCapture.au3>

_GDIPlus_Startup()

$hGUI = WinGetHandle("AutoIt Help")
WinMove($hGUI, "", @DesktopWidth-100, @DesktopHeight)

$iWidth = _WinAPI_GetWindowWidth($hGUI)
$iHeight = _WinAPI_GetWindowHeight($hGUI)

$hParent = GUICreate("WindowViewer", 500, 400)
$hGraphics = _GDIPlus_GraphicsCreateFromHWND($hParent)
GUISetState()

$hBMP = _WinCapture($hGUI, $iWidth, $iHeight)
$hImage = _GDIPlus_BitmapCreateFromHBITMAP($hBMP)

_GDIPlus_GraphicsDrawImageRectRect($hGraphics, $hImage, 0, 0, $iWidth, $iHeight, 50, 50, 400, 300)
_GDIPlus_ImageDispose($hImage)
_GDIPlus_GraphicsDispose($hGraphics)
_WinAPI_DeleteObject($hBMP)

Sleep(5000)
WinMove($hGUI, "", 100, 100)

Func _WinCapture($hWnd, $iWidth = -1, $iHeight = -1)
    Local $iH, $iW, $hDDC, $hCDC, $hBMP

    If $iWidth = -1 Then $iWidth = _WinAPI_GetWindowWidth($hWnd)
    If $iHeight = -1 Then $iHeight = _WinAPI_GetWindowHeight($hWnd)

    $hDDC = _WinAPI_GetDC($hWnd)
    $hCDC = _WinAPI_CreateCompatibleDC($hDDC)
    $hBMP = _WinAPI_CreateCompatibleBitmap($hDDC, $iWidth, $iHeight)
    _WinAPI_SelectObject($hCDC, $hBMP)

    DllCall("User32.dll", "int", "PrintWindow", "hwnd", $hWnd, "hwnd", $hCDC, "int", 0)
    _WinAPI_BitBlt($hCDC, 0, 0, $iW, $iH, $hDDC, 0, 0, 0x00330008)

    _WinAPI_ReleaseDC($hWnd, $hDDC)
    _WinAPI_DeleteDC($hCDC)

    _ScreenCapture_SaveImage(@DesktopDir&"\window.jpg", $hBMP, False)

    Return $hBMP
EndFunc   ;==>_WinCapture

Re: [..] Prendre une capture d'écran d'une fênetre non visible

Posté : sam. 19 oct. 2019 18:42
par walkson
Il manque _GDIPlus_Shutdown ( ) :mrgreen:
Merci pour cette solution mais je trouve étrange d'être obligé de passer par _GDIPlus_BitmapCreateFromHBITMAP($hBMP) et cela d'autant plus que l'on peut récupérer le Hbitmap du _ScreenCapture_CaptureWnd("",$hGUI,0,0,-1,-1,False) si la fenêtre est visible mais bon, cela restera un mystère de l'informatique...

Re: [..] Prendre une capture d'écran d'une fênetre non visible

Posté : sam. 19 oct. 2019 19:43
par mikell
Je t'avoue que j'ai posté le truc brut de copier/coller, répondant ainsi à la question du post n°1 :
"je parle de déplacer la fenêtre hors champ, avec un petit winmove"
C'est vrai que ça ne marche pas avec les fenêtres minimisées mais là franchement je crois que c'est impossible
Et je n'ai pas approfondi, partant du principe que franco est un utilisateur expérimenté et que si on lui fournit un point de départ ses compétences indéniables lui permettront alors de se démerbrouiller pour arranger le fourbi à sa sauce adapter ce code à son script (et réciproquement)
Image

Re: [..] Prendre une capture d'écran d'une fênetre non visible

Posté : sam. 19 oct. 2019 21:47
par franco
Salut à tous, et merci surtout.


J'aurais bien aimé partir en Weekend. lol
Hélas, je bossais ce samedi, jusqu'à 20h.

Pour en revenir au script, la fenêtre que je cherche à récupérer l'image, c'est le paramètre Affichage (sous windows 10).

En image :
https://i.imgur.com/ONi5wR2.png


En effet, je cherche juste à récupérer l'affichage des écrans, et en image.

Le souci ? Il récupère le fond, et c'est tout.
J'ai donc une image de couleur noire.

Arf...
#NoTrayIcon
#include <GDIPlus.au3>
#include <WinAPI.au3>
#include <ScreenCapture.au3>

_GDIPlus_Startup()

Run('control desk.cpl')
sleep(2000)
$hGUI = WinGetHandle("Paramètres")
WinMove($hGUI, "", @DesktopWidth-1000, @DesktopHeight)
WinSetState($hGUI,'',@SW_SHOW)

$iWidth = _WinAPI_GetWindowWidth($hGUI)
$iHeight = _WinAPI_GetWindowHeight($hGUI)

$hParent = GUICreate("WindowViewer", 500, 400)
$hGraphics = _GDIPlus_GraphicsCreateFromHWND($hParent)
GUISetState()

$hBMP = _WinCapture($hGUI, $iWidth, $iHeight)
$hImage = _GDIPlus_BitmapCreateFromHBITMAP($hBMP)

_GDIPlus_GraphicsDrawImageRectRect($hGraphics, $hImage, 0, 0, $iWidth, $iHeight, 50, 50, 400, 300)
_GDIPlus_ImageDispose($hImage)
_GDIPlus_GraphicsDispose($hGraphics)
_WinAPI_DeleteObject($hBMP)

Sleep(5000)
WinMove($hGUI, "", 100, 100)

Func _WinCapture($hWnd, $iWidth = -1, $iHeight = -1)
    Local $iH, $iW, $hDDC, $hCDC, $hBMP

    If $iWidth = -1 Then $iWidth = _WinAPI_GetWindowWidth($hWnd)
    If $iHeight = -1 Then $iHeight = _WinAPI_GetWindowHeight($hWnd)

    $hDDC = _WinAPI_GetDC($hWnd)
    $hCDC = _WinAPI_CreateCompatibleDC($hDDC)
    $hBMP = _WinAPI_CreateCompatibleBitmap($hDDC, $iWidth, $iHeight)
    _WinAPI_SelectObject($hCDC, $hBMP)

    DllCall("User32.dll", "int", "PrintWindow", "hwnd", $hWnd, "hwnd", $hCDC, "int", 0)
    _WinAPI_BitBlt($hCDC, 0, 0, $iW, $iH, $hDDC, 0, 0, 0x00330008)

    _WinAPI_ReleaseDC($hWnd, $hDDC)
    _WinAPI_DeleteDC($hCDC)

    _ScreenCapture_SaveImage(@DesktopDir&"\window.jpg", $hBMP, False)

    Return $hBMP
EndFunc   ;==>_WinCapture

Sinon, vous connaitrez par un outil, en ligne de commande, qui peut faire ce résultat, c-à-dire, voir l'affichage des écrans ?


Ce serait bien plus simple...


Pour info, mon "outil", c'est juste pour dupliquer l'écran,l'étendre, n'afficher qu'un des deux (etc).
Et aussi de passer l'écran suivant en primaire (merci MonitorInfoView).


Je cherche de mon coté, le pourquoi de l'image noire ^^



++

Re: [..] Prendre une capture d'écran d'une fênetre non visible

Posté : lun. 21 oct. 2019 10:50
par franco
Yo.

En ce matin, j'ai eu une idée.
Je pensais qu'elle était irréalisable, mais en fait non. Quoique...


Etant donné que je veux un visuel de l'affichage des écrans (via control desk.cpl), je me suis demandé : est-ce que c'est possible d'ouvrir un exécutable, à l'intérieur d'une interface...

Sur le moment, je pensais : rêve pas, c'est de la science fiction.
Mais vu que je suis un doux rêveur, j'ai lancé une recherche en anglais.

Et je suis tombé sur cela : https://www.autoitscript.com/forum/topi ... nside-gui/


Intéressant.

j'ai testé avec le bloc note, que voici.
► Afficher le texte

Ca fonctionne...


Mais pas avec "control desk.cpl"


Que voici :
► Afficher le texte
Dommage, car ceci était plus judicieux, qu'une capture d'image...


Bref, je continue ma recherche...


++

Re: [..] Prendre une capture d'écran d'une fênetre non visible

Posté : jeu. 24 oct. 2019 11:32
par franco
Lu'

J'ai eu une autre idée, que j'ai posté sur le forum US, vu que l'idée m'est venu en cherchant sur ce forum.

En fait, si je ne peux pas faire de copie d'écran, pour avoir un visuel, et si je ne peux pas ouvrir desk.cpl au sein d'une GUI :
---> autant l'afficher en résolution réduite, afin de voir que le nécessaire...

Là, c'est bon...

Sauf que le menu déroulant, j'en veux pas. :mrgreen:
J'ai donc cherché à le désactiver. D'où mon topic sur le forum US.

Je ne sais plus comment j'ai fait pour atterrir là bas, mais j'ai vu qu'on pouvait changer les styles de l'interface (fenêtre) d'un programme externe...
Alors un style qui me permettrait de désactiver le menu déroulant, ça serait sympa.

Vu qu'on peut désactiver le bouton fermer avec un dllcall aussi, pourquoi pas avec le menu déroulant...


On m'a donc répondu ceci : essaye avec controldisable.


De là, je me suis mis à la recherche, et j'ai vu qu'il fallait lister donc toutes les CLASSNN pour cela.
-> https://www.autoitscript.com/forum/topi ... -controls/

Bref, j'arrive, en gros, à désactiver la barre de menu (quitter, réduire, etc), mais pas le fameux menu déroulant...
_disable_display_properties()
Func _disable_display_properties()
   ShellExecute("desk.cpl")
   $hWnd = WinWait("Paramètres")
   ControlDisable($hWnd, "", "ApplicationFrameTitleBarWindow1") ; celui qui fonctionne
;~    ControlDisable($hWnd, "", "ApplicationFrameTitleBarWindow2")
;~ ControlDisable($hWnd, "", "Windows.UI.Core.CoreWindow1")
;~ ControlDisable($hWnd, "", "Windows.UI.Core.CoreWindow2")
;~ ControlDisable($hWnd, "", "ApplicationFrameInputSinkWindow1")
;~ ControlDisable($hWnd, "", "ApplicationFrameInputSinkWindow2")

;~ _GUIScrollBars_EnableScrollBar ( $hWnd , $SB_BOTH  , $ESB_DISABLE_BOTH )


;~ Windows.UI.Core.CoreWindow1
;~ ApplicationFrameTitleBarWindow1
;~ ApplicationFrameTitleBarWindow2
;~ ApplicationFrameInputSinkWindow1

EndFunc   ;==>_disable_display_properties

J'avoue que là, je sèche...
Et si j'arrive pas à faire ce que je souhaite, je pense que je vais arrêter là ( ^^ ). Ou du moins, suspendre la recherche, la recontinuer si j'ai d'autre piste.

++

Re: [..] Prendre une capture d'écran d'une fênetre non visible

Posté : dim. 27 oct. 2019 13:33
par franco
Lu'

En fait, j'ai une autre piste, sisi... :mrgreen:

Image


---- Faire un controlclick sur le bouton IDENTIFIER.

J'ai utilisé controlclick avec les valeurs x et y, trouvées avec au3info
-> - Le controlclick ne fonctionne pas. est-ce que la syntaxte est mauvaise ?

J'ai utilisé MouseClick : cela fonctionne, du moment où la fenêtre, activée, n'est pas déplacée.
-> existe-t-il un moyen de calculer les bonnes coordonnées ? Comme cela, déplacement ou pas, le bouton est quand même cliqué.

Le code :
ShellExecute("desk.cpl")
Local $HWND = WinWait("Paramètres", "")
WinActivate($HWND)
Sleep(2000)

;~ ControlClick($hWnd, "", "","left",1,380,420)
MouseClick("left",870, 600,3)

++

Re: [..] Prendre une capture d'écran d'une fênetre non visible

Posté : dim. 27 oct. 2019 23:21
par franco
Re.

Je vois que ce sujet n'apporte pas beaucoup d'intérêt. :mrgreen:


Néanmoins (dixit le sphinx lol), j'ai, avec l'aide de au3info, repérer les coordonnées à la fois la fenêtre du programme, et à la foix du bouton IDENTIFIER.

Comme cela, en faisant la différence, j'ai obtenu donc un nombre.

Grâce à ce nombre, j'ai pu calculer les coordonnées du bouton IDENTIFIER.

Du style :
Local $w = 570, $h = 570
$x_win = (@DesktopWidth - $w) / 2
$y_win = (@DesktopHeight - $h) / 2
$x_btn = $x_win + 380
$y_btn = $y_win + 450
ShellExecute("desk.cpl")
Local $hWnd = WinWait("Paramètres", "")
Sleep(2000)
WinActivate($hWnd)
WinMove($hWnd, '', $x_win, $y_win, $w, $h)
MouseClick("left", $x_btn, $y_btn)
Cela fonctionne, que ce soit sur l'écran principal ou sur l'écran secondaire, dont la résolution diffère.

Est-ce que ce bout de script est "propre" ?

++

Re: [..] Prendre une capture d'écran d'une fênetre non visible

Posté : lun. 28 oct. 2019 12:05
par mikell
Disons qu'il est "propre" par défaut :mrgreen: même si tant qu'à faire j'aurais personnellement plutôt utilisé un WinGetPos("Paramètres")