Problème de Handle et PID ! Code qui ne fonctionne avec Paint (mais très bien av [Résolu]

Messages postés
64
Date d'inscription
jeudi 3 mars 2005
Dernière intervention
2 septembre 2010
- - Dernière réponse : Chouchensb
Messages postés
64
Date d'inscription
jeudi 3 mars 2005
Dernière intervention
2 septembre 2010
- 28 août 2010 à 13:21
Bonjour,

J'étais en train d'écrire un exemple de code pour répondre à une question de Cpcdos sur l'utilisation des SendMessage, et je suis tombé sur un bug que je ne comprends pas.

J'effectue les opérations suivantes:
- Je lance une application avec l'instruction shell()
- Je récupère ensuite le handle de la fenêtre du programme de trois façons différentes:
1. A partir du PID renvoyé par le shell et à l'aide d'un code fourni par Microsoft
2. A partir du texte de la fenêtre, avec FindWindow
3. A partir du nom de la classe de la fenêtre, avec FindWindow

Alors que tout marche parfaitement avec la calculatrice de Windows ou Notepad, ça ne fonctionne pas du tout avec Paint ?!
Quelqu'un saurait il d'où vient le bug ????

PS: je ne savais pas trop ou poster mon message, API ou VBA, j'ai opté pour API...

Ci-joint le code exemple VBA qui montre le problème (utilisable directement par copier/coller dans Excel):


---------------------------------------------------------------------------------------------------------------------------

Option Explicit

'On déclare les API
Private Declare Function SendMessage Lib "User32.dll" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByRef lParam As Any) As Long
Private Declare Function SendDlgItemMessage Lib "User32.dll" Alias "SendDlgItemMessageA" (ByVal hDlg As Long, ByVal nIDDlgItem As Long, ByVal wMsg As Long, ByVal wParam As Long, ByRef lParam As Any) As Long
Private Declare Function GetParent Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, ByVal wCmd As Long) As Long
Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwprocessid As Long) As Long
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long

'On déclare les constantes utilisées dans les API (un petit tour sur google avec "Private Const ****** As Long =" permet de vite trouver leurs valeurs !)
Private Const GW_HWNDNEXT As Long = &H2
Private Const WM_SIZE As Long = &H5
Private Const WM_CLOSE As Long = &H10
Private Const SC_SIZE As Long = &HF000

Private Const WM_SYSCOMMAND As Long = &H112
Private Const SC_MINIMIZE As Long = &HF020&
Private Const SC_MAXIMIZE As Long = &HF030&
Private Const SC_RESTORE As Long = &HF120&



'Ca c'est le programme pour Paint qui ne marche pas ?!

Sub Paint_program()

Dim pidPaint As Long
Dim hWndPaint1 As Long
Dim hWndPaint2 As Long
Dim hWndPaint3 As Long

'On ouvre Paint et on en profite pour récupérer son process ID
pidPaint = Shell("mspaint.exe", vbNormalFocus)
'On récupère le handle de la fenêtre ouverte à partir du pid (à partir d'un code fourni par Microsoft: 'http://support.microsoft.com/kb/242308)
hWndPaint1 = GetWinHandle(pidPaint)
'On peut aussi le récupérer à partir du titre de la fenêtre, mais il faut le titre complet et exact
hWndPaint2 = FindWindow(vbNullString, "Sans titre - Paint") 'Ce code marche parce qu'on a le titre exact
'hWndPaint = FindWindow(vbNullString, "Sans titre Paint") 'FindWindow va renvoyer 0, car il y a une faute dans le texte
'Dernière méthode: on peut récupérer à partir de la classe la fenêtre ( à déterminer avec spy++ ou Winspector par exmple)
hWndPaint3 = FindWindow("MSPaintApp", vbNullString)

'Petit message
MsgBox "Infos coming from the Shell" & vbCrLf & "PID: " & Hex(pidPaint) & vbCrLf & "Windows handle: " & Hex(hWndPaint1) _
& vbCrLf & vbCrLf & "hWnd from text: " & Hex(hWndPaint2) _
& vbCrLf & vbCrLf & "hWnd from classname: " & Hex(hWndPaint3)

'On réduit la fenêtre
SendMessage hWndPaint1, WM_SYSCOMMAND, SC_MINIMIZE, 0
MsgBox "Fenêtre réduite"
'On maximise la fenêtre
SendMessage hWndPaint1, WM_SYSCOMMAND, SC_MAXIMIZE, 0
MsgBox "Fenêtre agrandie"
'On restaure la taille initiale de la fenêtre
SendMessage hWndPaint1, WM_SYSCOMMAND, SC_RESTORE, 0
MsgBox "Fenêtre restaurée"
'On ferme la fenêtre
SendMessage hWndPaint1, WM_CLOSE, 0, 0
MsgBox "Programme fermé"

End Sub

'Ca c'est le programme pour Notepad qui fonctionne !

Sub Notepad_program()

Dim pidNotepad As Long
Dim hWndNotepad1 As Long
Dim hWndNotepad2 As Long
Dim hWndNotepad3 As Long

'On ouvre Paint et on en profite pour récupérer son process ID
pidNotepad = Shell("notepad", vbNormalFocus)
'On récupère le handle de la fenêtre ouverte à partir du pid (à partir d'un code fourni par Microsoft: 'http://support.microsoft.com/kb/242308)
hWndNotepad1 = GetWinHandle(pidNotepad)
'On peut aussi le récupérer à partir du titre de la fenêtre, mais il faut le titre complet et exact
hWndNotepad2 = FindWindow(vbNullString, "Sans titre - Bloc-notes") 'Ce code marche parce qu'on a le titre exact
'hWndPaint = FindWindow(vbNullString, "Sans titre Bloc-notes") 'FindWindow va renvoyer 0, car il y a une faute dans le texte
'Dernière méthode: on peut récupérer à partir de la classe la fenêtre ( à déterminer avec spy++ ou Winspector par exmple)
hWndNotepad3 = FindWindow("Notepad", vbNullString)

'Petit message
MsgBox "Infos coming from the Shell" & vbCrLf & "PID: " & Hex(pidNotepad) & vbCrLf & "Windows handle: " & Hex(hWndNotepad1) _
& vbCrLf & vbCrLf & "hWnd from text: " & Hex(hWndNotepad2) _
& vbCrLf & vbCrLf & "hWnd from classname: " & Hex(hWndNotepad3)

'On réduit la fenêtre
SendMessage hWndNotepad1, WM_SYSCOMMAND, SC_MINIMIZE, 0
MsgBox "Fenêtre réduite"
'On maximise la fenêtre
SendMessage hWndNotepad1, WM_SYSCOMMAND, SC_MAXIMIZE, 0
MsgBox "Fenêtre agrandie"
'On restaure la taille initiale de la fenêtre
SendMessage hWndNotepad1, WM_SYSCOMMAND, SC_RESTORE, 0
MsgBox "Fenêtre restaurée"
'On ferme la fenêtre
SendMessage hWndNotepad1, WM_CLOSE, 0, 0
MsgBox "Programme fermé"

End Sub

'Ca c'est le programme pour la calculatrice windows marche aussi !

Sub Calc_program()

Dim pidCalc As Long
Dim hWndCalc1 As Long
Dim hWndCalc2 As Long
Dim hWndCalc3 As Long

'On ouvre Calc et on en profite pour récupérer son process ID
pidCalc = Shell("calc.exe", vbNormalFocus)
'On récupère le handle de la fenêtre ouverte à partir du pid (à partir d'un code fourni par Microsoft: 'http://support.microsoft.com/kb/242308)
hWndCalc1 = GetWinHandle(pidCalc)
'On peut aussi le récupérer à partir du titre de la fenêtre, mais il faut le titre complet et exact
hWndCalc2 = FindWindow(vbNullString, "Calculatrice") 'Ce code marche parce qu'on a le titre exact
'hWndCalc = FindWindow(vbNullString, "Calculatric") 'FindWindow va renvoyer 0, car il y a une faute dans le texte
'Dernière méthode: on peut récupérer à partir de la classe la fenêtre ( à déterminer avec spy++ ou Winspector par exmple)
hWndCalc3 = FindWindow("SciCalc", vbNullString)

'Petit message
MsgBox "Infos coming from the Shell" & vbCrLf & "PID: " & Hex(pidCalc) & vbCrLf & "Windows handle: " & Hex(hWndCalc1) _
& vbCrLf & vbCrLf & "hWnd from text: " & Hex(hWndCalc2) _
& vbCrLf & vbCrLf & "hWnd from classname: " & Hex(hWndCalc3)

'On réduit la fenêtre
SendMessage hWndCalc1, WM_SYSCOMMAND, SC_MINIMIZE, 0
MsgBox "Fenêtre réduite"
'On maximise la fenêtre
SendMessage hWndCalc1, WM_SYSCOMMAND, SC_MAXIMIZE, 0
MsgBox "Fenêtre agrandie"
'On restaure la taille initiale de la fenêtre
SendMessage hWndCalc1, WM_SYSCOMMAND, SC_RESTORE, 0
MsgBox "Fenêtre restaurée"
'On ferme la fenêtre
SendMessage hWndCalc1, WM_CLOSE, 0, 0
MsgBox "Programme fermé"

End Sub

'Code trouvé sur http://support.microsoft.com/kb/242308 -> utilisé pour la fonction GetWinHandle
Function ProcIDFromWnd(ByVal hwnd As Long) As Long

Dim idProc As Long

' Get PID for this HWnd
GetWindowThreadProcessId hwnd, idProc

' Return PID
ProcIDFromWnd = idProc

End Function

'Code trouvé sur http://support.microsoft.com/kb/242308 -> fonction utilisée pour récupérer le handle d'une fenêtre à partir du pid du programme qui l'a lancée
Function GetWinHandle(hInstance As Long) As Long

Dim tempHwnd As Long

' Grab the first window handle that Windows finds:
tempHwnd = FindWindow(vbNullString, vbNullString)

' Loop until you find a match or there are no more window handles:
Do Until tempHwnd = 0
' Check if no parent for this window
If GetParent(tempHwnd) = 0 Then
' Check for PID match
If hInstance = ProcIDFromWnd(tempHwnd) Then
' Return found handle
GetWinHandle = tempHwnd
' Exit search loop
Exit Do
End If
End If

' Get the next window handle
tempHwnd = GetWindow(tempHwnd, GW_HWNDNEXT)

Loop

End Function
Afficher la suite 

Votre réponse

2 réponses

Meilleure réponse
Messages postés
3983
Date d'inscription
jeudi 14 juillet 2005
Dernière intervention
30 juin 2013
21
3
Merci
Fais un Sleep() après le lancement du programme, c'est pas instantanné

VB.NET is good ... VB6 is better
Utilise Réponse acceptée quand un post répond à ta question

Dire « Merci » 3

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources 134 internautes nous ont dit merci ce mois-ci

Commenter la réponse de cs_ghuysmans99
Messages postés
64
Date d'inscription
jeudi 3 mars 2005
Dernière intervention
2 septembre 2010
0
Merci
Ah ouais ! C'est tout con en fait ! Merci !
Commenter la réponse de Chouchensb

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.