OVH Cloud OVH Cloud

PostMessage ...

26 réponses
Avatar
scraper
bonjour à tous !

un truc bizarre avec l'API PostMessage et FindWindow

l'API-Guide donne à peu près ceci :

Dim WinWnd As Long, Ret As String, RetVal As Long, lpClassName As String
'Search the window
WinWnd = FindWindow(vbNullString, Ret)
If WinWnd = 0 Then
MsgBox "Couldn't find the window ..."
Else
MsgBox WinWnd
End If
'Show the window
ShowWindow WinWnd, SW_SHOWNORMAL
'Create a buffer
lpClassName = Space(256)
PostMessage WinWnd, WM_CLOSE, 0&, 0&


(j'ai rajouté le msgbox WinWnd pour être certain que mon problème était pas
lié à la détection de la fenêtre)

or, je détecte bien la fenêtre que je veux fermer, mais le postmessage ne
fonctionne pas ??

il me semble que c'est la valeur de WinWND qui est pas correcte ...
(ou ce que je souhaite faire n'est pas bon !)

si je récupère le handle de la fenêtre avec Window Analyser, et que je
remplace WinWnd par cette valeur, là, ça fonctionne !!

bref, je pateauge ....



--

Attention ! Adresse mail invalide ...
Pour me contacter, cliquez sur le lien ci-dessous:
http://scraper.chez.tiscali.fr/contact.htm

scraper

10 réponses

1 2 3
Avatar
Zoury
> l'api-guide fait une erreur sur SendMesssage() dans plusieurs de ses
exemples



évidemment tu t'en moques car tu utilises PostMessage()... :O)
les déclarations provenant de l'exemple "Get Classname" de l'api-guide sont
corrects. (je crois que c'est l'exemple que tu as testé)..

--
Cordialement
Yanick Lefebvre - MVP pour Visual Basic
http://faq.vb.free.fr/?rubrique=0 - http://www.mvps.org/vbnet/
http://www.mentalis.org/agnet/apiguide.shtml - http://www.mztools.com/
Avatar
Zoury
>>>>>>>>>>>>>>>>>>>>>>>>>>>>






















































> * T'es-tu assuré que ta fenêtre est une fenêtre de premier niveau (les
> autres sont ignorées) ?























































la fenêtre sur laquelle je fais les essais, c'est la "boite de réception"
mais dire que c'est premier niveau ou pas ...

peut être n'est ce pas la bonne méthode, s'agissant de ce programme là ?


























































il ne devrait pas y avoir de probleme, j'ai testé ici et ça fonctionne. :O/
Assure toi de recherchée la fenêtre "Boîte de réception - Outlook Express"
avec i accent circonflexe et e accent aigu. ;O)

--
Cordialement
Yanick Lefebvre - MVP pour Visual Basic
http://faq.vb.free.fr/?rubrique=0 - http://www.mvps.org/vbnet/
http://www.mentalis.org/agnet/apiguide.shtml - http://www.mztools.com/
Avatar
scraper
Salut à Zoury qui dans son post
news:
nous a écrit/répondu :

l'api-guide fait une erreur sur SendMesssage() dans plusieurs de ses
exemples



évidemment tu t'en moques car tu utilises PostMessage()... :O)
les déclarations provenant de l'exemple "Get Classname" de
l'api-guide sont corrects. (je crois que c'est l'exemple que tu as
testé)..



en fait, j'ai essayé les deux, et pour être précis, je crois bien que le
comportement que je signalais (n° de handle) était sur SendMessage ...

en effet, j'ai observé que le type dewParams changeait, c'est ça ?
(entre ta fonction et celle de l'API Guide : il passe de Long chez toi à
Integer sur les API Guide )

je viens de refaire l'essai avec ta modif, et effectivement, là ça
fonctionne nickel !
un bémol cependant :
à partir de là, est il possible de faire fermer toutes les fenêtres filles
de OE en cascade, ou bien est ce que je m'y prends mal ??

si cette méthode est pas la bonne, que dois je privilégier ?

merci de ton aide

(à Stéphane aussi :-)



--

Attention ! Adresse mail invalide ...
Pour me contacter, cliquez sur le lien ci-dessous:
http://scraper.chez.tiscali.fr/contact.htm

scraper
Avatar
Zoury
> en effet, j'ai observé que le type dewParams changeait, c'est ça ?
(entre ta fonction et celle de l'API Guide : il passe de Long chez toi à
Integer sur les API Guide )



Yep. si on regarde la déclaration C++ de la fonction (Post/SendMessage les
deux sont identiques) :
'***
BOOL PostMessage(
HWND hWnd,
UINT Msg,
WPARAM wParam,
LPARAM lParam
);
'***
on voit que wParam est de type WPARAM qui est un typedef pour un unsigned
int (32 bits), il lui faut donc une variable de 4 octets pour se "mapper"
correctement (As Long).


je viens de refaire l'essai avec ta modif, et effectivement, là ça
fonctionne nickel !
un bémol cependant :
à partir de là, est il possible de faire fermer toutes les fenêtres filles
de OE en cascade, ou bien est ce que je m'y prends mal ??
si cette méthode est pas la bonne, que dois je privilégier ?



Logiquement en fermant la fenêtre principale, les sous-fenêtres devraient
aussi se fermer à moins que, par exemple, une boite de message soit apparue
pour permettre la sauvergarde de données. Quelles sont ces fenêtres qui
restent ouvertes ? Tu peux nous montrer le code que tu as jusqu'à maintenant
? on trouvera peut-être quelque chose..

--
Cordialement
Yanick Lefebvre - MVP pour Visual Basic
http://faq.vb.free.fr/?rubrique=0 - http://www.mvps.org/vbnet/
http://www.mentalis.org/agnet/apiguide.shtml - http://www.mztools.com/
Avatar
Stéphane Santon
Bonjour,

scraper a écrit :
à partir de là, est il possible de faire fermer toutes les fenêtres filles
de OE en cascade, ou bien est ce que je m'y prends mal ??
si cette méthode est pas la bonne, que dois je privilégier ?



Qu'est-ce que tu veux faire précisément au final ???
Fermer *l'application* Outlook-Express ou seulement ses fenêtres ?

Parce que pour fermer une appli, c'est le message wm_Destroy qu'il faut
envoyer, lui-même envoyant un wm_Quit.

D'ailleurs, tu peux appeler directement la fonction API
DestroyWindow( hWnd)

Mais je ne connais pas les possibilités d'appel de l'API depuis VB.
J'ai manipulé tout ça "autrefois" depuis Delphi.

--
** Anti-Spam : ajouter [usenet] dans l'objet pour ne pas être rejeté.

Cordialement, Stéphane *** http://www.team-santonum.com
Loisirs, nature, arts, technologie : accueil en Charente-Maritime
Avatar
Zoury
Salut Stéphane! :O)

Parce que pour fermer une appli, c'est le message wm_Destroy qu'il faut
envoyer, lui-même envoyant un wm_Quit.



DestroyWindow() ne ferme pas l'application... mais bien la fenêtre et ses
ressources. Cette fonction doit déjà être appeler quelque part "behind the
scene" par VB lorsque la fenêtre reçoit la notification WM_CLOSE (qui *lui*
active la fermeture de l'application). Aussi DestroyWindow() ne fonctionne
que sur les fenêtres "filles" du thread dans lequel il est utilisé.


Mais je ne connais pas les possibilités d'appel de l'API depuis VB.



Tu peux télécharger l'api-guide (voir ma sig) si tu es intéressé à voir
quelques exemples d'utilisation et de déclaration. :O)


J'ai manipulé tout ça "autrefois" depuis Delphi.



hehe! Je ne connais pas du tout Delphi, mais selon les exemples de code que
j'ai vu sur le web, tu ne devrais pas avoir de difficulté à en faire autant
avec VB. ;O)

--
Cordialement
Yanick Lefebvre - MVP pour Visual Basic
http://faq.vb.free.fr/?rubrique=0 - http://www.mvps.org/vbnet/
http://www.mentalis.org/agnet/apiguide.shtml - http://www.mztools.com/
Avatar
Stéphane Santon
Bonjour,

Zoury a écrit :
> Parce que pour fermer une appli, c'est le message wm_Destroy qu'il faut
> envoyer, lui-même envoyant un wm_Quit.

DestroyWindow() ne ferme pas l'application... mais bien la fenêtre et ses
ressources. Cette fonction doit déjà être appeler quelque part "behind the
scene" par VB lorsque la fenêtre reçoit la notification WM_CLOSE (qui *lui*
active la fermeture de l'application). Aussi DestroyWindow() ne fonctionne
que sur les fenêtres "filles" du thread dans lequel il est utilisé.



Il me semble que wm_Close est une demande de fermeture de l'application
par l'utilisateur (= Fichier|Quitter ou X sur fenêtre), alors que
wm_Destroy est une commande de fermeture de l'application.

Donc un wm_Close sur un Word avec un doc non enregistré va entraîner une
boîte de dialogue "Voulez-vous enregistrer ?".

--
** Anti-Spam : ajouter [usenet] dans l'objet pour ne pas être rejeté.

Cordialement, Stéphane *** http://www.team-santonum.com
Loisirs, nature, arts, technologie : accueil en Charente-Maritime
Avatar
scraper
Salut à Stéphane Santon qui dans son post
news:
nous a écrit/répondu :

Qu'est-ce que tu veux faire précisément au final ???
Fermer *l'application* Outlook-Express



oui :-)

ou seulement ses fenêtres ?



non ...

mais à la lumière de ce que tu m'as dit tantôt (et Zoury aussi !) j'ai
abandonné mon premier code ... ça le faisait pas : vu le nombre de fenêtres
qu'il est possible d'ouvrir sous OE, et leur titre différent ! :-( (plus
les personnalisations possibles ...)
donc, je me suis rabattu sur un nouveau projet ... mais ça colle pas encore
?
voici mon ébauche (largement inspirée de sources trouvées sur le net ...)

Option Explicit

Private Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, ByVal
wCmd As Long) As Long
Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA"
(ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
Private Declare Function GetParent Lib "user32" (ByVal Handle As Long) As
Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA"
(ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByRef lParam
As Any) As Long

Private Const GW_HWNDNEXT = 2
Private Const GW_HWNDFIRST = 0
Private Const WM_CLOSE As Long = &H10

Dim Handle As Long
Dim Title As String

Private Sub Form_Load()
Handle = GetWindow(Me.hwnd, GW_HWNDFIRST)
Handle = Me.hwnd
While Handle <> 0
Title = Space(100)
GetWindowText Handle, Title, 100
Title = Trim(Title)
If InStr(1, Title, "Outlook Express") > 0 Then
MsgBox Handle
SendMessage Handle, WM_CLOSE, 0, ByVal 0&
End If
Handle = GetWindow(Handle, GW_HWNDNEXT)

Wend

Unload Me

End Sub


à mon idée (me trompé je ?? :-) je retrouve la fenêtre qui a le titre
"outlook express" ... et je demande sa fermeture

ben pareil que tout à l'heure, ça fonctione pas et le n° de handle est pas
bon !
(et là, j'ai regardé, y'a pas d'integer ... lol

donc, je suis encore bloqué ...




--

Attention ! Adresse mail invalide ...
Pour me contacter, cliquez sur le lien ci-dessous:
http://scraper.chez.tiscali.fr/contact.htm

scraper
Avatar
François Picalausa
"scraper" a écrit dans le message de
news:
Salut à Stéphane Santon qui dans son post
news:
nous a écrit/répondu :
voici mon ébauche (largement inspirée de sources trouvées sur le net
...)




Hello,

Pour lister les windows, il existe l'API EnumWindows.
Voici un exemple d'utilisation (avec quelques fonctions en plus):

Dans un module standard (du à l'emploi d'addressof):
Option Explicit

Private Const GW_OWNER = 4
Private Const SW_NORMAL = 1

Private Type POINT
X As Long
Y As Long
End Type

'The WM_CLOSE message is sent as a signal that a window or an application
should terminate.
'An application can prompt the user for confirmation, prior to destroying a
window, by processing
'the WM_CLOSE message and calling the DestroyWindow function only if the
user confirms the choice.
Private Const WM_CLOSE = &H10


'The WM_DESTROY message is sent when a window is being destroyed. It is sent
to the window
'procedure of the window being destroyed after the window is removed from
the screen.
'This message is sent first to the window being destroyed and then to the
child windows
'(if any) as they are destroyed. During the processing of the message, it
can be assumed
'that all child windows still exist.
Private Const WM_DESTROY = &H2

Private Declare Function PostMessage _
Lib "user32" _
Alias "PostMessageA" _
( _
ByVal hwnd As Long, _
ByVal wMsg As Long, _
ByVal wParam As Long, _
ByVal lParam As Long _
) _
As Long
Private Declare Function APIEnumWindows _
Lib "user32" _
Alias "EnumWindows" _
( _
ByVal lpEnumFunc As Long, _
ByVal lParam As Long _
) _
As Long
Private Declare Function GetWindowText _
Lib "user32" _
Alias "GetWindowTextA" _
( _
ByVal hwnd As Long, _
ByVal lpString As String, _
ByVal cch As Long _
) _
As Long
Private Declare Function GetClassName _
Lib "user32" _
Alias "GetClassNameA" _
( _
ByVal hwnd As Long, _
ByVal lpClassName As String, _
ByVal nMaxCount As Long _
) _
As Long
Private Declare Function GetWindow _
Lib "user32" _
( _
ByVal hwnd As Long, _
ByVal wCmd As Long _
) _
As Long
Private Declare Function GetParent _
Lib "user32" _
( _
ByVal hwnd As Long _
) _
As Long
Private Declare Function ShowWindow _
Lib "user32" _
( _
ByVal hwnd As Long, _
ByVal nCmdShow As Long _
) _
As Long
Private Declare Function WindowFromPoint _
Lib "user32" _
( _
ByVal xPoint As Long, _
ByVal yPoint As Long _
) _
As Long
Private Declare Function GetCursorPos _
Lib "user32" _
( _
lpPoint As POINT _
) _
As Long

Private CallBackObject As Object
Private CallBackMethod As String

Public Sub EnumWindows(oObject As Object, sProc As String)
Set CallBackObject = oObject
CallBackMethod = sProc

APIEnumWindows AddressOf EnumWindowsProc, 0

Set CallBackObject = Nothing
CallBackMethod = ""
End Sub

Private Function EnumWindowsProc(ByVal hwnd As Long, ByVal lParam As Long)
As Long
Dim Continue As Boolean

CallByName CallBackObject, CallBackMethod, VbMethod, hwnd, Continue

EnumWindowsProc = CLng(Abs(Continue))
End Function

Public Function WindowText(Window As Long) As String
Dim strBufferText As String * 512
Dim ReturnLenght As Long

ReturnLenght = GetWindowText(Window, strBufferText, 512)
If ReturnLenght Then
WindowText = Left$(strBufferText, ReturnLenght)
End If
End Function

Public Function WindowClass(Window As Long) As String
Dim strBufferClass As String * 512
Dim ReturnLenght As Long

ReturnLenght = GetClassName(Window, strBufferClass, 512)
If ReturnLenght Then
WindowClass = Left$(strBufferClass, ReturnLenght)
End If
End Function

Public Function Parent(Window As Long) As Long
Parent = GetParent(Window)
End Function

Public Function Owner(Window As Long) As Long
Owner = GetWindow(Window, GW_OWNER)
End Function

Public Sub WinActivate(Window As Long)
ShowWindow Window, SW_NORMAL
End Sub

Public Sub PostClose(Window As Long)
PostMessage Window, WM_CLOSE, 0, 0
End Sub

Public Sub PostDestroy(Window As Long)
PostMessage Window, WM_DESTROY, 0, 0
End Sub

Public Function WindowFromCursorPos() As Long
Dim CP As POINT
If GetCursorPos(CP) Then
WindowFromCursorPos = WindowFromPoint(CP.X, CP.Y)
End If
End Function

'---------------------------------------------------------------------------
---------------
'Dans une form avec une listbox, list1
'et trois commandbuttons, command1, command2, command3

Option Explicit

Private Sub Command1_Click()
'List les fenêtres
List1.Clear
ModEnum.EnumWindows Me, "EnumProc"
End Sub

Private Sub Command2_Click()
'Close
If List1.ListIndex > -1 Then
PostClose List1.ItemData(List1.ListIndex)
End If
End Sub

Private Sub Command3_Click()
'Destroy - à l'usage ça ne semble pas fonctionner
If List1.ListIndex > -1 Then
PostDestroy List1.ItemData(List1.ListIndex)
End If
End Sub

Private Sub Form_Load()
Command1.Caption = "List"
Command2.Caption = "Close"
Command3.Caption = "Destroy"
End Sub

Public Sub EnumProc(Window As Long, Continue As Boolean)
'Si la fenêtre n'a ni owner ni parent
If Owner(Window) = 0 And Parent(Window) = 0 Then
'On l'ajoute à la liste
List1.AddItem WindowText(Window) & " (" & WindowClass(Window) & ")"
'Et on spécifie une item data correspondant au hWnd
List1.ItemData(List1.NewIndex) = Window
End If
'On continue l'énumération
Continue = True
End Sub

Private Sub List1_DblClick()
'Au double click sur un élément, on affiche la fenêtre sélectionnée
If List1.ListIndex > -1 Then
WinActivate List1.ItemData(List1.ListIndex)
End If
End Sub

Voila, voila...
--
François Picalausa (MVP VB)
http://faq.vb.free.fr --- http://msdn.microsoft.com
http://apisvb.europe.webmatrixhosting.net
Avatar
scraper
Salut à François Picalausa qui dans son post
news:%
nous a écrit/répondu :

Hello,

Pour lister les windows, il existe l'API EnumWindows.



ah oui .. j'avais pas réussi à la mettre en oeuvre .... (humm .... le adress
of, j'ai encore pas compris ...)

mais là, avec ton exemple, ça va beaucoup mieux !

voici ce que j'en ai tiré, adapté à mes besoins (détection de outlook
express, et si ouvert, le ferme ...)

'-----
'dans un module
Option Explicit

Public Declare Function EnumWindows Lib "user32" (ByVal lpEnumFunc As Long,
ByVal lParam As Long) As Boolean
Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA"
(ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
Private Declare Function GetWindowTextLength Lib "user32" Alias
"GetWindowTextLengthA" (ByVal hwnd As Long) As Long
Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA"
(ByVal hwnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long)
As Long
Private Declare Function PostMessage Lib "user32" Alias "PostMessageA"
(ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam
As Long) As Long

Private Const WM_CLOSE = &H10

Public Function CloseOEProc(ByVal hwnd As Long, ByVal lParam As Long) As
Boolean

Dim sSave As String, Ret As Long
Ret = GetWindowTextLength(hwnd)
sSave = Space(Ret)

GetWindowText hwnd, sSave, Ret + 1
If InStr(1, WindowClass(hwnd), "Outlook Express Browser Class") > 0
Then
PostMessage hwnd, WM_CLOSE, 0, 0
Else
CloseOEProc = True
End If

End Function

Private Function WindowClass(Window As Long) As String

Dim strBufferClass As String * 512
Dim ReturnLenght As Long
ReturnLenght = GetClassName(Window, strBufferClass, 512)
If ReturnLenght Then
WindowClass = Left$(strBufferClass, ReturnLenght)
End If

End Function

'dans une form
EnumWindows AddressOf CloseOEProc, ByVal 0&

'-----------------------

voila, je pense pas avoir commis de grossière erreur en adaptant ??


ça roule nickel, en tout cas !



merci à tous :-)

c'est vraiment super sympa ;-)


--

Attention ! Adresse mail invalide ...
Pour me contacter, cliquez sur le lien ci-dessous:
http://scraper.chez.tiscali.fr/contact.htm

scraper
1 2 3