OVH Cloud OVH Cloud

Fin de programme foireuse

9 réponses
Avatar
Gloops
Bonjour tout le monde,

Il s'agit de positionner Internet Explorer. Il y aurait bien la solution
de la reformatite, histoire que le bougre se rappelle où il est censé
s'afficher, m'enfin bon, avec tout ce qu'il y a déjà sur la machine, pas
forcément plus simple ...

Alors j'ai écrit le module ci-dessous.

ça marche très bien : ça tombe bien, hein ?

Il n'y a qu'un truc qui cloche, c'est si je veux arrêter le programme.

Il s'arrête, mais ensuite, Windows me dit que ce programme a rencontré
un problème et qu'il doit s'arrêter. Or, je trouve que mourir une fois
ça va bien comme ça, on s'en contenterait bien.

Une fois, j'en ai su un petit chouïa plus : la mémoire ne peut pas être
"read". Il y avait une adresse, aussi, mais je ne sais pas au juste
comment en tirer parti.

ça doit signifier que quelque chose prend trop de place, ou pas assez,
ou un truc du genre, mais alors quoi ...
________________________________________________________________________
Private Declare Function GetSystemMetrics Lib "user32" _
(ByVal nIndex As Long) As Long
Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Const SM_CYSCREEN = 1 'Y Size of Screen
Const SM_CXSCREEN = 0
Const VK_F12 = &H7B
Declare Function GetForegroundWindow Lib "user32" () As Long
Declare Function GetActiveWindow Lib "user32" () As Long
Declare Function MoveWindow Lib "user32" _
(ByVal hwnd As Long, ByVal x As Long, ByVal y As Long, _
ByVal nWidth As Long, ByVal nHeight As Long, _
ByVal bRepaint As Long) As Long
Private Declare Function apiGetAsyncKeyState Lib "user32" _
Alias "GetAsyncKeyState" _
(ByVal vKey As Long) _
As Integer

Private Type POINTAPI
x As Long
y As Long
End Type
Private Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Private Type WINDOWPLACEMENT
Length As Long
flags As Long
showCmd As Long
ptMinPosition As POINTAPI
ptMaxPosition As POINTAPI
rcNormalPosition As RECT
End Type
Private Declare Function ClientToScreen Lib "user32" _
(ByVal hwnd As Long, lpPoint As POINTAPI) As Long
Private Declare Function GetWindowPlacement Lib "user32" _
(ByVal hwnd As Long, lpwndpl As WINDOWPLACEMENT) As Long
Private Declare Function GetWindowText Lib "user32" _
Alias "GetWindowTextA" ( _
ByVal hwnd As Long, _
ByVal lpString As String, _
ByVal cch As Long) As Long

Public Sub Main()
Dim d As Double
Dim Largeur As Long, Hauteur As Long
Dim WinEst As WINDOWPLACEMENT
Dim strNomApp As String, strNomFenetre As String
Dim RetourTouche As Integer
strNomApp = "Microsoft Internet Explorer"
strNomFenetre = Space$(200)
Largeur = GetSystemMetrics(SM_CXSCREEN)
Hauteur = GetSystemMetrics(SM_CYSCREEN)
RetourTouche = 0
While RetourTouche = 0
hwnd = GetForegroundWindow()
GetWindowText hwnd, strNomFenetre, 200
If InStr(strNomFenetre, Chr$(0)) > 0 Then
strNomFenetre = Left$(strNomFenetre, _
InStr(strNomFenetre, Chr$(0)) - 1)
End If
strDroite = Right$(strNomApp + strNomFenetre, Len(strNomApp))
GetWindowPlacement hwnd, WinEst
If WinEst.showCmd = 3 And strDroite = strNomApp Then
MoveWindow hwnd, 0, 20, Largeur, Hauteur - 50, True
End If
DoEvents
Sleep 1000
DoEvents
DoEvents
DoEvents
RetourTouche = apiGetAsyncKeyState(VK_F12)
Wend
DoEvents
MsgBox "Fin de programme PositionneIE"
End Sub

9 réponses

Avatar
Jacques93
Bonsoit Gloops,
Gloops a écrit :
Bonjour tout le monde,

Il s'agit de positionner Internet Explorer. Il y aurait bien la solution
de la reformatite, histoire que le bougre se rappelle où il est censé
s'afficher, m'enfin bon, avec tout ce qu'il y a déjà sur la machine, pas
forcément plus simple ...

Alors j'ai écrit le module ci-dessous.

ça marche très bien : ça tombe bien, hein ?

Il n'y a qu'un truc qui cloche, c'est si je veux arrêter le programme.

Il s'arrête, mais ensuite, Windows me dit que ce programme a rencontré
un problème et qu'il doit s'arrêter. Or, je trouve que mourir une fois
ça va bien comme ça, on s'en contenterait bien.

Une fois, j'en ai su un petit chouïa plus : la mémoire ne peut pas être
"read". Il y avait une adresse, aussi, mais je ne sais pas au juste
comment en tirer parti.

ça doit signifier que quelque chose prend trop de place, ou pas assez,
ou un truc du genre, mais alors quoi ...
________________________________________________________________________
Private Declare Function GetSystemMetrics Lib "user32" _
(ByVal nIndex As Long) As Long
Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Const SM_CYSCREEN = 1 'Y Size of Screen
Const SM_CXSCREEN = 0
Const VK_F12 = &H7B
Declare Function GetForegroundWindow Lib "user32" () As Long
Declare Function GetActiveWindow Lib "user32" () As Long
Declare Function MoveWindow Lib "user32" _
(ByVal hwnd As Long, ByVal x As Long, ByVal y As Long, _
ByVal nWidth As Long, ByVal nHeight As Long, _
ByVal bRepaint As Long) As Long
Private Declare Function apiGetAsyncKeyState Lib "user32" _
Alias "GetAsyncKeyState" _
(ByVal vKey As Long) _
As Integer

Private Type POINTAPI
x As Long
y As Long
End Type
Private Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Private Type WINDOWPLACEMENT
Length As Long
flags As Long
showCmd As Long
ptMinPosition As POINTAPI
ptMaxPosition As POINTAPI
rcNormalPosition As RECT
End Type
Private Declare Function ClientToScreen Lib "user32" _
(ByVal hwnd As Long, lpPoint As POINTAPI) As Long
Private Declare Function GetWindowPlacement Lib "user32" _
(ByVal hwnd As Long, lpwndpl As WINDOWPLACEMENT) As Long
Private Declare Function GetWindowText Lib "user32" _
Alias "GetWindowTextA" ( _
ByVal hwnd As Long, _
ByVal lpString As String, _
ByVal cch As Long) As Long

Public Sub Main()
Dim d As Double
Dim Largeur As Long, Hauteur As Long
Dim WinEst As WINDOWPLACEMENT
Dim strNomApp As String, strNomFenetre As String
Dim RetourTouche As Integer
strNomApp = "Microsoft Internet Explorer"
strNomFenetre = Space$(200)
Largeur = GetSystemMetrics(SM_CXSCREEN)
Hauteur = GetSystemMetrics(SM_CYSCREEN)
RetourTouche = 0
While RetourTouche = 0
hwnd = GetForegroundWindow()
GetWindowText hwnd, strNomFenetre, 200
If InStr(strNomFenetre, Chr$(0)) > 0 Then
strNomFenetre = Left$(strNomFenetre, _
InStr(strNomFenetre, Chr$(0)) - 1)
End If
strDroite = Right$(strNomApp + strNomFenetre, Len(strNomApp))
GetWindowPlacement hwnd, WinEst
If WinEst.showCmd = 3 And strDroite = strNomApp Then
MoveWindow hwnd, 0, 20, Largeur, Hauteur - 50, True
End If
DoEvents
Sleep 1000
DoEvents
DoEvents
DoEvents
RetourTouche = apiGetAsyncKeyState(VK_F12)
Wend
DoEvents
MsgBox "Fin de programme PositionneIE"
End Sub




J'ai l'impresssion que l'initialisation de strNomFenetre n'est pas placé
au bon endroit, vu que avec :

If InStr(strNomFenetre, Chr$(0)) > 0 Then
strNomFenetre = Left$(strNomFenetre, _
InStr(strNomFenetre, Chr$(0)) - 1)

tu es succeptible de réduire sa taille, IE n'étant pas obligatoirement
THE ForeGroundWindow à ce moment là.

A vérifier avec :

Public Sub Main()
Dim d As Double
Dim Largeur As Long, Hauteur As Long
Dim WinEst As WINDOWPLACEMENT
Dim strNomApp As String, strNomFenetre As String
Dim RetourTouche As Integer
strNomApp = "Microsoft Internet Explorer"
Largeur = GetSystemMetrics(SM_CXSCREEN)
Hauteur = GetSystemMetrics(SM_CYSCREEN)
RetourTouche = 0
While RetourTouche = 0
hwnd = GetForegroundWindow()
strNomFenetre = Space$(200)
GetWindowText hwnd, strNomFenetre, 200
If InStr(strNomFenetre, Chr$(0)) > 0 Then
strNomFenetre = Left$(strNomFenetre, _
InStr(strNomFenetre, Chr$(0)) - 1)
End If
strDroite = Right$(strNomApp + strNomFenetre, Len(strNomApp))
GetWindowPlacement hwnd, WinEst
If WinEst.showCmd = 3 And strDroite = strNomApp Then
MoveWindow hwnd, 0, 20, Largeur, Hauteur - 50, True
End If
DoEvents
Sleep 1000
DoEvents
DoEvents
DoEvents
RetourTouche = apiGetAsyncKeyState(VK_F12)
Wend
DoEvents
MsgBox "Fin de programme PositionneIE"
End Sub


Quand à la valeur de 200, c'est toi qui voit :-)


--
Cordialement,

Jacques.
Avatar
Gloops
Bon, je crois que j'ai trouvé.

Si je lance le programme en double-cliquant sur un raccourci l'erreur ne
se produit pas, si je le lance avec une combinaison de touches elle se
produit.

J'ai utilisé GetProcesses cité par Zoury ici
http://groups.google.fr/group/microsoft.public.fr.vb/browse_thread/thread/bf75c3fdc53c25d4/405a86c2809a48de?lnk=st&q=GetProcesses+group:microsoft.public.fr.vb&rnum=1&hl=fr
pour tester si le programme est déjà lancé.

Seulement voilà, à partir de l'interface VB6 tout se passe comme
annoncé, alors qu'une fois compilé, l'instance en cours est comptée
comme taille des processus avec l'exécutable concerné. Donc, taille non
nulle, si je fais le test là-dessus je n'exécute jamais la suite du
programme.

Comme la taille est de l'ordre de 2600, je teste si il y a plus de 2600
d'utilisé, raté, la taille des processus ne varie guère. Je me retrouve
donc avec un PositionneIE de plus dans la liste des applications.

En revanche, elles se terminent proprement. Lorsque je presse la touche
F12, j'obtiens un message par instance me signalant que le programme se
termine. Plus de "problème rencontré".

Comment pourrais-je bien m'y prendre pour que la taille des processus
soit évaluée proprement de façon à me permettre de n'exécuter le
programme qu'une fois ? Ou dois-je m'y prendre autrement pour vérifier
si le programme est déjà lancé ? C'est vrai que je pourrais créer un
fichier, ou plus rapidement une clef dans le registre.


Je doute que ce soit une question très neuve, quelqu'un a-t-il une
expérience là-dessus, ayant comparé les différents moyens ?
Avatar
Gloops
Salut,

Bon, imaginons que le nom de la fenêtre en cours soit
"MsPaint - Bille de clown"

Dans strNomFenetre je vais donc avoir
MsPaint - Bille de clown0

avec un caractère nul à la place du 0 à la fin (celui qui est placé par
GetWindowText).

Donc, InStr(strNomFenetre, Chr$(0)) va valoir 25.

Donc, Left$(strNomFenetre, InStr(strNomFenetre, Chr$(0)) - 1)
représentera les 24 premiers caractères de strNomFenetre, ce qui vaudra
MsPaint - Bille de clown

Bon, ça me paraissait être le but, non ?

Cela étant, c'est vrai que pour la longueur du titre de la fenêtre, 200
laisse seulement 170 pour le titre de la page web, soit 200 moins la
longueur de " - Microsoft Internet Explorer"

Effectivement, si une page web a un titre plus long que ça, elle ne sera
pas positionnée par mon programme. Je vais mettre 300, ça permettra de
recevoir des pages web avec des titres de 270 caractères de long, ça
commence à faire de la littérature :)

Merci pour ton intervention
________________________________________
Jacques93 a écrit, le 08/10/2005 22:54 :

Bonsoit Gloops,
Gloops a écrit :
J'ai l'impresssion que l'initialisation de strNomFenetre n'est pas placé
au bon endroit, vu que avec :

If InStr(strNomFenetre, Chr$(0)) > 0 Then
strNomFenetre = Left$(strNomFenetre, _
InStr(strNomFenetre, Chr$(0)) - 1)

tu es succeptible de réduire sa taille, IE n'étant pas obligatoirement
THE ForeGroundWindow à ce moment là.


Avatar
Jacques93
Gloops a écrit :
Salut,

Bon, imaginons que le nom de la fenêtre en cours soit
"MsPaint - Bille de clown"

Dans strNomFenetre je vais donc avoir
MsPaint - Bille de clown0

avec un caractère nul à la place du 0 à la fin (celui qui est placé par
GetWindowText).

Donc, InStr(strNomFenetre, Chr$(0)) va valoir 25.

Donc, Left$(strNomFenetre, InStr(strNomFenetre, Chr$(0)) - 1)
représentera les 24 premiers caractères de strNomFenetre, ce qui vaudra
MsPaint - Bille de clown

Bon, ça me paraissait être le but, non ?

Cela étant, c'est vrai que pour la longueur du titre de la fenêtre, 200
laisse seulement 170 pour le titre de la page web, soit 200 moins la
longueur de " - Microsoft Internet Explorer"

Effectivement, si une page web a un titre plus long que ça, elle ne sera
pas positionnée par mon programme. Je vais mettre 300, ça permettra de
recevoir des pages web avec des titres de 270 caractères de long, ça
commence à faire de la littérature :)




Ce n'est pas ce que j'ai voulu dire. Je m'explique :

tu initialises la variable :

strNomFenetre = Space$(200)

là elle fait 200 caractères, puis dans la boucle avec :

strNomFenetre = Left$(strNomFenetre, InStr(strNomFenetre, Chr$(0)) - 1)

tu est suceptible de réduire sa taille, comme tu l'indiques avec

MsPaint - Bille de clown0

strNomFenetre ne fait plus que 25 caractères, et non plus 200
A partir de là, dès que tu va rencontrer une fenêtre ayant un titre de
plus de 25 caractères => plantage. Enfin je l'interprète comme ça, et en
mettant :

strNomFenetre = Space$(200)

dans la boucle, ça ne plante plus.

--
Cordialement,

Jacques.
Avatar
Jacques93
Jacques93 a écrit :
Gloops a écrit :

Salut,

Bon, imaginons que le nom de la fenêtre en cours soit
"MsPaint - Bille de clown"

Dans strNomFenetre je vais donc avoir
MsPaint - Bille de clown0

avec un caractère nul à la place du 0 à la fin (celui qui est placé
par GetWindowText).

Donc, InStr(strNomFenetre, Chr$(0)) va valoir 25.

Donc, Left$(strNomFenetre, InStr(strNomFenetre, Chr$(0)) - 1)
représentera les 24 premiers caractères de strNomFenetre, ce qui vaudra
MsPaint - Bille de clown

Bon, ça me paraissait être le but, non ?

Cela étant, c'est vrai que pour la longueur du titre de la fenêtre,
200 laisse seulement 170 pour le titre de la page web, soit 200 moins
la longueur de " - Microsoft Internet Explorer"

Effectivement, si une page web a un titre plus long que ça, elle ne
sera pas positionnée par mon programme. Je vais mettre 300, ça
permettra de recevoir des pages web avec des titres de 270 caractères
de long, ça commence à faire de la littérature :)




Ce n'est pas ce que j'ai voulu dire. Je m'explique :

tu initialises la variable :

strNomFenetre = Space$(200)

là elle fait 200 caractères, puis dans la boucle avec :

strNomFenetre = Left$(strNomFenetre, InStr(strNomFenetre, Chr$(0)) - 1)

tu est suceptible de réduire sa taille, comme tu l'indiques avec

MsPaint - Bille de clown0

strNomFenetre ne fait plus que 25 caractères, et non plus 200
A partir de là, dès que tu va rencontrer une fenêtre ayant un titre de
plus de 25 caractères => plantage. Enfin je l'interprète comme ça, et en
mettant :

strNomFenetre = Space$(200)

dans la boucle, ça ne plante plus.




Pour être plus précis,

strNomFenetre = Left$(strNomFenetre, InStr(strNomFenetre, Chr$(0)) - 1)

est succeptible de réduire la taille de la variable strNomFenetre, à 25
dans l'exemple, et tu continue à appeler l'API GetWindowText en
indiquant qu'elle fait toujours 200 :

GetWindowText hwnd, strNomFenetre, 200

Si tu remplaçais, par :

GetWindowText hwnd, strNomFenetre, Len(strNomFenetre)

Cela devrait marcher également, l'api tronquant, si nécessaire, le nom
de la fenêtre.
--
Cordialement,

Jacques.
Avatar
Gloops
Bonjour,

Effectivement, une fois que j'avais fermé l'explorateur Internet, en le
rouvrant il n'était plus positionné, et je ne comprenais pas pourquoi.
Alors j'ai mis des MsgBox un peu partout, avec strNomFenetre notamment,
et mon "about:blank - Microsoft Internet Explorer" devenait "a", c'était
donc normal qu'on ne le reconnaisse pas.

Alors j'ai effectivement mis l'initialisation dans la boucle, voilà qui
est finement observé. On dirait que tu t'en sers plus souvent que moi,
de celle-là.
________________________________________
Jacques93 a écrit, le 09/10/2005 10:48 :

Ce n'est pas ce que j'ai voulu dire. Je m'explique :

tu initialises la variable :

strNomFenetre = Space$(200)

là elle fait 200 caractères, puis dans la boucle avec :

strNomFenetre = Left$(strNomFenetre, InStr(strNomFenetre, Chr$(0)) - 1)

tu est suceptible de réduire sa taille, comme tu l'indiques avec

MsPaint - Bille de clown0

strNomFenetre ne fait plus que 25 caractères, et non plus 200
A partir de là, dès que tu va rencontrer une fenêtre ayant un titre de
plus de 25 caractères => plantage. Enfin je l'interprète comme ça, et en
mettant :

strNomFenetre = Space$(200)

dans la boucle, ça ne plante plus.



Avatar
Jacques93
Bonjour Gloops,
Gloops a écrit :
Bonjour,



[...]

Alors j'ai effectivement mis l'initialisation dans la boucle, voilà qui
est finement observé. On dirait que tu t'en sers plus souvent que moi,
de celle-là.



Je dirai que c'est un classique avec certaines API, si le buffer n'est
pas correctement dimensionné => crash, parfois avec un message, parfois
sans ... c'est selon.

--
Cordialement,

Jacques.
Avatar
Gloops
Ah oui, parfois juste le nom avec une seule lettre, parfois crash ...
ça pouvait bien être ça l'explication du programme qui avait "rencontré
un problème" ...

Jacques93 a écrit, le 09/10/2005 17:11 :

Bonjour Gloops,
Gloops a écrit :

Bonjour,




[...]

Alors j'ai effectivement mis l'initialisation dans la boucle, voilà
qui est finement observé. On dirait que tu t'en sers plus souvent que
moi, de celle-là.




Je dirai que c'est un classique avec certaines API, si le buffer n'est
pas correctement dimensionné => crash, parfois avec un message, parfois
sans ... c'est selon.



Avatar
Gloops
On va voir après le week-end, sinon on dirait qu'il va bien falloir que
je me livre à des expériences ...

Gloops a écrit, le 08/10/2005 23:26 :

Bon, je crois que j'ai trouvé.

Si je lance le programme en double-cliquant sur un raccourci l'erreur ne
se produit pas, si je le lance avec une combinaison de touches elle se
produit.

J'ai utilisé GetProcesses cité par Zoury ici
http://groups.google.fr/group/microsoft.public.fr.vb/browse_thread/thread/bf75c3fdc53c25d4/405a86c2809a48de?lnk=st&q=GetProcesses+group:microsoft.public.fr.vb&rnum=1&hl=fr

pour tester si le programme est déjà lancé.

Seulement voilà, à partir de l'interface VB6 tout se passe comme
annoncé, alors qu'une fois compilé, l'instance en cours est comptée
comme taille des processus avec l'exécutable concerné. Donc, taille non
nulle, si je fais le test là-dessus je n'exécute jamais la suite du
programme.

Comme la taille est de l'ordre de 2600, je teste si il y a plus de 2600
d'utilisé, raté, la taille des processus ne varie guère. Je me retrouve
donc avec un PositionneIE de plus dans la liste des applications.

En revanche, elles se terminent proprement. Lorsque je presse la touche
F12, j'obtiens un message par instance me signalant que le programme se
termine. Plus de "problème rencontré".

Comment pourrais-je bien m'y prendre pour que la taille des processus
soit évaluée proprement de façon à me permettre de n'exécuter le
programme qu'une fois ? Ou dois-je m'y prendre autrement pour vérifier
si le programme est déjà lancé ? C'est vrai que je pourrais créer un
fichier, ou plus rapidement une clef dans le registre.


Je doute que ce soit une question très neuve, quelqu'un a-t-il une
expérience là-dessus, ayant comparé les différents moyens ?