Panneau informatif personnalisé

Programmation d'applications complexes
Avatar de l’utilisateur
Jacobus
Messages : 1575
Inscription : mar. 06/avr./2004 10:35
Contact :

Panneau informatif personnalisé

Message par Jacobus »

Bonjour tout le monde,
je vous partage mon panneau perso utilisé pour afficher des infos avec mes applis. Cela peut vous être utile si vous souhaitez également afficher quelque chose, comme par exemple un RDV, une photo, une info importante ou même un simple message d'erreur ou d'attention.
Vous pouvez l'adapter à vos besoins, à vos couleurs, et à vos envies.
Sa particularité; le contour est transparent, sans titre, ni icône, ni boutons. :)

Code : Tout sélectionner

;-=====================================
;   PANNEAU INFORMATIF PERSONNALISE
; By Jacobus le 28/09/2025
; PB 6.21 & 6.30B2 (x86) et (x64) avec Windows 10 & 11 pro
; Possibilités:
; (activer le DPI dans les options de compilation)
; - Positionnement de la fenêtre sur l'écran, au centre ou en bas à droite au-dessus de la zone de notification par exemple
; - Contour du panneau transparent (transparence ajustable)
; - Icônes prélevées dans Shell32.dll, donc pas de fichier externe
; - Largeur et hauteur de la fenêtre ajustables
; - Modifier titre et textes (peut être remplacé par une image)
; - Couleur des textes et du fond modifiables
; - Durée d'affichage du panneau par timer avec fermeture automatique si souhaité
; - Fermeture ou non en mode fondu
; - Option: If the timer is enabled -> the close button is hidden 
;                                   -> And another timer is started To count down before closing the panel
;-=====================================

;-DPI
CompilerIf #PB_Compiler_DPIAware = 1
  
  Global dpix.d = DesktopResolutionX()
  Global dpiy.d = DesktopResolutionY()
  
CompilerElse
  
  Global dpix.d = 1
  Global dpiy.d = 1
  
CompilerEndIf

Enumeration
  #WINMAIN
  #TXTCOUNT
  #WINSECOND
  #CONTAINERMAIN
  #IMGTITLE
  #TXTTITLE
  #TXTINFO
  #BTNCLOSE
EndEnumeration

; Deux possibilités pour Visibility, soit en valeur de 0 à 255, soit en pourcentage de 0 à 100 %
Procedure SetWinTransparency(hWnd, Visibility)
  SetWindowLongPtr_(hWnd, #GWL_EXSTYLE, GetWindowLongPtr_(hWnd, #GWL_EXSTYLE) | #WS_EX_LAYERED) 
  
  ; 1/ 0 .. 100 % 
  ; SetLayeredWindowAttributes_(hWnd, 0, (Visibility * 255) / 100, #LWA_ALPHA) 
  
  ; 2/ 1 .. 255
  SetLayeredWindowAttributes_(hWnd, 0, Visibility , #LWA_ALPHA) 
EndProcedure 

Global Font0 = LoadFont(0, "Bahnschrift Light SemiCondensed", 10, #PB_Font_Bold|#PB_Font_HighQuality)
Global Font1 = LoadFont(1, "Courier New", 10, #PB_Font_Bold|#PB_Font_HighQuality)

Procedure Panneau_Info(PosX.i, PosY.i, WinWidth.i, WinHeight.i, ContBackColor.i, TitleBackColor.i, TitleColor.i, TextBackColor.i, TextFrontColor.i, Title$, Textinfo$, FlagPos.i, Time = 0, Fade = 0)
  ;{ Explications:
; PosX           = Position en x de la fenêtre
; PosY           = Position en y de la fenêtre
; WinWidth       = Largeur de la fenêtre
; WinHeight      = Hauteur de la fenêtre
; ContBackColor  = Couleur de fond du ContainerGadget
; TitleBackColor = Couleur de fond du titre
; TitleColor     = Couleur du titre dans le container info
; TextBackColor  = Couleur de font du textgadget info
; TextFrontColor = Couleur du texte du texgadgetinfo
; Title$         = Titre du panneau d'info
; Textinfo$      = Texte d'info qui sera affiché
; FlagPos        = #PB_Window_BorderLess|#PB_Window_WindowCentered (par défaut)
;                = #PB_Window_BorderLess (pour afficher le panneau ailleurs qu'au centre de l'écran en adaptant PosX et PosY)
; Time           = Indiquer une valeur en ms (exmple 3000 pour 3 secondes) si vous souhaitez une fermeture automatique sinon laisser à 0
; Fade           = Mettre à 1 pour une fermeture en mode fondu, sinon laisser vide.
;}
  
; Création de la fenêtre qui servira de bordure avec effet de transparence
  If OpenWindow(#WINMAIN, PosX, PosY, WinWidth*dpix, WinHeight*dpiy, "", FlagPos) 
    SetWindowColor(#WINMAIN, RGB(237, 242, 244))

    SetWinTransparency(WindowID(#WINMAIN), 40) ; transparence de la bordure (1 à 255)
   ; SetWinTransparency(WindowID(#WINMAIN), 20) ; transparence de la bordure  (0 -> 100 %)

;     ; a countdown to closing is displayed in the transparent border at the bottom if the timer is activated
;     TextGadget(#TXTCOUNT, 20, WindowHeight(#WINMAIN, #PB_Window_FrameCoordinate)-25, WindowWidth(#WINMAIN, #PB_Window_FrameCoordinate)-40, 20, "", #PB_Text_Center)
;     SetGadgetFont(#TXTCOUNT,Font0)
;     SetGadgetColor(#TXTCOUNT, #PB_Gadget_BackColor, RGB(237, 242, 244))
;     SetGadgetColor(#TXTCOUNT, #PB_Gadget_FrontColor, TitleColor)
;     HideGadget(#TXTCOUNT, #True)
    
    ;Création de la fenêtre secondaire qui recevra les gadgets que l'on veut
    If OpenWindow(#WINSECOND, 0, 0, WindowWidth(#WINMAIN, #PB_Window_FrameCoordinate)-60, WindowHeight(#WINMAIN, #PB_Window_FrameCoordinate)-60, "Info", #PB_Window_BorderLess|#PB_Window_WindowCentered, WindowID(#WINMAIN)) ; doit toujours être au centre de la fenêtre principale
      ;{
      ContainerGadget(#CONTAINERMAIN, 0, 0, WindowWidth(#WINMAIN, #PB_Window_FrameCoordinate)-60, WindowHeight(#WINMAIN, #PB_Window_FrameCoordinate)-60)
      SetGadgetColor(#CONTAINERMAIN, #PB_Gadget_BackColor, RGB(81, 95, 99))
      
      ImageGadget(#IMGTITLE, 20, 10, 32, 32, ExtractIcon_(GetModuleHandle_(#Null), "Shell32.dll",221));<-- utilisation de l'icône n° 221 trouvée dans Shell32.dll (Windows11)
      
      TextGadget(#TXTTITLE, 60, 20, WindowWidth(#WINMAIN, #PB_Window_FrameCoordinate)-140, 20, Title$) 
      SetGadgetFont(#TXTTITLE,Font0) 
      SetGadgetColor(#TXTTITLE, #PB_Gadget_BackColor, RGB(81, 95, 99))
      SetGadgetColor(#TXTTITLE, #PB_Gadget_FrontColor, TitleColor)
      
      TextGadget(#TXTINFO, 20, 50, WindowWidth(#WINMAIN, #PB_Window_FrameCoordinate)-100, WindowHeight(#WINMAIN, #PB_Window_FrameCoordinate)-150, Textinfo$)
      SetGadgetFont(#TXTINFO,Font1)
      SetGadgetColor(#TXTINFO, #PB_Gadget_BackColor, TextBackColor)
      SetGadgetColor(#TXTINFO, #PB_Gadget_FrontColor, TextFrontColor)
      
      ;===============================================
      ;-Bouton au choix : Texte ou image ou image+texte
      
      ;ButtonGadget(#BTNCLOSE, WindowWidth(#WINMAIN, #PB_Window_FrameCoordinate)-180, WindowHeight(#WINMAIN, #PB_Window_FrameCoordinate)-95, 100, 25, "Fermer")                                                       ; bouton texte   
      
      ;ButtonImageGadget(#BTNCLOSE, WindowWidth(#WINMAIN, #PB_Window_FrameCoordinate)-100, WindowHeight(#WINMAIN, #PB_Window_FrameCoordinate)-95, 32, 32, ExtractIcon_(GetModuleHandle_(#Null), "Shell32.dll", 215))  ; bouton image   
      
      ButtonGadget(#BTNCLOSE,WindowWidth(#WINMAIN, #PB_Window_FrameCoordinate)-180, WindowHeight(#WINMAIN, #PB_Window_FrameCoordinate)-95, 100, 27,Space(2)+"Fermer")                                                 ; bouton image + texte (les 3 lignes)     
      SetWindowLongPtr_(GadgetID(#BTNCLOSE), #GWL_STYLE, GetWindowLongPtr_(GadgetID(#BTNCLOSE), #GWL_STYLE) |#BS_LEFT)
      SendMessage_(GadgetID(#BTNCLOSE), #BM_SETIMAGE, #IMAGE_ICON, ExtractIcon_(GetModuleHandle_(#Null), "Shell32.dll", 215)) ;<-- utilisation de l'icône n° 215 trouvée dans Shell32.dll (Windows11)
      
      GadgetToolTip(#BTNCLOSE,"Fermer le panneau d'information")

   ; a countdown to closing is displayed in the transparent border at the bottom if the timer is activated
      TextGadget(#TXTCOUNT, 20, WindowHeight(#WINMAIN, #PB_Window_FrameCoordinate)-85, WindowWidth(#WINMAIN, #PB_Window_FrameCoordinate)-100, 20, "", #PB_Text_Right)
      SetGadgetFont(#TXTCOUNT,Font0)
      SetGadgetColor(#TXTCOUNT, #PB_Gadget_BackColor, TextBackColor)
      SetGadgetColor(#TXTCOUNT, #PB_Gadget_FrontColor, TitleColor)
      HideGadget(#TXTCOUNT, #True)
  
      CloseGadgetList()
      
      If Time > 0 ; si on veut que le panneau s'efface tout seul on indique le temps dans les arguments de la procédure
        AddWindowTimer(#WINMAIN, 120, Time)
        HideGadget(#BTNCLOSE, #True) ; on cache le bouton qui n'est plus nécessaire
        ; Timer for the countdown
        TTime = Time/1000
        SetGadgetText(#TXTCOUNT, "Ce message s'autodétruira dans "+Str(TTime)+" secondes")
        HideGadget(#TXTCOUNT, #False); on affiche le compte à rebours du timer 
        AddWindowTimer(#WINMAIN, 121, 1000)
      EndIf
      
      Repeat 
        Event = WaitWindowEvent() 
        Select Event 
         ; si un timer a été indiqué   
          Case #PB_Event_Timer ;{
            Select EventTimer()
              Case 120
                quit = 1
                Event = #PB_Event_CloseWindow
                If Fade = 1
                  AnimateWindow_(WindowID(#WINSECOND),500,#AW_BLEND|#AW_HIDE)
                EndIf 
             Case 121               
                TTime = TTime - 1
                SetGadgetText(#TXTCOUNT, "Ce message s'autodétruira dans "+Str(TTime)+" secondes")
            EndSelect
            ;}
          Case #PB_Event_Gadget ;{         
            Select EventGadget()
              Case #BTNCLOSE
                quit = 1
                Event = #PB_Event_CloseWindow
                If Fade = 1
                  AnimateWindow_(WindowID(#WINSECOND),500,#AW_BLEND|#AW_HIDE) ; pour une fermeture en douceur en mode fondu
                EndIf 
                End 
            EndSelect
            ;}
        EndSelect       
      Until Event = #PB_Event_CloseWindow 
      ;}
    EndIf 
      
    Repeat 
      Event = WaitWindowEvent()      
    Until quit = 1
    If Fade = 1
      AnimateWindow_(WindowID(#WINMAIN),500,#AW_BLEND|#AW_HIDE) ; pour une fermeture en douceur en mode fondu
    EndIf 
    End 
  EndIf
EndProcedure

If ExamineDesktops()<>0
Global DW = DesktopWidth(0)
Global DH = DesktopHeight(0)

;-Ma résolution d'écran, vérifiez la vôtre
;{
Debug "DesktopWidth(0) = " +Str(DW) + "    DesktopScaledX(DW) = " +DesktopScaledX(DW)
Debug "DesktopHeight(0) = "+Str(DH) + "    DesktopScaledY(DH) = " +DesktopScaledY(DH)
Debug "========================="
Debug "Divisé par le dpi = " +Str(DW/dpix) +" x "+Str(DH/dpiy)  ; 2560 x 1440
Debug "========================="
Debug "posx = "+ Str((DW/dpix)-(300*dpix)) ; 300 = PosX
Debug "posy = "+ Str((DH/dpiy)-(200*dpiy)) ; 200 = PosY (pour une fenêtre de 150 ajout de 50 pour hauteur de la barre des tâches)

;Mes Résultats:
; DesktopWidth(0)  = 3840    DesktopScaledX(DW) = 5760
; DesktopHeight(0) = 2160    DesktopScaledY(DH) = 3240
; =========================
; Divisé par le dpi = 2560 x 1440
; =========================
; posx = 2110
; posy = 1140
;}

EndIf 

;-=====================================
;-EXEMPLES D'UTILISATION

Title$ = "TEST D'AFFICHAGE POUR CE PANNEAU D'INFO..."
Textinfo$ = "Le niveau de transparence doit être compris entre 1 (transparence totale) et 255 (opaque) pour le contour de la première fenêtre. Niveau à 50 pour cet exemple."

;Décommenter le panneau que vous voulez voir

;Exemple 1 / pour affichage le panneau au centre de l'écran (on ne s'occupe donc pas du DPI pour POsX et PosY) et clic sur le bouton pour fermer
;Panneau_Info(0, 0, 800, 600, RGB(45, 65, 113), RGB(45, 65, 113), RGB(226, 236, 239), RGB(45, 65, 113), RGB(226, 236, 239), Title$, Textinfo$, #PB_Window_BorderLess|#PB_Window_ScreenCentered, 0, 1) ; grosse pancarte...

;Exemple 2 / pour affichage en bas à droite (DPI de POsX et PosY à prendre en considération pour les grands écrans) et clic sur le bouton pour fermer
;Panneau_Info((DW/dpix)-(300*dpix), (DH/dpiy)-(200*dpiy), 300, 150, RGB(45, 65, 113), RGB(45, 65, 113), RGB(226, 236, 239), RGB(45, 65, 113), RGB(226, 236, 239), Title$, Textinfo$, #PB_Window_BorderLess)

;Exemple 3 / pour affichage en bas à droite pendant une durée déterminée
;avec timer, le panneau se ferme au bout de 5 secondes en mode fondu
;Panneau_Info((DW/dpix)-(500*dpix), (DH/dpiy)-(350*dpiy), 500, 300, RGB(45, 65, 113), RGB(45, 65, 113), RGB(226, 236, 239), RGB(45, 65, 113), RGB(226, 236, 239), Title$, Textinfo$, #PB_Window_BorderLess, 5000, 1)

;Example 4 /pour affichage le panneau au centre de l'écran avec un timer de 7 secondes et un compte à rebours
Panneau_Info(0, 0, 300, 200, RGB(81, 95, 99), RGB(81, 95, 99), RGB(140, 215, 34), RGB(81, 95, 99), RGB(226, 236, 239), Title$, Textinfo$, #PB_Window_BorderLess|#PB_Window_ScreenCentered, 7000, 1)

Dernière modification par Jacobus le sam. 04/oct./2025 9:31, modifié 12 fois.
Quand tous les glands seront tombés, les feuilles dispersées, la vigueur retombée... Dans la morne solitude, ancré au coeur de ses racines, c'est de sa force maturité qu'il renaîtra en pleine magnificence...Jacobus.
Avatar de l’utilisateur
SPH
Messages : 4961
Inscription : mer. 09/nov./2005 9:53

Re: Panneau informatif personnalisé

Message par SPH »

Merci :wink:

!i!i!i!i!i!i!i!i!i!
!i!i!i!i!i!i!
!i!i!i!
//// Informations ////
Intel Core i7 4770 64 bits - GTX 650 Ti
Version de PB : 6.12LTS- 64 bits
Avatar de l’utilisateur
Jacobus
Messages : 1575
Inscription : mar. 06/avr./2004 10:35
Contact :

Re: Panneau informatif personnalisé

Message par Jacobus »

J'ai ajouté une petite option : Si on active le timer le bouton de fermeture de la fenêtre est automatiquement caché car plus nécessaire.
Cet exemple d'utilisation est pratique pour des infos, mais vous pouvez reprendre ce type de présentation pour afficher un diaporama de photos dans ce qui pourra ressembler à un cadre photo en verre par exemple... :wink:
Quand tous les glands seront tombés, les feuilles dispersées, la vigueur retombée... Dans la morne solitude, ancré au coeur de ses racines, c'est de sa force maturité qu'il renaîtra en pleine magnificence...Jacobus.
Avatar de l’utilisateur
PhM
Messages : 130
Inscription : dim. 08/déc./2019 10:50

Re: Panneau informatif personnalisé

Message par PhM »

Merci, c'est original et peut servir.

Et, comme on en apprends tous les jours, je ne connaissais pas l'effet de cet "encadrement" : ;{ / ;} qui peut également être très utile.
Avatar de l’utilisateur
Jacobus
Messages : 1575
Inscription : mar. 06/avr./2004 10:35
Contact :

Re: Panneau informatif personnalisé

Message par Jacobus »

Merci à vous, si ce petit effet peut vous servir, j'en suis satisfait. :)

PhM, pour les phases de la lune par exemple... 8)
Image
Quand tous les glands seront tombés, les feuilles dispersées, la vigueur retombée... Dans la morne solitude, ancré au coeur de ses racines, c'est de sa force maturité qu'il renaîtra en pleine magnificence...Jacobus.
Avatar de l’utilisateur
Jacobus
Messages : 1575
Inscription : mar. 06/avr./2004 10:35
Contact :

Re: Panneau informatif personnalisé

Message par Jacobus »

Pour le fun, :)
Ajout d'un second timer afin d'afficher un compte à rebours avant fermeture du panneau dans le cas ou l'utilisateur préfère une fermeture automatique plutôt qu'un bouton, mais aussi savoir durant combien de temps le panneau sera affiché.
Code mis à jour dans le premier post.

Cela peut donner ça :
Image
Quand tous les glands seront tombés, les feuilles dispersées, la vigueur retombée... Dans la morne solitude, ancré au coeur de ses racines, c'est de sa force maturité qu'il renaîtra en pleine magnificence...Jacobus.
Avatar de l’utilisateur
SPH
Messages : 4961
Inscription : mer. 09/nov./2005 9:53

Re: Panneau informatif personnalisé

Message par SPH »

Il semblerait que je n'ai pas compris ce que tu as codé !
Tu veux dire que ton code remplace un MessageRequester ?

En tout cas, merci de t'investir pour nous apprendre differentes techniques basiques... :wink:

!i!i!i!i!i!i!i!i!i!
!i!i!i!i!i!i!
!i!i!i!
//// Informations ////
Intel Core i7 4770 64 bits - GTX 650 Ti
Version de PB : 6.12LTS- 64 bits
Avatar de l’utilisateur
Jacobus
Messages : 1575
Inscription : mar. 06/avr./2004 10:35
Contact :

Re: Panneau informatif personnalisé

Message par Jacobus »

SPH a écrit : lun. 29/sept./2025 20:14 Il semblerait que je n'ai pas compris ce que tu as codé !
Tu veux dire que ton code remplace un MessageRequester ?
En tout cas, merci de t'investir pour nous apprendre differentes techniques basiques... :wink:
Non, le MessageRequester() reste ce qu'il est, une fenêtre de dialogue rapide. Il est parfait pour ce qu'il doit faire. Cependant rien n'empêche d'en faire un perso, en utilisant le panneau que j'ai fait si tu veux.
J'avais besoin d'un affichage indépendant pour des informations dans une petite fenêtre au-dessus de la zone de notification, en bas à droite de l'écran, et j'ai bidouillé un code pour avoir autre chose qu'une banale fenêtre. Toujours en cherchant à faire le plus simple possible avec ce qu'offre PB et quelques API quand c'est nécessaire.
Ce panneau est fait avant tout pour afficher des notifications comme le font d'autres applications (courrier, antivirus, RDV,...) mais libre à chacun de faire ce qu'il veut avec. Ce code bénéficie de quelques astuces simples et, comme tu le dis, de trucs basiques qui peuvent dépanner :wink:

Code mis à jour:
(j'avais oublié la constante #TXTCOUNT dans l'Enumeration, ce qui générait une erreur, je l'ai rajouté)
Quand tous les glands seront tombés, les feuilles dispersées, la vigueur retombée... Dans la morne solitude, ancré au coeur de ses racines, c'est de sa force maturité qu'il renaîtra en pleine magnificence...Jacobus.
Avatar de l’utilisateur
Jacobus
Messages : 1575
Inscription : mar. 06/avr./2004 10:35
Contact :

Re: Panneau informatif personnalisé

Message par Jacobus »

Mise à jour de la procédure de transparence par Axolotl ici:
https://www.purebasic.fr/english/viewtopic.php?t=87629
Modification apportée dans le code initial :)
Quand tous les glands seront tombés, les feuilles dispersées, la vigueur retombée... Dans la morne solitude, ancré au coeur de ses racines, c'est de sa force maturité qu'il renaîtra en pleine magnificence...Jacobus.
Répondre