[Résolu] Capture du texte d'une fenetre externe à PB

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
brossden
Messages : 833
Inscription : lun. 26/janv./2004 14:37

Re: Capture du texte d'une fenetre externe à l'application P

Message par brossden »

Merci Dobro mais c ne sera pas avant lundi !

Par contre je persiste et signe qu'il y a un Bug !

La solution de Falsam est sympa mais je n'arrive pas à connaitre l'handle de l'exécutable, as tu une idée en connaissant l'handle de la fenêtre ?
Denis

Bonne Jounée à tous
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Re: Capture du texte d'une fenetre externe à l'application P

Message par Backup »

tu veux le PID du prg ?
Avatar de l’utilisateur
falsam
Messages : 7324
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: Capture du texte d'une fenetre externe à l'application P

Message par falsam »

brossden a écrit :La solution de Falsam est sympa mais je n'arrive pas à connaitre l'handle de l'exécutable, as tu une idée en connaissant l'handle de la fenêtre ?
Puisque je passe par là je vais répondre. Mon code précédent se servait du nom de l’exécutable pour trouver l'handle de la fenêtre ou se trouve le texte à capturer.

J'ai modifié ce code pour que cette fois çi c'est le titre de la fenêtre qui permet de trouver l'handle.

Ouvrir Notepad par exemple et saisir du texte sans l'enregistrer.
la fenêtre se nomme "Sans titre - Bloc-notes"

Code : Tout sélectionner

;Lire le contenu de la fenetre d'une application externe
;Contributeur : Falsam (08 mars 2013)
;
; OS : Windows

Enumeration
  #Mainform 
EndEnumeration

;Handle de l'application externe
Global ExeHwnd.l

Procedure SearchText(hwnd, lParam)
  TextLength = SendMessage_(hwnd, #WM_GETTEXTLENGTH, 0, 0)
  text$ = Space(TextLength)
  SendMessage_(hwnd, #WM_GETTEXT, TextLength + 1, @text$)
  If Trim(Text$) <>""
   Debug text$
  EndIf    
EndProcedure 

;Start
Procedure Start()
  OpenWindow(#MainForm, 0, 0, 500, 400, "", #PB_Window_SystemMenu)
   
  ;Cherche le handle de l'application externe en se servant du titre de la fenetre (Exemple pour notepad.exe)
  ExeHwnd = FindWindow_(0, "Sans titre - Bloc-notes")
  
  If ExeHwnd
    EnumChildWindows_(ExeHwnd, @SearchText(), ExeHwnd)     
  EndIf
   
EndProcedure

Start()

Repeat
  
  Select WaitWindowEvent()          
    Case #PB_Event_CloseWindow
      End
                  
  EndSelect
ForEver
Configuration : Windows 11 Famille 64-bit - PB 6.20 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
brossden
Messages : 833
Inscription : lun. 26/janv./2004 14:37

Re: Capture du texte d'une fenetre externe à l'application P

Message par brossden »

Falsam tu es mon sauveur !

lol !

Je n'ai pas encore pu essayer en réel sur mon appli au boulot, mais les quelque tests que j'ai fais chez moi sont très prometteurs

Je vous remercie tous pour votre participation !
Denis

Bonne Jounée à tous
brossden
Messages : 833
Inscription : lun. 26/janv./2004 14:37

Re: Capture du texte d'une fenetre externe à l'application P

Message par brossden »

Désolé cela ne fonctionne pas non plus Falsam

Si tu veux avoir une idée de ce que je rencontre comme problème tu peux le simuler en créant une petite application sous PB en créant en mode console une fenêtre dans laquelle tu auras réalisé un PrintN d'un texte quelconque et c'est ce texte que je cherche à récupérer d'une autre appli PB !

Exemple :

Code : Tout sélectionner

If OpenConsole()
    PrintN("Appuyez sur [Entree] pour quitter")
    Input()
EndIf
Denis

Bonne Jounée à tous
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Re: Capture du texte d'une fenetre externe à l'application P

Message par Backup »

....
Dernière modification par Backup le mar. 19/août/2014 10:06, modifié 2 fois.
brossden
Messages : 833
Inscription : lun. 26/janv./2004 14:37

Re: Capture du texte d'une fenetre externe à l'application P

Message par brossden »

Désolé Dobro cela ne fonctionne pas même si effectivement cela marche sur le texte du forum !
Denis

Bonne Jounée à tous
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Re: Capture du texte d'une fenetre externe à l'application P

Message par Backup »

brossden a écrit :Désolé Dobro cela ne fonctionne pas même si effectivement cela marche sur le texte du forum !
il ne doit pas etre selectionnable a la souris ton text alors ...contrairement a ce que tu disais ...
brossden a écrit :par contre je peux sélectionner une zone rectangulaire quelconque et faire CTRL + C qui fonctionne
c'est EXACTEMENT ce que fais ce code .. 8O

bon tu nous le donne ce prg , qu'on puisse tester a la maison ? :mrgreen:
brossden
Messages : 833
Inscription : lun. 26/janv./2004 14:37

Re: Capture du texte d'une fenetre externe à l'application P

Message par brossden »

Dobro

Merci de tes efforts et à Falsam aussi , j'ai repris ton programme initial et je l'ai compilé avec une ancienne version de PB et tout fonctionne IMPEC !

Donc c'est bien un bug de PB version 5.10
Denis

Bonne Jounée à tous
Avatar de l’utilisateur
Ar-S
Messages : 9540
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: [Résolu] Capture du texte d'une fenetre externe à PB

Message par Ar-S »

Comme le topic est résolu, je me permet d'ajouter mes remerciements pour ces codes. En bidouillant celui de dobro, je me suis simplifié la vie lorsque de mon portable je veux accéder à mon réseau local. Le login et mot de passe ne sont jamais mémorisés sur ce PC (même si je coche la case...), je dois les rentrer à chaque reboot.
Comme ça me pompait, j'ai fait en sorte que le prog fasse tout tout seul.

voilà les points d'impact
Image
J'ouvre le raccourcis vers le dossier sur le reseau, la fenêtre de sécurité s'ouvre, j'execute alors le prog en PB qui fait ceci :

Copie du login dans le clipboard
Position en X sur le champ login
clic gauche
Ctrl+v

Copie du MDP dans le clipboard
position du curseur en Y+30 pour le placement sur le champ mdp
clic gauche
Ctrl+v

Position du curseur en X/Y pour le placer sur le bouton OK
Clic gauche
Vidage du clipboard.
End
Tout roule.
C'est excellent donc merci encore :P .

Voilà le code

Code : Tout sélectionner

Enumeration
		#win
		#Text_info
		#Text_info2
		#Text_info3
EndEnumeration

Declare  MouseEvent(Ereignis.l)
Declare  setpass()

Global Seconde=2
Global.s Login,MDP

Login = "votrelogin"
MDP = "votremotdepasse"

OpenWindow(#win,10,10,200,200,"",#PB_Window_SystemMenu)
StickyWindow(#win,1)
AddWindowTimer(#win, 123, seconde*1000)
AddWindowTimer(#win, 888, 1000)
TextGadget(#text_info,10,10,200,40,"Info")
TextGadget(#text_info2,10,50,200,100,"Log automatique")
TextGadget(#text_info3,10,150,200,40,"")


Repeat
		Select WaitWindowEvent() 
				Case #PB_Event_Timer 
				If EventTimer()=888
						Seconde-1
						SetGadgetText(#text_info3, Str(Seconde)+" Secondes")
				EndIf
				If  EventTimer() = 123
					setpass()
					End
			EndIf
				Case #WM_CLOSE
				End
		EndSelect
ForEver


Procedure MouseEvent(Ereignis.l)
		Mem.l=GlobalAlloc_(0,8)
		GetCursorPos_(Mem)
		mouse_event_(Ereignis|#MOUSEEVENTF_ABSOLUTE,PeekL(Mem)*($FFFF/GetSystemMetrics_(0)),PeekL(Mem+4)*($FFFF/GetSystemMetrics_(1)),0,GetMessageExtraInfo_())
		GlobalFree_(Mem)
EndProcedure



Procedure SetPass()
		ClearClipboard()
		#MOUSEEVENTF_MOVE = $1 : #MOUSEEVENTF_ABSOLUTE = $8000 : #MOUSEEVENTF_LEFTDOWN = $2 : #MOUSEEVENTF_LEFTUP = $4
		#MOUSEEVENTF_MIDDLEDOWN = $20 : #MOUSEEVENTF_MIDDLEUP = $40 : #MOUSEEVENTF_RIGHTDOWN = $8 : #MOUSEEVENTF_RIGHTUP = $10
		
		x= 950
		y = 316
			
		SetCursorPos_(x,y) ; Place le curseur sur le champ LOGIN
		MouseEvent(#MOUSEEVENTF_LEFTDOWN) ; appuis sur bouton de la souris
		Delay(100)
		MouseEvent(#MOUSEEVENTF_LEFTUP) ; relache le bouton de souris
		
		SetClipboardText(Login)
		res = keybd_event_(#VK_CONTROL,0,0,0)  ; " Appuyer sur CTRL
		res = keybd_event_(#VK_V,0,0,0)		;   " Appuyer sur V
		Delay(100)
		res = keybd_event_(#VK_V,0,2,0)      ;   " Relacher V
		res = keybd_event_(#VK_CONTROL,0,2,0)  ; " Relacher CTRL
		SetClipboardText(MDP)
		Delay(100)
		
		SetCursorPos_(x,y+29)	;	Positionne curseur sur champ PASSWORD
		MouseEvent(#MOUSEEVENTF_LEFTDOWN) ; appuis sur bouton de la souris
		Delay(100)
		MouseEvent(#MOUSEEVENTF_LEFTUP) ; relache le bouton de souris
		
		res = keybd_event_(#VK_CONTROL,0,0,0)  ; " Appuyer sur CTRL
		res = keybd_event_(#VK_V,0,0,0)		;   " Appuyer sur V
		Delay(100)
		res = keybd_event_(#VK_V,0,2,0)      ;   " Relacher V
		res = keybd_event_(#VK_CONTROL,0,2,0)  ; " Relacher CTRL
		
		SetCursorPos_(1065,434) ; Place le curseur sur le bouton OK
		MouseEvent(#MOUSEEVENTF_LEFTDOWN) ; appuis sur bouton de la souris
		Delay(100)
		MouseEvent(#MOUSEEVENTF_LEFTUP) ; relache le bouton de souris
		ClearClipboard()
EndProcedure


~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Re: [Résolu] Capture du texte d'une fenetre externe à PB

Message par nico »

C'est pas mal mais Mouse_event et Keyboard_event sont de vielles fonctions obsolètes depuis XP déjà, de plus tu fais l'utilisation du Presse Papier qui serait complètement inutile avec la nouvelle fonction SendInput:

- l'avantage non négligeable de cette fonction, c'est qu'elle permet de simuler l'appui des touches du clavier mais sans interaction avec celui-ci, c'est à dire que le changement d'état du clavier pendant l'envoi ne changera pas tes données (comme la touche CAPS par exemple ainsi que l'utilisation des touches durant l'envoie des données n'altère pas celui-ci) , de plus il est aisé de d'envoyé n'importe quels caractères dans n'importe quelles langues.

C' est plus compliqué à mettre en place, c'est vrai, mais le confort est sans égal; on trouve des exemples sur les forums.

Si tu dois remercier quelqu'un, je suis là. :lol:
Avatar de l’utilisateur
Ar-S
Messages : 9540
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: [Résolu] Capture du texte d'une fenetre externe à PB

Message par Ar-S »

Salut nico, ton exemple que j'ai trouvé est effectivement assez complexe. Pour ce que j'ai réalisé, les commandes "obsolètes" fonctionnent encore en Windows 8.1 donc ça fera l'affaire, mais je garde le sendinput à l'esprit. En revanche je risque de rebidouiller mon code pour remplacer les déplacements du curseur par de la tabulation pour passer d'un champ à un autre, ce sera plus sur au cas ou la fenêtre bouge. merci tout de même :wink:
~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Re: [Résolu] Capture du texte d'une fenetre externe à PB

Message par nico »

Bon, voici ma procédure personnelle que j'ai modifié pour la rendre compatible ASCII.

Il faut créer deux procédures, une pour envoyer du texte et une autre pour envoyer des commandes, voici la première pour commencer, je posterais l'autre plus tard, pour tester lancer Notepad par exemple en premier puis ensuite compiler le code et cliquer sur Notepad en barre de tâche pour afficher la fenêtre:

Code : Tout sélectionner

#KEYEVENTF_UNICODE = 4

Procedure SendInput(Text.s)
  Protected j.l, k.l, wVk.l = 0
  Protected *char.UNICODE, Dim SendInputData.INPUT(0)
  Protected *TexteUnicode
  
  CompilerIf #PB_Compiler_Unicode = 1
    *TexteUnicode = @Text
  CompilerElse
    *TexteUnicode = AllocateMemory((Len(Text)*2) + 2)
    PokeS(*TexteUnicode, Text, Len(Text), #PB_Unicode)
    PokeB(*TexteUnicode + 10, 0)
  CompilerEndIf
  
  k = Len(Text) * 2
  
  If k
    ReDim SendInputData(k)
    
    For j=0 To k-2 Step 2
      
      *char = *TexteUnicode + j
      
      If *char\u = 0
        ; Sécurisation du code
        Break
      ElseIf *char\u = 13
        wVk = #VK_RETURN
      ElseIf *char\u = 9
        wVk = #VK_TAB
      Else
        wVk = 0       
      EndIf
      
      SendInputData(j)\type=#INPUT_KEYBOARD
      SendInputData(j)\ki\wVk=wVk
      SendInputData(j)\ki\dwExtraInfo = 0
      SendInputData(j)\ki\dwFlags = #KEYEVENTF_UNICODE
      SendInputData(j)\ki\time = 0
      
      If wVk = 0
        SendInputData(j)\ki\wScan = *char\u
      EndIf
      
      SendInputData(j+1)\Type = #INPUT_KEYBOARD
      SendInputData(j+1)\ki\wVk = wVk
      SendInputData(j+1)\ki\dwExtraInfo = 0
      SendInputData(j+1)\ki\dwFlags = #KEYEVENTF_UNICODE|#KEYEVENTF_KEYUP
      SendInputData(j+1)\ki\time = 0
      
      If wVk = 0
        SendInputData(j+1)\ki\wScan = *char\u
      EndIf
      
    Next j
    
    Debug j
    Debug k
    SendInput_(j, SendInputData(0), SizeOf(INPUT))
  EndIf
  
  CompilerIf #PB_Compiler_Unicode <> 1
    FreeMemory(*TexteUnicode)
  CompilerEndIf
EndProcedure

Delay(4000)

SendInput("azerty"+Chr(9)+"b"+Chr(13)+"c")
SendInput("ùìò~iaallzertyââââääääêûîôÄËÜÏÖùò~âêûîôÿ¨Y¨Y^y"+Chr(13))
SendInput("Hello..."+#CRLF$+"1)"+#TAB$+"äöüÖÄÜß"+#CRLF$+"2)"+#TAB$+"§@µ{}"+#CRLF$+"3)"+#TAB$+"·©"+#CRLF$)
Dernière modification par nico le mer. 12/févr./2014 18:36, modifié 1 fois.
Avatar de l’utilisateur
Ar-S
Messages : 9540
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: [Résolu] Capture du texte d'une fenetre externe à PB

Message par Ar-S »

Merci pour la proce, marche bien avec la fenêtre active. Dans mon cas mon prog n'a pas besoin d'être activé vu que le clic souris (simulé) l'active. J'ai pas le temps de suite de tester ta proce en condition, je dois partir me faire péter la bouche par mon dentiste (g-Rom pas besoin de bulle salace je te vois déjà arriver en courant :mrgreen: )

Je testerai en revenant si je suis pas trop eclaté. En tout cas merci, le 1er essaye est très concluant.
~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Re: [Résolu] Capture du texte d'une fenetre externe à PB

Message par nico »

Attention, j'ai modifié le code de mon précédent post car je n'était pas sûr de la libération de la chaîne en mode ASCII pour TextUnicode, je crée donc une zone mémoire c'est plus sûr, j'en ai profité pour sécuriser le code en testant : If *char\u = 0 signale une fin de chaine, même si ça semble pas utile, ça ne mange pas de pain.

J'en profite pour faire une petite explication de code:

Code : Tout sélectionner

      ElseIf *char\u = 13
        wVk = #VK_RETURN
      ElseIf *char\u = 9
        wVk = #VK_TAB
      Else
J'ai choisis volontairement d'exécuter la touche enter et la touche tab comme une commande et non du texte, tout d'abord parce que c'est le cas mais aussi lors de mes essais, j'ai constaté que si on exécute ces commandes comme du texte, cela peut fonctionner mais ce n'est pas garanti (ça va dépendre de l'éditeur où l'on colle le texte), alors que dans cette configuration, il n'y a pas de problème.
Répondre