XL 2010 Savoir si la calculatrice est présente ou pas

Magic_Doctor

XLDnaute Barbatruc
Bonsoir,

À partir d'un CommandButton que j'ai nommé perspicacement "Bouton_Calculatrice" je peux appeler la calculatrice :
VB:
Private Sub Bouton_Calculatrice_Click()
'CommandButton "Bouton_Calculatrice" permettant d'afficher la calculatrice

Application.ScreenUpdating = False

Dim x
      
     x = Shell("C:\Windows\System32\calc.exe", 1)

Range("C2500").Select: Application.ScreenUpdating = True

End Sub
Mais si, pour des raisons éthyliques, on clique plusieurs fois de suite sur ce même bouton, à chaque fois apparaîtra une nouvelle calculatrice.
Je voudrais tout simplement court-circuiter cet appel si la calculatrice est déjà présente. J'ai tenté ceci sans succès (du reste, je m'y attendais) :
VB:
Private Sub Bouton_Calculatrice_Click()
'CommandButton permettant d'afficher la calculatrice

Application.ScreenUpdating = False

Dim x

    If Not x Is Nothing Then Exit Sub
    x = Shell("C:\Windows\System32\calc.exe", 1)
      
Range("C2500").Select: Application.ScreenUpdating = True

End Sub
Comment s'y prendre ?
 
Dernière édition:
Solution
Bonsoir,

J'ai trouvé ça. C'est simple et, ma foi, ça marche bien pour la calculatrice.
VB:
Function IsProcessRunning(process As String) As Boolean
'********************************************************************************************
'Vérifie si une application est ouverte
'https://stackoverflow.com/questions/29807691/determine-if-application-is-running-with-excel
'********************************************************************************************
'- process : le nom de l'application (ex : "calc.exe" --> calculatrice Windows)

    Dim objList As Object
   
    Set objList = GetObject("winmgmts:") _
        .ExecQuery("select * from win32_process where name='" & process & "'")
   
    IsProcessRunning = objList.Count > 0...

Dudu2

XLDnaute Barbatruc
En fait ça s'explique quand même puisque, aucun d'entre eux, à part le bon Handle ne passe le filtre de la fenêtre visible:
WindowStyle = GetWindowLong(hWnd, GWL_STYLE)
If WindowStyle And WS_VISIBLE Then
(Voir le code de ma fonction)
Edit: C'est vrai que je m'amuse mais je fais aussi des trucs qui marchent
1593954311220.gif
 

patricktoulon

XLDnaute Barbatruc
re
je ne vois pas le rapport
un handle est un handle (addresse qui est donnée a l'ouverture de la fenêtre)

une fois que le handle est trouvé que la fenêtre soit visible ou pas tu dois pouvoir agir dessus avec showwindow
mais le fait que tu la trouve en bloquant le exit function me conforte dans le princide d'indexation de thread
le process n'est que le process la fenêtre c'est le process( 0 ou 1) selon la base utilisée
 

patricktoulon

XLDnaute Barbatruc
bon ben après test
je confirme il y a bien un soucis avec le multithread
quand il y en a qu'une de calculette en supprimant le exit do --->>>on a le bon
mais quand il y a plusieurs instance le processid est le même mais les handle sont différent par rapport a find window

comme quoi des fois il faut être prudent avant de sabrer le champagne ;) ;)surtout avec les apis windows

demonstration
demo4.gif
 
Dernière édition:

Dudu2

XLDnaute Barbatruc
Ne soit pas si pessimiste ! Tu veux toujours trouver un truc qui ne marche pas :cool:

Sur mon Windows 7, 2 calculettes = 2 processes.
Et je suis sûr que quand bien même ce ne serait qu'un seul process sur Windows 10 (?) la fonction utilisée pour la calculatrice et emballée dans le fichier du message #26 pour test indépendant, testée avec un processus multithread, retourne bien les 2 fenêtres, car elle rend un tableau des fenêtres trouvées.

De plus, en l'occurrence, comme je l'ai déjà signalé, peu importe qu'il y en ait 2 ou plus (que la fonction détecte parfaitement) puisque seule la 1ère calculatrice sera utilisée.
Et s'il fallait vraiment supprimer les autres on peut toujours faire un SendMessage(hWnd, WM_CLOSE, 0, 0) sur les Handle des fenêtres en excédent, Handles que retourne la fonction dans son tableau.
 

patricktoulon

XLDnaute Barbatruc
tiens regarde avec seulement 2 calculettes d'ouvertes
Capture.JPG


l'id de process est bien le même pour tous et en plus on trouve plus de 2 handles
la captures est plus que parlantes
pourtant dans le gestionnaire de tache
Capture.JPG

Et s'il fallait vraiment supprimer les autres on peut toujours faire un SendMessage(hWnd, WM_CLOSE, 0, 0) sur les Handle des fenêtres en excédent, Handles que retourne la fonction dans son tableau.
a oui!! et la quelle ? ;)
je ne suis pas pessimiste mais réaliste ;)
 
Dernière édition:

patricktoulon

XLDnaute Barbatruc
ben oui il plantes quand il y a x instances de calc.exe
tout du moins il font pas le job correctement

je vais te poser une question tu va y chercher la réponse tout seul (si vraiment tu trouve pas je te la donnerais) et tu comprendra pourquoi c'est pas une solution

la question
pourquoi certains développeurs préfèrent getactivewindow à findwindow

quand tu aura la réponse tu la transpose au problème qui nous préoccupe ici et tu en prendra tes résolutions ;)



après comme je l'ai dis plus haut
en ce qui concerne calc.exe
on tue tout les thread et on en ouvre un new ( ça c'est la seule solution valable) ;)
et là je viens de répondre a moitié a la question tout du moins ça devrait te mettre sur la voie ;)
 

Dudu2

XLDnaute Barbatruc
Moi je vois 2 PID différents:
2020-07-05_160444.jpg

Et d'ailleurs ça n'a aucune importante, on s'en fout car ma solution marche dans les 2 cas.
a oui!! et la quelle ?
Celle que tu veux on s'en fout.
quand tu aura la réponse tu la transpose au problème qui nous préoccupe ici et tu en prendra tes résolutions
Écoute mon Patrick, tu n'aimes pas qu'une solution qui ne vient pas de toi fonctionne et cette discussion prend une tournure que je n'aime pas car tu commences à me manquer de respect.
Je vais donc en rester là.
Tu m'as fait le même coup avec le Scroll ComboBox à chercher des arguments tirés par les cheveux pour dénigrer une solution dont la preuve par 4 est faite par la réalité du test. Idem ici.
Je te laisse donc à tes réflexions en te souhaitant une bonne fin d'après-midi.
 

patricktoulon

XLDnaute Barbatruc
je suis désolé que tu n'accepte pas des remarques
et au contraires si d'autres me trouve les solutions je m'en porte mieux ;)
faut il quelles soient valables en toutes circonstances (c'est important)
si pour toi ne pas être d'accords avec toi est un manque de respect peut être devrais tu revoir la signification de ce mot

"la réalité du test" oui chez toi ;) pas chez tout le monde

dommage, ton comportement me rappelle celui de personnes d'un autre forum que je nommerais pas

je pensais en toute crédulité(peut être) qu'un forum est justement un endroit ou l'on peut échanger des divergences d'opinions sans en avoir un gout amer ou l'ego diminué

dis moi en toute bonne fois
qu'y a t-il de plus simple que ceci
VB:
Private Sub CommandButton1_Click()
 Dim process As Object
   For Each process In GetObject("winmgmts:").ExecQuery("Select * from Win32_Process")
        If process.Caption = "calc.exe" Then process.Terminate
    Next
    Shell "C:\Windows\System32\calc.exe", vbMaximizedFocus
'et comme nous l'avons vu chopper le bon handle est compliqué
'peut etre prendre la chose a l'envers avec setwindowpos avec "-1"(pour descendre d'un cran dans l'index de position d'affichage  mais!!!!!!!! sur le handle de l'application qui est facile a avoir 
' je dis ça c'est juste une idée 
End Sub
bonne fin d'après midi a toi aussi
;)
 

Magic_Doctor

XLDnaute Barbatruc
Bonjour,

Dudu2, j'ai voulu essayer tes solutions (posts#26 & 27) qui paraissent intéressantes. Le problème, c'est que chez moi ça ne marche pas, en raison je pense de ma version d'Excel obsolète (2007 !!!). Je ne suis pas expert en la matière, mais il me semble qu'à partir d'une certaine version d'Excel (compatible 64 bits peut-être) il y a un problème avec les APIs des versions précédentes, et j'ai vu, dans tes PJ, qu'il y avait des APIs non reconnues chez moi (toutes en rouge). Il serait décidément temps que j'actualise ma version d'Excel !
Mais en tout cas merci pour l'intérêt que tu as porté à ce sujet.
 

patricktoulon

XLDnaute Barbatruc
re
bonjour @Magic_Doctor

VB:
#If VBA7 Then
Private Declare PtrSafe Function GetDesktopWindow Lib "user32" () As LongPtr
Private Declare PtrSafe Function GetWindow Lib "user32" (ByVal hwnd As LongPtr, ByVal uCmd As Long) As LongPtr
Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr
Private Declare PtrSafe Function GetWindowThreadProcessId Lib "user32.dll" (ByVal hwnd As LongPtr, ByRef lpdwProcessId As Long) As Long
Private Declare PtrSafe Function GetWindowLong Lib "user32.dll" Alias "GetWindowLongA" (ByVal hwnd As LongPtr, ByVal nIndex As Integer) As Long
Private Declare PtrSafe Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As LongPtr, ByVal lpString As String, ByVal nMaxCount As Integer) As Integer
Private Declare PtrSafe Function SetForegroundWindow Lib "user32" (ByVal hwnd As LongPtr) As Boolean
Private Declare PtrSafe Function ShowWindow Lib "user32.dll" (ByVal hwnd As LongPtr, ByVal nCmdShow As Long) As Long
#Else
Private Declare Function GetDesktopWindow Lib "user32" () As Long
Private Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, ByVal uCmd As Long) As Long
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function GetWindowThreadProcessId Lib "user32.dll" (ByVal hwnd As Long, ByRef lpdwProcessId As Long) As Long
Private Declare Function GetWindowLong Lib "user32.dll" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Integer) As Long
Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal nMaxCount As Integer) As Integer
Private Declare Function SetForegroundWindow Lib "user32" (ByVal hwnd As Long) As Boolean
Private Declare Function ShowWindow Lib "user32.dll" (ByVal hwnd As Long, ByVal nCmdShow As Long) As Long
#End If
 

Magic_Doctor

XLDnaute Barbatruc
Bonjour patricktoulon,

Je viens d'essayer ce que tu proposes (post#39) et ça marche diretement très bien (sans la fonction avec tout le tralala des différentes langues possibles et imaginables reconnues par Windows).
Donc, j'adopte !
J'imagine que dans ton dernier post il s'agit d'APIs compatibles avec Excel 2007.

Une dernière requête. Comment (toujours au moyen d'un CommandButton) appeler le Bloc Note de Windows ?
 
Dernière édition:

Magic_Doctor

XLDnaute Barbatruc
Oui, avec l'âge on devient fainéant. C'était pourtant si simple :
VB:
Private Sub Bouton_Notes_Click()

Dim process As Object

    For Each process In GetObject("winmgmts:").ExecQuery("Select * from Win32_Process")
        If process.Caption = "notepad.exe" Then process.Terminate
    Next
    Shell "C:\Windows\System32\notepad.exe", vbMaximizedFocus

End Sub
Et hop ! le Bloc Note. ¡Que linda es la vida!

Un dernier détail. Le bloc Note s'ouvre en grand, très grand : il occupe toute la surface de la feuille, et je voudrais qu'automatiquement sa taille soit nettement plus réduite pour un peu voir ce qui se passe autour. Que dois-je rajouter dans la routine ?
 

Discussions similaires

Statistiques des forums

Discussions
311 720
Messages
2 081 923
Membres
101 840
dernier inscrit
SamynoT