Page 2 sur 2

Re: Afficher/Activer une application déjà lancée ?

Publié : ven. 22/janv./2016 13:03
par cage
Merci pour tout ces codes.
@Ar-S
De nouveau tiré de WinAPi
Le handle de la fenêtre sous le curseur :
Je garde et je me suis fait un exe qui me sera très utile.
Fonctionne très bien.

J'ai trouvé une solution simple mais pas forcément satisfaisante.
J'utilise l'API FindWindow_("WindowClass", #NUL) pour trouver le hWnd de l'exe déjà lancé.
Comme je ne sais pas créer un "class name" avec PB pour identifier mon appli, je donne une valeur particulière a la fenêtre PB (#WinApp=999).
Donner une valeur a partir de 1000 et au dessus pose problème dans l'IDE mais pas une fois compilé.
Le titre de la fenêtre de mes applis change en cours d'utilisation, aussi pour pouvoir utiliser la fonction FindWindow_(..), il me faut le nom d'une classe.
Toutes les applis crées sans nom de classe ont pour nom de classe "WindowClass_0" si on utilise OpenWindow(0,...), "WindowClass_1" si on utilise OpenWindow(1,...), et ainsi de suite.

Ma question subsidiaire: peut-on créer un nom de classe pour une appli en PB ???

Exemple de code qui fonctionne:

Code : Tout sélectionner

EnableExplicit

#WinApp=999 ; cette valeur me permet d'avoir un nom de classe "WindowClass_999" pour mon appli

Global MyApp$ = "MyApp" : Global Mutex

Global TB_Message = RegisterWindowMessage_("TaskbarCreated")

If TB_Message
  Mutex = CreateMutex_(0,1, @MyApp$)
  If GetLastError_() = #ERROR_ALREADY_EXISTS
    ; Code manquant pour activer la fenêtre si on tente de relancer l'application.
    Define hWnd = FindWindow_("WindowClass_"+Str(#WinApp), #NUL) ; je teste "WindowClass_999"
    If hWnd
      SendMessage_(hWnd,#WM_SYSCOMMAND, #SC_RESTORE,0)
      End
    EndIf
  EndIf
EndIf

Enumeration Images
  #Image_App
EndEnumeration

Global IconApp = CatchImage(#Image_App  , ?Image_App)

Procedure initSysTray()
  If FindWindow_("Progman", #NUL) <> 0
    AddSysTrayIcon(#WinApp, WindowID(#WinApp), IconApp)
    SysTrayIconToolTip(#WinApp, MyApp$)
  EndIf
EndProcedure

Procedure TaskbarCallback(hWnd, Msg, wParam, lParam)
  If Msg = TB_Message
    initSysTray()
  EndIf
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

ExamineDesktops()
#W=400 : #H=200
Define X = (DesktopWidth(0) -#W)/2
Define Y = (DesktopHeight(0)-#H)/2
Define Event
SetWindowCallback(@TaskbarCallback()) ; crash explorer
If OpenWindow(#WinApp, X, Y, #W, #H, "MyApp & Mutex & ...", #PB_Window_MinimizeGadget|#PB_Window_Minimize)
  initSysTray()
  SetWindowState(#WinApp, #PB_Window_Normal)
  Repeat
    Event = WaitWindowEvent()
    Select Event
      Case #PB_Event_CloseWindow : End
    EndSelect
  ForEver
EndIf

DataSection
  Image_App:
  ; size : 1150 bytes
  Data.q $1010000100010000,$0468002000010000,$0028000000160000,$0020000000100000,$0000002000010000
  Data.q $0000000004400000,$0000000000000000,$0000000000000000,$0000000000000000,$0000000000000000
  Data.q $0000000000000000,$0000000000000000,$0000000000000000,$0000000000000000,$0000000000000000
  Data.q $0000000000000000,$50752D2D3E5A0100,$2A2A553045639433,$0000000000000600,$0000000000000000
  Data.q $0000000000000000,$8E8A144C4C3F0000,$7575A8939390838C,$4663020000005075,$6093BE4F709A2431
  Data.q $4764E2305381FD39,$000005000033562F,$0000000000000000,$4B3C000000000000,$B5B38D929290113C
  Data.q $8785A38E8E8CE2B5,$4C69040000008887,$81AFDB5E80AC3534,$5481FE385F93FE5E,$0000512F4561DF31
  Data.q $0000000000000400,$8F8D0F4444440000,$B7B4F4B8BAB6858F,$6B65BF9D9E9CFCB6,$333301000000326B
  Data.q $81AD503C597C0500,$5F93FE5D81AFDA5F,$4361DC315481FE38,$3A3A040000004C2E,$B8B57E8B8D8B0D3A
  Data.q $9D9AFCB5B6B3F2B7,$00002E696963BA9D,$0000000000000100,$5478040000000000,$80AED45D7FAA483C
  Data.q $5481FE385F93FE5C,$8381522B415AD931,$B5B2F0B5B6B47A83,$625BB09B9C99FBB4,$0000010000002762
  Data.q $0000000000000000,$0000000000000000,$7DA9403B53730300,$5F93FE5A7FADCD5C,$8387EA35537CFE38
  Data.q $9895F9B1B2AFF37E,$000020575F57A598,$0000000000000100,$0000000000000000,$0000000000000000
  Data.q $506F020000000000,$7CABC95879A43935,$8084FF51739DFE57,$58589F7D7E7BFB78,$0000000000001A58
  Data.q $00240A1919190000,$0000000000000700,$2424010000000000,$1C1C040000000724,$7A94855A636D091C
  Data.q $D0CBFEA9B4BCFB65,$4C4C7C969892F8CD,$2727000000000A4C,$39398E373B3D0D13,$00000F2222227C35
  Data.q $ABA91E6E6E6E0000,$8E8C8D9D9F9D93A9,$A5A1E5ADAEAB838C,$D4CFAB838481F1A2,$A6A1EBD6DAD3DCD1
  Data.q $2A2A1238383870A3,$4D4FC7393E402423,$4C4C694D5050F348,$D4D28AB6B8B60A4C,$BEBBFBC7C8C6F7D3
  Data.q $8B88F2B2B3AFFCBD,$9592113C3C3C798B,$CFCAD8D3D5D04B95,$4445BC696D6CEDCC,$5F61F0494E4FCA3F
  Data.q $999943484C4CAD5C,$A1A0E5CACBC95099,$ABA87D888886A4A1,$6B6BE2A9AAA8EBAA,$5555000000002D6B
  Data.q $858552888B880355,$4D4FFF44494BED82,$4545C76C6F70FE48,$8787010000002145,$5151869496944487
  Data.q $A8A42B5353531951,$8C8CF4C2C3C1D6A6,$0000000000004E8C,$4647243838380000,$7778FE494E50DC42
  Data.q $000049656868DA73,$0000000000000200,$5252081F1F1F0300,$C4C1AC9D9E9B1F52,$7272B8B4B4B2F3C3
  Data.q $0000010000003172,$545552373B3B0600,$6969DB747677EB4F,$0000040000004D69,$0000000000000000
  Data.q $6666000000000000,$A2A2BBAFB1AE3466,$00001965656576A2,$3F3F381F24241000,$7272CE4F5455783B
  Data.q $3F3F4768686BBE6E,$0000000000000400,$0000000000000000,$0000000000000000,$3333175858580300
  Data.q $0000000000000533,$3A3A252222220700,$42423A464A4A4136,$0000020000001742,$0000000000000000
  Data.q $FFFF000000000000,$C0030000E0070000,$0100000080010000,$07C0000003800000,$1080000019E00000
  Data.q $0000000000800000,$8101000000010000,$07C0000003000000
  Data.b $00,$00,$C4,$0F,$00,$00
  Tool_ico_end:
EndDataSection

Re: Afficher/Activer une application déjà lancée ?

Publié : ven. 22/janv./2016 16:23
par cage
@Spock
Le nom du '"Program Manager" sous Windows est "Progman" en terme de "Class Name"
On parle donc de "Class Name" pour identifier une fenêtre.
Dans Windows, Microsoft oblige, chaque application a son "Class Name"
Une application une fois lancée est gérable par son handle.
On peut lui envoyer des messages type CLOSE, MINIMIZE, MAXIMIZE, RESTORE, etc...
Regarde l'aide de l'API FindWindow_(..) pour voir que le premier paramètre est LPCTSTR lpClassName
Il faut donc trouver le handle de la fenêtre principale de l'application pour pouvoir agir dessus.
En partant du PID de l'application, on retrouve son handle propre mais pas celui de sa fenêtre si elle existe. Toutes les applications n'ont pas forcément une fenêtre.
Je n'ai pas trouvé de moyen simple de trouver le handle de la fenêtre d'une application qui est la seule chose qui permet de s'adresser a une application et une seule.
Si tu compile 10 applications PB qui ont un OpenWindow(0, ...), toutes tes applications ont un "Class name" égal a "WindowClass_0". Tu ne peux donc pas t'adresser a une appli en particulier.

Comme tu vois, rien a voir avec la POO. Je viens de VB ou je codais en procédural même si VB est fortement orienté Objet ce qui pour était pour moi une bonne chose.
Je ne confonds pas langage objet avec les propriétés/événements des objets VB qui facilitent la vie quand on code. form.objet.propriété = quelque chose est mieux a mon sens que Get ou Set surtout quand on vois le nombre incroyable de propriétés/événements que possédent les objets VB. Mais c'est une autre discussion.

Ma question initiale était de ré-activer une fenêtre déjà lancée. (exe PB avec interface graphique=GUI=fenêtre)
Tout ce que j'ai trouvé sur le net est incroyablement compliqué.
La solution que j'ai évoqué est très simple

Code : Tout sélectionner

If GetLastError_() = #ERROR_ALREADY_EXISTS And #RUNONE ; #MONO_INSTANCE
    ;;; One instance of application is already started
    Define hWnd = FindWindow_("WindowClass_"+Str(#WinApp), #NUL)
    If hWnd
      SendMessage_(hWnd,#WM_SYSCOMMAND, #SC_RESTORE,0)
      End
    EndIf
    End
  EndIf
Reste la question de pouvoir donner un "Class Name" a notre programme VB pour l'identifier en terme de fenêtre comme un Mutex l'identifie en mémoire pour savoir s'il est déjà en cours d'exécution.

A priori, on peut lire un "Class Name" par une fonction Get mais il n'y a pas de fonction Set pour le créer.

S'il n'y a pas de solution simple, peut-être que Fred pourrait modifier la fonction OpenWindow pour ajouter cette possibilité.

Je te donne un site riche en utilitaires et qui a bonne réputation : http://www.nirsoft.net
Regarde http://www.nirsoft.net/utils/winexp.html (fonctionne aussi sous W10) et tu verras tout un tas d'informations sur les process qui tournent sur ton PC dont le fameux Class
:wink:

Re: Afficher/Activer une application déjà lancée ?

Publié : ven. 22/janv./2016 17:05
par falsam
cage a écrit :Reste la question de pouvoir donner un "Class Name" a notre programme pour l'identifier en terme de fenêtre comme un Mutex l'identifie en mémoire pour savoir s'il est déjà en cours d'exécution.
Peut etre que la solution consiste à donner un nom au mutex ?

Code : Tout sélectionner

Define.i Mutex
Define.s Message, MutexName

;La solution est peut être de donner un nom au mutex
MutexName = "Class_Single_Instance"

;L'application est elle lancé ?
Mutex = OpenMutex_(#MUTEX_ALL_ACCESS, 0, @MutexName)

If Mutex <> 0
  ;Ha oui elle est lancée
  Message = "Cette application est déja lancée avec le mutex " + Str(Mutex)
  MessageRequester("Information", Message)
  
Else
  
  ;L'application n'est pas encore lancée : Création d'un mutex
  Mutex = CreateMutex_(0, 0, @MutexName)
  
  Message = "L'application n'est pas encore lancer : Création du mutex " + Str(Mutex) 
  MessageRequester("Information", Message)
  
  ;Ouverture de l'application
  If OpenWindow(0, 0, 0, 800, 600, "Une seule instance " + Str(Mutex), #PB_Window_MinimizeGadget|#PB_Window_ScreenCentered)
    AddSysTrayIcon(1, WindowID(0), LoadIcon_(#Null, #IDI_WARNING))
    
    Repeat 
      Select WaitWindowEvent() 
        Case #PB_Event_CloseWindow 
          If Mutex <> 0
            CloseHandle_(Mutex) 
            End
          EndIf    
          
      EndSelect     
    ForEver
  EndIf
EndIf
Par contre, Je n'ai pas réussi à afficher la fenêtre quand elle est réduite dans la barre des taches par exemple.

Intéressant ce sujet , je suis de prés .....

Re: Afficher/Activer une application déjà lancée ?

Publié : ven. 22/janv./2016 17:44
par nico
@Denis,

Non j'ai réagis comme toi, j'ai cru que c'était l'enregistrement d'un message perso mais non, il s'agit bien d'un message global et officiel que l'on retrouve ici:
https://msdn.microsoft.com/en-us/librar ... s.85).aspx

Pour le message, je pense que c'est bon.

Re: Afficher/Activer une application déjà lancée ?

Publié : ven. 22/janv./2016 18:15
par Anonyme2
Merci Nico,

je viens de lire quelques pages de ton lien et le message ABM_GETTASKBARPOS semble intéressant(client depuis Windows XP et server depuis Windows 2000).

Je vais essayer de regarder si j'ai un peu de temps pour définir si la barre de tache existe.

Re: Afficher/Activer une application déjà lancée ?

Publié : sam. 23/janv./2016 12:24
par cage
@Ar-S: Ce code me retourne toujours "Rien lancé."
La variable PN$ ne contient qu'une lettre (debug PN$) a chaque boucle du While

Code : Tout sélectionner

;Autor: ts-soft

EnableExplicit

Procedure CheckRunningPureBasic(Name.s)
  Protected result.l, Snapshot.l, ProcessFound.l, PN$, Process.PROCESSENTRY32
  Process\dwSize = SizeOf(PROCESSENTRY32)
  Snapshot = CreateToolhelp32Snapshot_(#TH32CS_SNAPPROCESS, 0)
  If Snapshot
    ProcessFound = Process32First_(Snapshot, Process)
    While ProcessFound
      PN$ = UCase(PeekS(@Process\szExeFile, #PB_Any, #PB_Ascii))
      If UCase(Name) = GetFilePart(PN$) : result = #True : Break : EndIf
      ProcessFound = Process32Next_(Snapshot, Process)
    Wend
    CloseHandle_(Snapshot)
  EndIf
  ProcedureReturn result
EndProcedure

If CheckRunningPureBasic("PureBasic.exe")
  MessageRequester("","Programme est en cours d'exécution.",0)
Else
  MessageRequester("","Rien lancé.",0)
EndIf
Voici les deux fonctions que j'ai retenu et qui fonctionnent très bien pour moi (Win10/64-bit) et PB 5.41 LTS
getNamePID : trouve le PID d'un programme a partir du nom de l'exécutable
findWindowTitle : trouve le handle d'une fenêtre a partir d'une partie du titre de la fenêtre

Code : Tout sélectionner

EnableExplicit

Define ptrPID = 0 : Define progr$ = "PureBasic.exe"
Define ptrHW  = 0 : Define titre$ = "PureBasic 5."

Procedure.i getNamePID(ProcessName.s,*ptrPID)
  Protected HSnap.l,Prec.processentry32,result.l=#False
  HSnap=CreateToolhelp32Snapshot_(#TH32CS_SNAPPROCESS,0)
  If HSnap=#INVALID_HANDLE_VALUE
    ProcedureReturn result
  EndIf
  Prec\dwSize=SizeOf(prec)
  If Not Process32First_(HSnap,Prec)
    ProcedureReturn result
  EndIf
  Repeat
    If LCase(GetFilePart(PeekS(@Prec\szexefile)))=LCase(ProcessName)
      PokeL(*ptrPID,Prec\th32ProcessID)
      result=#True
      Break
    EndIf
  Until Not Process32Next_(HSnap,Prec)
  CloseHandle_(HSnap)
  ProcedureReturn result
EndProcedure

Procedure.i findWindowTitle(tSearch.s,*ptrHW)
  Protected hWnd.i, tWnd.s
  hWnd = GetWindow_(GetDesktopWindow_(), #GW_CHILD)
  While hWnd
    tWnd = Space(GetWindowTextLength_(hWnd) + 2)
    GetWindowText_(hWnd, tWnd, Len(tWnd))
    If FindString(LCase(tWnd), LCase(tSearch))
      PokeL(*ptrHW,hWnd)
      ProcedureReturn #True
    EndIf
    hWnd = GetWindow_(hWnd, #GW_HWNDNEXT)
  Wend
  ProcedureReturn #False
EndProcedure

Debug "TEST 1 ==> getNamePID("+progr$+", "+@ptrPID+")"+#CRLF$

If getNamePID(progr$, @ptrPID)
  Debug "Le PID du programme ["+progr$+"] est "+ptrPID+#CRLF$
  Debug "Le programme ["+progr$+"] est en cours d'exécution."+#CRLF$
Else
  Debug "Le programme ["+progr$+"] n'est pas lancé."+#CRLF$
EndIf

Debug "TEST 2 ==> findWindowTitle("+progr$+", "+@ptrHW+")"+#CRLF$

If findWindowTitle(titre$,@ptrHW)
  Debug "Le handle de la fenêtre ["+titre$+"] est "+ptrHW+#CRLF$
  Debug "Le programme ["+progr$+"] est en cours d'exécution."+#CRLF$
  SendMessage_(ptrHW,#WM_SYSCOMMAND, #SC_MINIMIZE,0)
  Delay(1000)
  SendMessage_(ptrHW,#WM_SYSCOMMAND, #SC_RESTORE,0)
  SetForegroundWindow_(ptrHW)
Else
  Debug "Le programme ["+progr$+"] n'est pas lancé."+#CRLF$
EndIf

Re: Afficher/Activer une application déjà lancée ?

Publié : sam. 23/janv./2016 15:21
par nico
@Cage,

Tu les faits comment test tests et tu travailles sur quel système?

Le code pour lancer une seule instance existe depuis des lustres, il est simple et Denis et moi te l'avons donner (tirer de MSDN), je te dis ça pour t'éviter de réinventer la roue, toutefois il y a peut être y avoir un problème au niveau des attributs de sécurité mais j'en doute.

Si tu me donnes ton code complet et la façon dont tu t'y prends, je veux bien passer un peu de temps pour faire des tests.

Re: Afficher/Activer une application déjà lancée ?

Publié : sam. 23/janv./2016 17:40
par nico
Dans ce cas, tu fais un stickywindow!

Re: Afficher/Activer une application déjà lancée ?

Publié : sam. 23/janv./2016 17:57
par nico
Au lieu de simplement terminer l'application si le Mutex existe, je voudrais ré-afficher cette application.
Il souhaite réafficher sa fenêtre existante lors d'une deuxième instance, non?.

Re: Afficher/Activer une application déjà lancée ?

Publié : sam. 23/janv./2016 18:51
par cage
Heu, tout est dans le titre.
Le but est d’empêcher de lancer une application déjà lancée et soit de l'activer, c'est a dire de l'afficher et de lui donner le focus, soit de ne rien faire et de quitter avant de lancer une deuxième instance.
Comme j'utilise un mutex dans mes progs, aucune difficulté pour tester si le mutex existe déjà et quitter.
C'est ce que je faisais jusqu’à maintenant.
Mais je veux aller plus loin et ré-afficher l'instance déjà existante.
J'ai donc besoin de pouvoir communiquer avec cette instance en mémoire pour lui envoyer des messages de type RESTORE, MAXIMIZE, MINIMIZE, CLOSE ou autre.
J'ai aussi besoin de pouvoir communiquer avec une application tierce dont je ne connais que le nom de l'exe pour les mêmes raisons.
Pas si simple que cela a faire si j'en juge par toutes les demandes que j'ai trouvé sur les différents forums anglais et français pour C, C++, PureBasic, Net, AutoHotkey, etc...
J'ai vu des solutions qui faisaient plusieurs pages de code et auxquelles je ne comprenais rien.
J'ai donc fais une synthèse de tout cela et gardé les solutions les plus simple et qui sont a ma portées.
Je ne cherche pas a copier bêtement du code, mais a comprendre comment d'autres y sont arrivés ou pas et a faire quelque chose a ma sauce.
L'utilisation du "ClassName" pour identifier ses progs me parait une très bonne solution, c'est pour cela que je l'utilise maintenant.
Voila a quoi je suis arrivé non sans mal pour répondre a ma question initiale, mais c'est motivant.
Cela reste a améliorer c'est sur, mais au moins je comprend ce que j'ai codé.
Dans l'exemple qui suit, il suffit de changer #RUNONE = #True par #False pour tester les deux cas.
#RUNONE = #True n'autorise qu'une instance et elle est ré-affichée si elle existe déjà.
#RUNONE = #False autorise de créer autant d'instance qu'on le souhaite.
J'ai laissé la possibilité d'afficher un message, mais non utilisé dans l'exemple.
Vu la simplicité d'utilisation des "ClassName", c'est pour cela que j'ai émis l'idée que Fred puisse implémenter cette fonctionnalité dans PB pour pouvoir donner le nom que l'on souhaite a cette "ClassName"

Code : Tout sélectionner

EnableExplicit

OnErrorGoto(?ErrorHandler)

#MyApp$ = "myapp"    ; nom de l'exécutable

#TITLE$ = #MyApp$    ; titre MessageBox et autres

#RUNONE = #True      ; ? l'applicationne peut être lancée qu'une fois ???

Global Mutex
Global Message$

#WinAppWidth  = 270
#WinAppHeight = 210
#WinAppTitle$ = #MyApp$

; https://msdn.microsoft.com/en-us/library/windows/desktop/cc144179%28v=vs.85%29.aspx
Global TB_Message = RegisterWindowMessage_("TaskbarCreated")

CompilerIf #PB_Compiler_Debugger
  ;;; Nous sommes dans l'IDE
  #WinApp = 999
CompilerElse
  ;;; Je choisi un nombre différent pour chacune de mes applications
  ;;; Pour cette application, le "ClassName" de mon appli sera "WindowClass_50"
  #WinApp = 50
CompilerEndIf

Procedure messageBox(request = #False)
  Protected flag = #PB_MessageRequester_Ok ;|#MB_ICONINFORMATION
  If request
    flag = #PB_MessageRequester_YesNo ; |#MB_ICONQUESTION
  EndIf
  ProcedureReturn MessageRequester(#TITLE$, Message$, flag | #MB_TOPMOST)
EndProcedure

CompilerIf #PB_Compiler_Debugger
; "On est dans l'interface de développement."
CompilerElse
  If TB_Message
    Mutex = CreateMutex_(#Null, #False, #MyApp$)
    If GetLastError_() = #ERROR_ALREADY_EXISTS And #RUNONE ; #MONO_INSTANCE
      Define hWnd = FindWindow_("WindowClass_"+Str(#WinApp), #NUL)
      If hWnd
        SendMessage_(hWnd,#WM_SYSCOMMAND, #SC_RESTORE,0)
        SetForegroundWindow_(hWnd)
        End
      EndIf
      Message$ = "L'application est déjà lancée."
    EndIf
  EndIf
  If Message$ <> #Null$
    messageBox()
    End
  EndIf
CompilerEndIf

Define Flags = #PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget|#PB_Window_WindowCentered

ExamineDesktops()
Define X = (DesktopWidth(0)-#WinAppWidth)/2
Define Y = (DesktopHeight(0)-#WinAppHeight)/2
Define Event
If OpenWindow(#WinApp, X, Y, #WinAppWidth, #WinAppHeight, #WinAppTitle$, Flags)
  HideWindow(#WinApp, #False, #PB_Window_ScreenCentered)
  Repeat
    Event = WaitWindowEvent()
    Select Event
      Case #PB_Event_CloseWindow
        Break
    EndSelect
  ForEver

ErrorHandler:
  End
EndIf

Re: Afficher/Activer une application déjà lancée ?

Publié : sam. 23/janv./2016 19:16
par nico
Je ne vois pas où est le problème quand tu lances une deuxième instance, il suffit normalement d'envoyer un Message en Broadcast sendmessage_(HWND_BROADCAST, MonMessage, valeur1,valeur2)

Pour la valeur de MonMessage, celle-ci doit être supérieure ou égale à WM_USER, il vaut mieux passer par RegisterWindowMessage, il faudra le faire pour tous les programmes que tu vas créés sinon il faut faire une recherche par la classe et/ou le titre pour des progs externes que tu n'aurais pas réalisés.

Re: Afficher/Activer une application déjà lancée ?

Publié : sam. 23/janv./2016 19:40
par cage
J'ai testé tout ce qu'on m'a proposé, mais ne marche correctement, ou alors de façon aléatoire.
La solution que j'ai trouvée est très simple et fonctionne a tous les coups.
Juste avoir un numéro différent lorsque l'on crée la fenêtre puisque PB ne permet pas de créer son propre ClassName (autrement, le ClassName pourrait être le nom de son application)
notepad.exe => Notepad
notepad++.exe => Notepad++
program manager => Progman

Code : Tout sélectionner

CompilerIf #PB_Compiler_Debugger
  ;;; Nous sommes dans l'IDE
  #WinApp = 999
CompilerElse
  ;;; Je choisi un nombre différent pour chacune de mes applications
  ;;; Pour cette application, le "ClassName" de mon appli sera "WindowClass_50"
  #WinApp = 50
CompilerEndIf

If OpenWindow(#WinApp, X, Y, #WinAppWidth, #WinAppHeight, #WinAppTitle$, Flags)
  HideWindow(#WinApp, #False, #PB_Window_ScreenCentered)
  Repeat
    Event = WaitWindowEvent()
    Select Event
      Case #PB_Event_CloseWindow
        Break
    EndSelect
  ForEver
ErrorHandler:
  End
EndIf
puis au lancement de l'appli

Code : Tout sélectionner

CompilerIf #PB_Compiler_Debugger
; "On est dans l'interface de développement."
CompilerElse
  Mutex = CreateMutex_(#Null, #False, #MyApp$)
  If GetLastError_() = #ERROR_ALREADY_EXISTS
    Define hWnd = FindWindow_("WindowClass_"+Str(#WinApp), #NUL)
    If hWnd ; on ré-affiche l'application
      SendMessage_(hWnd,#WM_SYSCOMMAND, #SC_RESTORE,0)
      SetForegroundWindow_(hWnd)
      End
    EndIf
  Else
    ;;; on continue et on relance l'application
  EndIf
CompilerEndIf

Re: Afficher/Activer une application déjà lancée ?

Publié : dim. 24/janv./2016 13:07
par cage
Justement, non. Je veux un numéro unique pour l'application pour pouvoir l'identifier.

Ce numéro sert a créer le ClassName ==> WindowClass_Numéro

Le Gestionnaire de Programme (Program Manager) s'appelle et s’appellera toujours Progman

Le Tray Window s'appelle et s’appellera toujours Shell_TrayWnd

C'est bien pour cela qu'il est si facile de dialoguer avec eux

!!! Et c'est bien cela que je veux faire avec mes propres applications. !!!

Code : Tout sélectionner

lHwd = FindWindow_("Progman", #NUL)

If lHwd
  ShowWindow_(lHwd, #SW_HIDE)

  Delay(2000)

  ShowWindow_(lHwd, #SW_SHOW)
EndIf

lHwd = FindWindow_("Shell_TrayWnd", #NUL)

If lHwd
  ShowWindow_(lHwd, #SW_HIDE)

  Delay(2000)

  ShowWindow_(lHwd, #SW_SHOW)
EndIf