Détection d'une fenêtre

Programmation d'applications complexes
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Détection d'une fenêtre

Message par Le Soldat Inconnu »

Salut,

Une question, je ne me suis pas encore trop pencher dessus, ci ça trouve, c'est tout bête, mais pour le moment, je vois pas donc je vais sollicité qlq cerveaux du forum

Ma question est la suivante :
Comment faire pour détecter la création d'une nouvelle fenêtre sous windows. Je m'explique, j'ai un prog PB et je veux qu'il détecte quand on crée une nouvelle fenêtre (n'importe quel programme).
Alors si en plus, ça me donne le handle de la fenêtre, ce serait nickel

voilà :wink:

A+
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
Oliv
Messages : 2117
Inscription : mer. 21/janv./2004 18:39

Message par Oliv »

Moi je rajouterai, comment savoir si sont programme tourne déjà pour ne pas le lancer une 2ème fois ?
T€r$@k€n
Messages : 42
Inscription : ven. 23/janv./2004 18:49

Message par T€r$@k€n »

Moi je rajouterai, comment savoir si sont programme tourne déjà pour ne pas le lancer une 2ème fois ?
Je ne sais pas si c'est possible, mais je pense qu'il suffirait au lancement de ton programme créer un fichier temporaire.
Lors de chaque execution de ton programme il verifira la presence de ce fichier avant de se lancer.
Il ne faut pas oublier par contre de supprimer ce fichier [ quand tu quittes le programme ]...
Ceci est Juste une idée ...

T£r$Ak£n :)
Image
_______________________________________
Avatar de l’utilisateur
Chris
Messages : 3731
Inscription : sam. 24/janv./2004 14:54
Contact :

Message par Chris »

Ceci est Juste une idée ...
C'est même la meilleure pour ce genre de truc!
Il suffit de vérifier la présence du fichier, donc, pas d'accès disque.
Pas de bidouillage dans la base de registre!

L'idéal, quoi!! :)

Chris :)
filperj
Messages : 395
Inscription : jeu. 22/janv./2004 1:13

Message par filperj »

Citation:
Moi je rajouterai, comment savoir si sont programme tourne déjà pour ne pas le lancer une 2ème fois ?
Il y a un post sur le forum anglais:http://purebasic.myforums.net/viewtopic.php?p=24945
J'ai pas tout compris, mais ça a l'air intéressant :)
Le chaos l'emporte toujours sur l'ordre
parcequ'il est mieux organisé.
(Ly Tin Wheedle)
Oliv
Messages : 2117
Inscription : mer. 21/janv./2004 18:39

Message par Oliv »

Merci Filperj, pour Tersaken, oui mais quand le programme plante ? le fichier reste présent........
T€r$@k€n
Messages : 42
Inscription : ven. 23/janv./2004 18:49

Message par T€r$@k€n »

Oui, J'y ai aussi Penser ...
Il y a encore quelque chose de plus con,
Je ne connais pas assez bien Pure pour savoir si cela est Possible,
Vu que nous sommes dans application, je pense que tu te sers du mode fenetre. Vu que chaque fenetre porte Un Numero, Un Test en debut de programme qui verifirait que la fenetre 1 [ imaginons que ça soit celle de notre Programme ] ...
J'ai Regardé rapidement l'aide, et cela est tout a fait possible ; a mon avis ...

[ EDIT ] A moins que Window porte aussi ses numeros de fenetre !

T£r$Ak£n :?
Image
_______________________________________
julien
Messages : 846
Inscription : ven. 30/janv./2004 15:06
Contact :

Message par julien »

si l'exe plante, il suffit de rediriger le programme avec OnError et d'effacer le fichier

J'ai écrit un petit programme avec un fichier de reférence dans les temp et la gestion des erreur, c'est très basique mais ça marche.
Je pense qu'il doit y avoir une API pour ce truc... reste à la trouver :)

Code : Tout sélectionner

; Code de Julien

OnErrorGoto(?ERREUR)



; vérifie dans les temp 
temp$ = Space(1024):GetTempPath_(1024,temp$)

If FileSize(temp$+"FichierdeRef.run")<>-1
MessageRequester("DSL","Le programme est déja lancé en mémoire !",#MB_ICONINFORMATION)
End  
Else
CreateFile(1, temp$+"FichierdeRef.run")
CloseFile(1) 
EndIf 



If MessageRequester("","Voulez-vous provoquer une erreur ?",#PB_MessageRequester_YesNo)=6 
For k=0 To 5
erreur=10/k ; division par 0
Next k
EndIf 


MessageRequester("","Le programme est fini",#MB_ICONINFORMATION)
DeleteFile(temp$+"FichierdeRef.run")
End







ERREUR:
MessageRequester("ERREUR","Ce programme va être fermé car il a effectué une"+Chr(10)+"operation non conforme voulue par le programmeur",#MB_ICONERROR) 

DeleteFile(temp$+"FichierdeRef.run")

julien
Messages : 846
Inscription : ven. 30/janv./2004 15:06
Contact :

Message par julien »

ou mieux, si le titre de la fenêtre est statique, par exemple : "MonProg_By_julien"

il suffit de faire ceci :

Code : Tout sélectionner


; Code de Julien

; c'est la procedure qui permet cela
Procedure exelance2fois(nomfenetre$)
F=FindWindow_(0, nomfenetre$)
If F<>0
ProcedureReturn 1 ; retourne 1 si détecté
Else
ProcedureReturn 0 ; retourne 1 si détecté
EndIf
EndProcedure


; appel de la procedure
res=exelance2fois("MonProg_By_julien")
If res=1
MessageRequester("DSL","Le programme est déja lancé en mémoire !",#MB_ICONINFORMATION)
End 
EndIf 





;*********** Partie application
Enumeration
  #Window_0
EndEnumeration

;- Gadget Constants
;
Enumeration
  #Text_0
EndEnumeration


Procedure Open_Window_0()
  If OpenWindow(#Window_0, 337, 249, 208, 206,  #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_TitleBar , "MonProg_By_julien")
    If CreateGadgetList(WindowID())
      TextGadget(#Text_0, 20, 70, 180, 20, "Relance l'application sans quitter !")
      
    EndIf
  EndIf
EndProcedure



Open_Window_0()

Repeat
  
  Event = WaitWindowEvent()
  
  If Event = #PB_EventGadget
    
    ;Debug "WindowID: " + Str(EventWindowID())
    
    GadgetID = EventGadgetID()
    
    
    
  EndIf
  
Until Event = #PB_EventCloseWindow

End
.... Par contre si quelqu'un sait comment retrouver la handle d'une fenêtre avec uns partie du titre... cela serai intérrésant.... même pour les titre dynamique... :P
Fred
Site Admin
Messages : 2808
Inscription : mer. 21/janv./2004 11:03

Message par Fred »

Une bonne solution est d'enumerer les fenetres ouvertes sur le system toute les secondes par exemple:

Code : Tout sélectionner


Global OfficeRunning


Procedure.l EnumWindowsProc(hFind, lParam)

  WindowName.s = Space(255)

  If GetWindowText_(hFind, WindowName, 255)
  
    If FindString(WindowName, "Microsoft Office", 1)
      
      If FindString(WindowName, "Word", 1) Or FindString(WindowName, "Excel", 1)
        OfficeRunning = 1
      EndIf
      
    ElseIf FindString(WindowName, "Microsoft Word", 1) Or FindString(WindowName, "Microsoft Excel", 1)
      OfficeRunning = 1
    EndIf

  EndIf
    
  ProcedureReturn 1
EndProcedure

EnumWindows_(@EnumWindowsProc(), 0)

Un code qui m'a servi pour savoir si Office etait lancé.
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Re: Détection d'une fenêtre

Message par nico »

Le Soldat Inconnu a écrit :Salut,

Comment faire pour détecter la création d'une nouvelle fenêtre sous windows. Je m'explique, j'ai un prog PB et je veux qu'il détecte quand on crée une nouvelle fenêtre (n'importe quel programme).
Alors si en plus, ça me donne le handle de la fenêtre, ce serait nickel

voilà :wink:

A+
Tu pourrait scanner les fenetres ouvertes plusieurs fois dans ton programme, comparer les résultats obtenus...et à partir de là, tu peux avoir tous les renseignements que tu désires.

Voici un petit programme pour t'aider à lister les programme en cours:

Code : Tout sélectionner

Enumeration
  #Window_0
EndEnumeration

Enumeration
  #ListIcon_0
EndEnumeration

Dim  WindowName.s(200)
Dim  WindowClass.s (200)

For a=0 To 199
WindowName(a)=Space(200) 
WindowClass(a)=Space(200)
Next a 

Global compt.l

Procedure ProcedureEnum(WindowID.l , lParam.l)
  GetWindowText_(WindowID,@WindowName(compt),200)
  GetClassName_(WindowID,@WindowClass(compt),200)
  Getwindowrect_(WindowID,@dimension.RECT)
  hwndfenetre=FindWindow_(WindowClass(compt),WindowName(compt))
  If WindowName(compt)<>""  :;pour afficher que les fenetres qui portent un nom
  AddGadgetItem(#ListIcon_0, compt, WindowName(compt)+Chr(10)+Str(hwndfenetre)+Chr(10)+Str(dimension\right-dimension\left)+"/"+Str(dimension\bottom-dimension\Top)+Chr(10)+WindowClass(compt))
  compt=compt+1
  EndIf
  ProcedureReturn 1
EndProcedure 

If OpenWindow(#Window_0, 200, 320, 610, 210,  #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_TitleBar , "Listing")

    If CreateMenu(0, WindowID())
      MenuTitle("Rafraichir")
      MenuItem( 1, "Go")
    EndIf
    
    If CreateGadgetList(WindowID())
      ListIconGadget(#ListIcon_0, 10, 10, 600, 200, "Nom", 200, #PB_ListIcon_GridLines)
      AddGadgetColumn(#ListIcon_0, 2, "Handle", 100)
      AddGadgetColumn(#ListIcon_0, 3, "Long/Larg", 100)
      AddGadgetColumn(#ListIcon_0, 4, "Class", 200) 
    EndIf
EndIf
  
  OpenLibrary(0,"user32.dll")
  CallFunction(0,"EnumWindows",@ProcedureEnum(),0)
   
Repeat
   Event = WaitWindowEvent()
  
    Select Event
       Case #PB_EventMenu
           Select EventMenuID() 
            Case 1 
                  compt=0
                  CallFunction(0,"EnumWindows",@ProcedureEnum(),0) 
          EndSelect
      EndSelect
      
Until Event = #PB_EventCloseWindow
End
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Message par nico »

Je l'ai complété:
Exécuter le programme avec le débugger, et ensuite lancer un autre programme , son titre et son handle apparaîtront dans le débugger.
Suivant le programme, plusieurs fenêtres peuvent surgir.
En ce qui me concerne, à chaque fois que je lance un programme, j'ai une fenêtre "program manager" qui apparaît. ???


Code : Tout sélectionner

Enumeration
  #Window_0
EndEnumeration

Enumeration
  #ListIcon_0
EndEnumeration

Dim  WindowName.s(200)
Dim  WindowNamecompare.s(200)
Dim  resultatcompare.s(200)
Dim  WindowClass.s (200)
Dim  hwndfenetre.l (200)

For a=0 To 199
  WindowName(a)=Space(200)
  WindowNamecompare(a)=Space(200)
  resultatcompare(a)=Space(200)
  WindowClass(a)=Space(200)
Next a 

Global compt.l,nombre.l

Procedure compare()
  For a=0 To nombre-1
    For b=0 To nombre-1
      If WindowName(a)=WindowNamecompare(b)
        resultatcompare(a)=""
      EndIf
    Next b
  Next a
  
  For a=0 To nombre-1
    If resultatcompare(a)<>""
      Debug "Titre: "+resultatcompare(a)+"         Handle: "+Str(hwndfenetre(a))
    EndIf    
  Next
  
  For a=0 To 199
    WindowNamecompare(a)=WindowName(a)
  Next a 
EndProcedure

Procedure ProcedureEnum(Window.l , lParam.l)
  GetWindowText_(Window,@WindowName(compt),200)
  GetClassName_(Window,@WindowClass(compt),200)
  Getwindowrect_(Window,@dimension.RECT)
  hwndfenetre(compt)=FindWindow_(WindowClass(compt),WindowName(compt))
  If WindowName(compt)<>""  :;pour afficher que les fenetres qui portent un nom
    If IsWindowVisible_(hwndfenetre(compt))  :;seulement les fenêtres visibles
    AddGadgetItem(#ListIcon_0, compt, WindowName(compt)+Chr(10)+Str(hwndfenetre(compt))+Chr(10)+Str(dimension\right-dimension\left)+"/"+Str(dimension\bottom-dimension\Top)+Chr(10)+WindowClass(compt))
    resultatcompare(compt)= WindowName(compt)
    compt=compt+1
    EndIf
  EndIf
  ProcedureReturn 1
EndProcedure 

Procedure timerProcedure(WindowID, Message, wParam, lParam) 
  Resultat.l = #PB_ProcessPureBasicEvents 
  Select Message
    Case #wm_timer
          compt=0
          ClearGadgetItemList(0)
          CallFunction(0,"EnumWindows",@ProcedureEnum(),lParam) 
          nombre = CountGadgetItems(#ListIcon_0)
          compare()
          ;Debug nombre
  EndSelect
  ProcedureReturn Resultat 
EndProcedure 

If OpenWindow(#Window_0, 200, 160, 620, 450,  #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_TitleBar , "Listing")
    If CreateGadgetList(WindowID())
      ListIconGadget(#ListIcon_0, 10, 10, 600, 400, "Nom", 200, #PB_ListIcon_GridLines)
      AddGadgetColumn(#ListIcon_0, 2, "Handle", 100)
      AddGadgetColumn(#ListIcon_0, 3, "Long/Larg", 100)
      AddGadgetColumn(#ListIcon_0, 4, "Class", 200) 
    EndIf
EndIf
  
OpenLibrary(0,"user32.dll")
CallFunction(0,"EnumWindows",@ProcedureEnum(),0)

For a=0 To 199 
  WindowNamecompare(a)=WindowName(a)
Next a 
  settimer_( WindowID(),1,2000,0)
  
  SetWindowCallback(@timerProcedure()) 
  
Repeat
   Event = WaitWindowEvent()
   Select Event 
      Case #PB_EventCloseWindow 
        killtimer_(WindowID(),1)
        quit.l=1 
  EndSelect
Until quit=1
julien
Messages : 846
Inscription : ven. 30/janv./2004 15:06
Contact :

Message par julien »

Pour Detecter Si le Programme est lancé plusieurs fois, il y'a une
librairie qui le fait tres bien :
http://www.purearea.net/pb/download/use ... unning.zip

Voici un petit code pour l'utiliser

Code : Tout sélectionner

OpenConsole()
PrintN("Compiler un Exe pour tester cette librairie")
MyApp.s="App"

Result=AppRunning(MyApp.s)

If Result=0
PrintN ("Application lance une fois")
Else
PrintN ("Application lance plusieurs fois")
EndIf

Repeat
Delay(10)
ForEver


Invité

Message par Invité »

La méthode pour détecter s'il y a plusieurs instances d'un même programme est celle-ci:

Code : Tout sélectionner

#MUTEX_ALL_ACCESS =  $1F0001
Application.s="Essai.exe"

If OpenMutex_(#MUTEX_ALL_ACCESS,#False,Application)=0
  If CreateMutex_(#Null, #True, Application)= 0
   ;Fin du programme mutex non créer
    End
  EndIf 
Else
  MessageRequester("Information", "programme déja ouvert", #PB_MessageRequester_Ok)
  End
EndIf 

;Le reste du code ici
  MessageRequester("Information", "Fin du programme", #PB_MessageRequester_Ok) 
End
sinon on peut utiliser FindWindow. :D
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Message par nico »

Je me fait avoir à chaque fois avec le Login, désolé. :?
Répondre