Page 1 sur 1

Exemple Screen + Alt-Tab et Alt-Enter

Publié : sam. 03/janv./2026 18:46
par Thyphoon
Bonjour à tous,

J'ai remis au propre un code que j'avais fait il y a quelques années ...
Je le partage avec vous car ça peut servir, surtout pour les debutants.
Si certain on des propositions d'amélioration n'hesitez pas.

Code : Tout sélectionner

EnableExplicit

; -----------------------------------------------------------------------------
; Structure contenant tous les paramètres et états liés à l'affichage
; -----------------------------------------------------------------------------
Structure screenStruct
  isFullScreen.b      ; 0 = fenêtré, 1 = plein écran
  screenWidth.l       ; largeur souhaitée
  screenHeight.l      ; hauteur souhaitée
  screenDepth.l       ; profondeur de couleur (bits)
  screenFlags.l       ; flags PB pour l'écran (sync, etc.)
  screenTitle.s       ; titre
  spriteMouse.i       ; ID du sprite utilisé comme curseur
  mouseX.l            ; position X de la souris
  mouseY.l            ; position Y de la souris
EndStructure

; Instance globale de la structure d'écran
Global Screen.screenStruct

; -----------------------------------------------------------------------------
; Initialisation des valeurs par défaut
; -----------------------------------------------------------------------------
Screen\isFullScreen  = #False
Screen\screenWidth   = 1280
Screen\screenHeight  = 720
Screen\screenDepth   = 32
Screen\screenFlags   = #PB_Screen_SmartSynchronization
Screen\screenTitle   = "Demo Alt-Tab / Alt-Enter"

; -----------------------------------------------------------------------------
; Création des assets (ici un sprite 16x16 pour simuler un curseur rouge)
; -----------------------------------------------------------------------------
Procedure InitAssets()

  ; Création du sprite + démarrage d'un contexte de dessin sur ce sprite
  If CreateSprite(Screen\spriteMouse, 16, 16, #PB_Sprite_AlphaBlending) And StartDrawing(SpriteOutput(Screen\spriteMouse))

    ; Permet de dessiner avec gestion complète de l'alpha (canaux RGBA)
    DrawingMode(#PB_2DDrawing_AllChannels)

    ; Dessine un cercle rouge centré (8,8) de rayon 8 (curseur simple)
    Circle(8, 8, 8, RGBA(255, 0, 0, 255))

    StopDrawing()
  Else
    Debug "Error Draw cursor"
  EndIf

EndProcedure

; -----------------------------------------------------------------------------
; Initialisation de l'écran selon le mode : plein écran ou fenêtré
; Retourne #True si OK
; -----------------------------------------------------------------------------
Procedure.b InitScreen()

  If Screen\isFullScreen

    ; En plein écran, on parcourt les modes disponibles pour trouver un mode
    ; au moins égal à la résolution demandée, avec un refresh à 60 Hz.
    ExamineScreenModes()
    While NextScreenMode()
      If ScreenModeWidth() >= Screen\screenWidth And ScreenModeHeight() >= Screen\screenHeight And ScreenModeRefreshRate() = 60
        Screen\screenWidth  = ScreenModeWidth()
        Screen\screenHeight = ScreenModeHeight()
        Break
      EndIf
    Wend

    ; Ouverture de l'écran plein écran
    If OpenScreen(Screen\screenWidth, Screen\screenHeight, Screen\screenDepth, Screen\screenTitle, #PB_Screen_WaitSynchronization)
      ProcedureReturn #True
    Else
      MessageRequester("Erreur", "Impossible d'ouvrir l'écran")
      End
    EndIf

  Else
    ; En fenêtré : création d'une fenêtre PB puis d'un "WindowedScreen" dedans.
    ; DesktopUnscaledX/Y évite certaines surprises avec le scaling Windows (DPI).
    If OpenWindow(0, 0, 0, DesktopUnscaledX(Screen\screenWidth), DesktopUnscaledY(Screen\screenHeight),
                  Screen\screenTitle, #PB_Window_ScreenCentered) And
       OpenWindowedScreen(WindowID(0), 0, 0, Screen\screenWidth, Screen\screenHeight, #False, 0, 0, #PB_Screen_WaitSynchronization)

      ProcedureReturn #True
    EndIf

  EndIf

EndProcedure

; -----------------------------------------------------------------------------
; Gestion du ALT+TAB (perte de focus / écran inactif)
; Idée : si l'écran n'est plus actif, on ferme et on attend le retour d'activation.
; -----------------------------------------------------------------------------
Procedure CheckScreenFocus()

  ; IsScreenActive() = 0 => l'écran n'est plus actif (ex: Alt-Tab)
  If IsScreenActive() = 0

    ; Libère les sprites
    ;TODO FreeAssets()
    FreeSprite(Screen\spriteMouse)

    ; Crée une micro-fenêtre minimisée/borderless pour "garder un handle" Window
    ; pendant qu'on ferme l'écran. Le but est d'attendre un événement d'activation.
    OpenWindow(0, 1, 1, 1, 1, Screen\screenTitle, #PB_Window_Minimize | #PB_Window_BorderLess)

    ; Ferme l'écran plein écran / windowed screen
    CloseScreen()

    Protected Event.l
    Repeat
      Event = WaitWindowEvent()

      ; Si l'utilisateur ferme la fenêtre, on quitte
      If Event = #PB_Event_CloseWindow
        End
        Break
      EndIf

    ; On attend que la fenêtre reçoive l'événement d'activation
    Until Event = #PB_Event_ActivateWindow

    ; Une fois réactivé, on ferme la petite fenêtre
    CloseWindow(0)

    ; On réinitialise écran + assets
    InitScreen()
    InitAssets()

  EndIf

EndProcedure

; -----------------------------------------------------------------------------
; Bascule fenêtré <-> plein écran via ALT + Entrée
; -----------------------------------------------------------------------------
Procedure ToggleFullScreen()

  ; XOR logique : inverse 0/1
  Screen\isFullScreen ! 1

  ; Si on passe en plein écran, il faut fermer la fenêtre fenêtrée aussi.
  If Screen\isFullScreen = #True
    CloseScreen()
    CloseWindow(0)
  Else
    ; Si on repasse en fenêtré, on ferme juste l'écran (la fenêtre sera recréée)
    CloseScreen()
  EndIf

  ; Ré-ouvre le bon mode + re-crée les assets (curseur)
  InitScreen()
  InitAssets()

EndProcedure

; -----------------------------------------------------------------------------
; Boucle principale
; -----------------------------------------------------------------------------
Procedure Main()

  Protected Event.i

  ; Init des systèmes
  InitSprite()
  InitKeyboard()
  InitMouse()

  ; Init affichage + assets
  InitScreen()
  InitAssets()

  Repeat

    ; En mode fenêtré, on doit vider les événements Window pour éviter le "freeze"
    If Screen\isFullScreen = #False
      Repeat
        Event = WindowEvent()
      Until Event = 0
    EndIf

    ; Efface l'écran
    ClearScreen(RGB(0, 0, 32))

    ; Mise à jour clavier/souris
    ExamineKeyboard()
    ExamineMouse()

    ; Lecture position souris
    Screen\mouseX = MouseX()
    Screen\mouseY = MouseY()

    ; Affiche le sprite du curseur à la position souris
    DisplayTransparentSprite(Screen\spriteMouse, Screen\mouseX, Screen\mouseY)

    ; Gestion ALT + Entrée => toggle plein écran
    If KeyboardPushed(#PB_Key_LeftAlt) Or KeyboardPushed(#PB_Key_RightAlt)
      If KeyboardReleased(#PB_Key_Return)
        ToggleFullScreen()
      EndIf
    EndIf

    ; Affiche le Buffer (double buffering)
    FlipBuffers()

    ; Gestion ALT+TAB / perte d'activation
    CheckScreenFocus()

    ; Petite pause CPU (1ms) pour ne pas monopoliser inutilement
    Delay(1)

  Until KeyboardPushed(#PB_Key_Escape)

  ; Nettoyage
  CloseScreen()

EndProcedure

Main()


Re: Exemple Screen + Alt-Tab et Alt-Enter

Publié : jeu. 08/janv./2026 21:15
par MetalOS
Ca fonctionne bien sous Linux.

Re: Exemple Screen + Alt-Tab et Alt-Enter

Publié : ven. 09/janv./2026 4:08
par Thyphoon
Merci ! Je l'utilise effectivement sous linux /raspberry / Windows ...
helas pas de MacOs pour tester