Page 1 sur 2

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

Publié : jeu. 21/janv./2016 16:08
par cage
Bonjour a tous,

Petit a petit, j'essaye d'améliorer mes applications PB.
Cette fois ci, je souhaiterais pouvoir ré-afficher une application PB déjà lancée.
L'application a un Mutex que je teste au démarrage.
Au lieu de simplement terminer l'application si le Mutex existe, je voudrais ré-afficher cette application.
Est-il possible de connaitre le Handle de l'appli a partir du Mutex.
J'ai (mal) recherché sur les forums FR/EN sans rien trouver de pertinent.
Je sais trouver le PID a partir du nom de l'exe mais pas le Handle.
Pourriez-vous sans me donner la solution, me mettre sur la voie (si possible).
Pour info, le titre de mon appli change en cours d'utilisation et n'est pas prévisible.
Merci.

Code : Tout sélectionner

EnableExplicit

#WinApp=0 : Global MyApp$ = "MyApp" : Global Mutex

Mutex = CreateMutex_(0,1,MyApp$)
If GetLastError_() = #ERROR_ALREADY_EXISTS
; Code manquant pour activer la fenêtre si on tente de relancer l'application.
  End
EndIf

DataSection ; Images
  Image_App:
  IncludeBinary "MyApp.ico"
EndDataSection

Enumeration Images
  #Image_App
EndEnumeration

Global IconApp = CatchImage(#Image_App  , ?Image_App)
Global TB_Message = RegisterWindowMessage_("TaskbarCreated")

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

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

Publié : jeu. 21/janv./2016 19:33
par Ar-S
Tu as cette fonction de ts-soft des winapi qui check si l'appli est lancée

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

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

Publié : jeu. 21/janv./2016 19:47
par Anonyme2
Je ne sais pas si c'est ce que tu cherches, je pense que oui.

Enregistre l'exe et lances-le plusieurs fois pour voir
Code pompé à droite à gauche et adapté. :mrgreen:
J'ai aussi ajouté du code dans la callback

J'ai mis une icône en data car j'ai horreur d'exécuter un code ou il y a une icône non référencée, ça rebute surement du monde.

Code : Tout sélectionner

EnableExplicit

#WinApp=0 : 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.
            SendMessage_(#HWND_BROADCAST, TB_Message, 0, 0)
            If Mutex
                  CloseHandle_(Mutex)
            EndIf
            End
      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()
            
            If IsIconic_(hWnd) = #False
                  ShowWindow_(hWnd,#SW_MINIMIZE)
            EndIf
            ShowWindow_(hWnd,#SW_RESTORE)
            SetForegroundWindow_(hWnd)
      EndIf
      ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

ExamineDesktops()
#W=300 : #H=200
Define X = (DesktopWidth(0) -#W)/2
Define Y = (DesktopHeight(0)-#H)/2
Define Event
SetWindowCallback(@TaskbarCallback()) ; crash explorer
If OpenWindow(0, X, Y, #W, #H, "MyApp & Mutex & ...", #PB_Window_MinimizeGadget|#PB_Window_Minimize)
      initSysTray()
      SetWindowState(0, #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é : jeu. 21/janv./2016 21:47
par cage
@Ar-S : J'utilise un Mutex dans toutes mes apps, donc si l'app est déjà lancée et que j'essaye de la relancer, ce bout de code empêche une deuxième instance.

Code : Tout sélectionner

MyApp$ = "AppName"
Mutex = CreateMutex_(0, 1, @MyApp$)
If GetLastError_() = #ERROR_ALREADY_EXISTS
  ; Pour l'instant, j'affiche un message indiquant qu'il existe déjà une instance active
  ; Mon but, activer a l'écran l'instance existante.
  End
EndIf
Ce que je voudrais faire maintenant et qui me pose problème, c'est bien d'empêcher une deuxième instance, mais d'activer la première en l'affichant a l'écran et en premier plan pour que le "client" voit que l'application est déjà lancée.
Merci pour le code.

@Denis : j'ai fais plusieurs tests, au début cela ne fonctionnait pas du tout.
J'ai fini par recopier ton code au cas ou, et cette fois cela fonctionne.
Je vais regarder de plus près le code pour essayer de bien comprendre ce qu'il fait.
Je ne suis pas très familier avec les API de Windows et le passage de messages.
En tout cas merci de m'avoir répondu, je vais pouvoir avancer dans ma connaissance de PB
J'ai mis une icône en data car j'ai horreur d'exécuter un code ou il y a une icône non référencée, ça rebute surement du monde.
Merci pour la solution. Je retiens pour les fois prochaines.
Gérard

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

Publié : jeu. 21/janv./2016 22:26
par cage
@Denis
Je crois que j'ai répondu trop vite. Cela ne refonctionne plus.
Mon exe qui fonctionnait tout a l'heure ne fonctionne plus.
L'exe est visible plusieurs fois dans le TaskMgr et il faut les killer a la main.
J'ai l'impression que c'est aléatoire.
Gérard

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

Publié : jeu. 21/janv./2016 22:46
par nico
Essayes avec ça:

Code : Tout sélectionner

If TB_Message
  SetLastError_(#NO_ERROR)
  
  Mutex = CreateMutex_(#Null, #False, @MyApp$)
  Erreur.l = GetLastError_()
  If (Erreur = #ERROR_ALREADY_EXISTS) Or (Erreur = #ERROR_ACCESS_DENIED)
    
    ; Code manquant pour activer la fenêtre si on tente de relancer l'application.
    SendMessage_(#HWND_BROADCAST, TB_Message, 0, 0)
    If Mutex
      CloseHandle_(Mutex)
    EndIf
    End
  EndIf
EndIf

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

Publié : jeu. 21/janv./2016 23:36
par cage
Merci nico, mais cela ne change rien.

Je me posais la question si a partir du PID de l'exe on pouvait faire quelque chose.

Je connais le mutex, le nom de l'exe, et le PID de l'exe en cours d'exécution.

Il me manque le handle de la fenêtre de l'exe.

Avec le handle de la fenêtre, je sais l'activer.

Je fouille sur Internet, mais sans succès pour l'instant.

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

Publié : ven. 22/janv./2016 0:50
par Ar-S
De nouveau tiré de WinAPi
Le handle de la fenêtre sous le curseur :

Code : Tout sélectionner

EnableExplicit

Define EventID

Structure Point64
  StructureUnion
    p.POINT
    q.q
  EndStructureUnion
EndStructure

Procedure Thread(z)
  Protected cursor.POINT64
  Protected hndl
  
  Repeat
    GetCursorPos_(cursor.POINT64)
    
    hndl = WindowFromPoint_( cursor\q )
    
    SetGadgetText(1,"Num du Handle sous la souris : "+Str(hndl))
    
    Delay(100)
  ForEver
  
EndProcedure

If OpenWindow(0,0,0,500,400,"Window",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  TextGadget(1,10,10,WindowWidth(0)-20,20,"",0)
  
  CreateThread(@Thread(),0)
  
  Repeat
    EventID=WaitWindowEvent()
    If EventID = #PB_Event_CloseWindow
      End
    EndIf
  ForEver
EndIf

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

Publié : ven. 22/janv./2016 0:59
par Ar-S
2eme truc.
Je viens de me rappeler un des codes de mon Ar-S Libs.
En le bidouillant un poil il est très simple de rendre une fenêtre externe apparente. j'ai testé avec la fenêtre de FlashFXP et ça marche nikel.

Code : Tout sélectionner

Procedure.s WinCommand(ExternalWindowName$) 
  ;Ar-S Libs v 1.2
  hwnd = FindWindow_(0,ExternalWindowName$)
  If hwnd <> 0 
    SendMessage_(hwnd,#WM_SYSCOMMAND, #SC_RESTORE,0)
  EndIf  
EndProcedure    

WinCommand("FlashFXP")
En combinant tout ça (detecter 1 instance et afficher la fenetre du même nom) devrait donner ça.

Code : Tout sélectionner


Procedure.s OneInstance(TitreDeLaFenetre$)
  WindowTitle.s=TitreDeLaFenetre$
  SetLastError_(#NO_ERROR)
  hMutex.l= CreateMutex_(#Null, #False, @WindowTitle)
  erreur.l = GetLastError_()
  If ( erreur = #ERROR_ALREADY_EXISTS ) Or ( erreur = #ERROR_ACCESS_DENIED )
    ;      SetWindowState(#LDVM,#PB_Window_Minimize)
    hwnd = FindWindow_(0,TitreDeLaFenetre$)
    If hwnd <> 0 
      SendMessage_(hwnd,#WM_SYSCOMMAND, #SC_RESTORE,0)
    EndIf 
    End
  EndIf
EndProcedure



If OpenWindow(0, 0, 0, 220, 100, "montitre", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  OneInstance("montitre")
  
   ButtonGadget  (1, 10, 60, 200, 30, "Fermer")
   
   Repeat
     Event = WaitWindowEvent()
     
     Select Event
     
       Case #PB_Event_Gadget
         Select EventGadget()
           Case 1 
              CloseWindow(0)
              End  
         EndSelect
            
     EndSelect
   Until Event = #PB_Event_CloseWindow
 EndIf
 
 
 

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

Publié : ven. 22/janv./2016 8:53
par Anonyme2
Malgré mes dizaines et dizaine d'essais, dans le taskmanager je n'ai toujours qu'une seule fois le programme.

J'ai modifié des choses en fonction de mes observations.
Je boucle sur initSysTray() dans la callback car l'icône ne réapparait pas après avoir détruit la barre de tache et ensuite la remettre.
Il faut attendre que le système ait terminé de créer la barre avant de réafficher l'icône, c'est ce que fait

Code : Tout sélectionner

While Not(initSysTray())
Wend
pour

Code : Tout sélectionner

SendMessage_(#HWND_BROADCAST, TB_Message, @Windowid_0, 0)
j'ai transmis l'adresse d'une variable (.i) qui aura la valeur Windowi(0) mais je ne l'utilise pas...

voilà le code, il y aurait encore des améliorations à faire.
Shell_NotifyIcon ne correspond pas à ce que je cherche, je vais faire des essais avec Shell_NotifyIconGetRect_() pour voir s'il y a ou non une corrélation avec l'affichage de l'icône avant de le recréer.

Code : Tout sélectionner

EnableExplicit
Define .i

#WinApp=0 : Global MyApp$ = "MyApp" : Global Mutex

Global TB_Message = RegisterWindowMessage_("TaskbarCreated")
Global Erreur
Global Windowid_0


If TB_Message
      Mutex = CreateMutex_(0,1, @MyApp$)
      Erreur = GetLastError_()
      If Erreur = #ERROR_ALREADY_EXISTS Or (Erreur = #ERROR_ACCESS_DENIED)
            ; Code manquant pour activer la fenêtre si on tente de relancer l'application.
            SendMessage_(#HWND_BROADCAST, TB_Message, @Windowid_0, 0)
            If Mutex
                  CloseHandle_(Mutex)
            EndIf
            End
      EndIf
EndIf

Enumeration Images
      #Image_App
EndEnumeration

Global IconApp = CatchImage(#Image_App  , ?Image_App)

Procedure.i initSysTray()
      ;// retourne #true si affichage icône zone notification sinon retourne #false
      ;// A l'initialisation, Resultat vaut #False donc pas besoin ici de lui attribuer la valeur par défaut
      Protected Resultat
      
      If FindWindow_("Progman", #NUL) <> 0
            If IsSysTrayIcon(#WinApp)
                   RemoveSysTrayIcon(#WinApp)
                  AddSysTrayIcon(#WinApp, WindowID(#WinApp), IconApp)
                  SysTrayIconToolTip(#WinApp, MyApp$)
            Else
                  AddSysTrayIcon(#WinApp, WindowID(#WinApp), IconApp)
                  SysTrayIconToolTip(#WinApp, MyApp$)
            EndIf
            Resultat = #True
      EndIf
      ProcedureReturn Resultat
EndProcedure

Procedure TaskbarCallback(hWnd, Msg, wParam, lParam)
  ;// ici PeekI(wParam) vaut le handle de la fenêtre
      If Msg = TB_Message
            While Not(initSysTray())
            Wend
            If IsIconic_(hWnd) = #False
                  ShowWindow_(hWnd,#SW_MINIMIZE)
            EndIf
            ShowWindow_(hWnd,#SW_RESTORE)
            SetForegroundWindow_(hWnd)
      EndIf
      ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

ExamineDesktops()
#W=300 : #H=200
Define X = (DesktopWidth(0) -#W)/2
Define Y = (DesktopHeight(0)-#H)/2
Define Event
SetWindowCallback(@TaskbarCallback()) ; crash explorer
If OpenWindow(0, X, Y, #W, #H, "MyApp & Mutex & ...", #PB_Window_MinimizeGadget|#PB_Window_Minimize)
      Windowid_0 = WindowID(0)
      
      initSysTray()
      SetWindowState(0, #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 10:54
par Anonyme2
Pour éviter de recréer à chaque fois l'icône du systray, j'ai utiliser l'API Shell_NotifyIconGetRect

L'API existe depuis Win 7 mais le code doit fonctionner pour les OS antérieur.

Impossible d'utiliser Import car le fichier lib est trop ancien et la fonction n'est pas reconnue.


Code : Tout sélectionner

EnableExplicit
Define .i

Macro _DWORD
      ;// A 32-bit unsigned integer
      l
EndMacro

Macro _HANDLE
      i
EndMacro

Macro _HWND
      _HANDLE
EndMacro

Macro _UINT
      ;// An unsigned INT
      l
EndMacro

Structure NOTIFYICONIDENTIFIER Align #PB_Structure_AlignC
      ; typedef struct _NOTIFYICONIDENTIFIER {
      ;   DWORD cbSize;
      ;   HWND  hWnd;
      ;   UINT  uID;
      ;   GUID  guidItem;
      ;   } NOTIFYICONIDENTIFIER, *PNOTIFYICONIDENTIFIER;
      cbSize._DWORD
      hWnd._HWND
      uID._UINT
      guidItem.GUID
EndStructure

#WinApp=0 : Global MyApp$ = "MyApp" : Global Mutex

Global TB_Message = RegisterWindowMessage_("TaskbarCreated")
Global Erreur
;// mémorise le handle de la fenêtre
Global Windowid_0



If TB_Message
      Mutex = CreateMutex_(0,1, @MyApp$)
      Erreur = GetLastError_()
      If Erreur = #ERROR_ALREADY_EXISTS Or (Erreur = #ERROR_ACCESS_DENIED)
            ; Code manquant pour activer la fenêtre si on tente de relancer l'application.
            SendMessage_(#HWND_BROADCAST, TB_Message, @Windowid_0, 0)
            If Mutex
                  CloseHandle_(Mutex)
            EndIf
            End
      EndIf
EndIf

Enumeration Images
      #Image_App
EndEnumeration

Global IconApp = CatchImage(#Image_App  , ?Image_App)

;//Prototype utilisé pour exécuter l'API Shell_NotifyIconGetRect_
Prototype.i Shell__NotifyIconGetRect(*pt, *pt1)

Procedure.i initSysTray()
      ;// retourne #true si affichage icône zone notification sinon retourne #false
      ;// A l'initialisation, Resultat vaut #False donc pas besoin ici de lui attribuer la valeur par défaut
      Protected Resultat
      ;// élément permetant d'utiliser l'API Shell_NotifyIconGetRect_()
      Protected Item.NOTIFYICONIDENTIFIER
      ;// coordonnées de l'icône
      Protected Points.RECT
      ;// variable du prototype
      Protected GetRect.Shell__NotifyIconGetRect
      
      
      If FindWindow_("Progman", #NUL) <> 0
            ;// initialisation de la variable Item
            Item\cbSize = SizeOf(NOTIFYICONIDENTIFIER)
            ;// le handle de la fenêtre parent
            Item\hWnd = Windowid_0
            ;// identifiant de notification de l'icône pour l'application.
            Item\uID = #WinApp
            ;// un GUID enregistré qui identifie l'icône, non utilisé ici
            ;Item\guidItem
            
            ;// si Shell__NotifyIconGetRect retourne #S_OK pas besoin de réafficher
            If IsSysTrayIcon(#WinApp) ;= 0
                  If OpenLibrary(0, "Shell32.dll")
                        GetRect.Shell__NotifyIconGetRect = GetFunction(0, "Shell_NotifyIconGetRect")
                        If GetRect
                              If GetRect(@Item, @Points) = #S_OK
                                    Debug Points\left
                                    Debug Points\right
                                    Debug Points\top
                                    Debug Points\bottom
                                    Debug ""
                                    CloseLibrary(0)
                                    ProcedureReturn #True
                              EndIf
                        EndIf
                        CloseLibrary(0)
                  EndIf
            EndIf
            
            ;// ici Shell__NotifyIconGetRect a échoué, 2 cas,:
            ;// on est sur l'initialisation, donc IsSysTrayIcon(#WinApp) retourne 0 et pas besoin de détruire
            ;// sinon IsSysTrayIcon(#WinApp) retourne une autre valeur. il faut réafficher dans les 2 cas
            If IsSysTrayIcon(#WinApp)
                  RemoveSysTrayIcon(#WinApp)
            EndIf
            AddSysTrayIcon(#WinApp, WindowID(#WinApp), IconApp)
            SysTrayIconToolTip(#WinApp, MyApp$)
            Resultat = #True
      EndIf
      ProcedureReturn Resultat
EndProcedure

Procedure TaskbarCallback(hWnd, Msg, wParam, lParam)
      ;// ici PeekI(wParam) vaut le handle de la fenêtre
      If Msg = TB_Message
            While Not(initSysTray())
            Wend
            If IsIconic_(hWnd) = #False
                  ShowWindow_(hWnd,#SW_MINIMIZE)
            EndIf
            ShowWindow_(hWnd,#SW_RESTORE)
            SetForegroundWindow_(hWnd)
      EndIf
      ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

ExamineDesktops()
#W=300 : #H=200
Define X = (DesktopWidth(0) -#W)/2
Define Y = (DesktopHeight(0)-#H)/2
Define Event
SetWindowCallback(@TaskbarCallback()) ; crash explorer
If OpenWindow(0, X, Y, #W, #H, "MyApp & Mutex & ...", #PB_Window_MinimizeGadget|#PB_Window_Minimize)
      Windowid_0 = WindowID(0)
      
      initSysTray()
      SetWindowState(0, #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 11:15
par Anonyme2
Une autre approche serait d'intercepter le message de création de la barre de tache pour réafficher l'icône lorsque c'est terminer.

Je ne connais pas le message s'il existe.

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

Publié : ven. 22/janv./2016 12:22
par nico
C'est celui-ci Denis, Global TB_Message = RegisterWindowMessage_("TaskbarCreated"), il est présent dans le code déjà.

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

Publié : ven. 22/janv./2016 12:30
par Anonyme2
nico a écrit :C'est celui-ci Denis, Global TB_Message = RegisterWindowMessage_("TaskbarCreated"), il est présent dans le code déjà.

Faut peut-être que je change mes lunettes :mrgreen:

Dans PureIconManager, j'utilise une chaine perso pour RegisterWindowMessage.

Ca fait longtemps, alors j'ai un peu de mal à me souvenir.

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

Publié : ven. 22/janv./2016 12:35
par Anonyme2
Après réflexion, il existe peut-être un message du type WM_xx pour le début de création de la taskbar et un autre lorsqu'elle est vraiment créée (après création), ces types de messages existent pour d'autres éléments il me semble.