Chouchensb
Messages postés64Date d'inscriptionjeudi 3 mars 2005StatutMembreDernière intervention 2 septembre 2010
-
28 août 2010 à 12:08
Chouchensb
Messages postés64Date d'inscriptionjeudi 3 mars 2005StatutMembreDerniè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):
'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)
'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)
'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)
' 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)