Page 1 sur 1

Créer des régions en couleur.

Publié : jeu. 08/janv./2026 17:30
par Francois
Bonsoir,

Toujours dans ma quête de connaissance, je souhaite créer une simple fenêtre que j’aimerais peindre en vert, la percer et y écrire un texte en couleur.
Mon programme ressemble à ceci :

Code : Tout sélectionner

WId.i = OpenWindow(#PB_Any,50,100,800,300,"My name is James...",#PB_Window_SystemMenu)
If WId
  HWnd = WindowID(WId)                                  ; Récupère le handle de la fenêtre
  HDc  = GetDC_(HWnd)                                   ; Récupère le handle du DC de la fenêtre (DC : Device context)
  rc.RECT                                               ; Structure définissant une région
  
  GetClientRect_(hwnd, rc)                              ; Récupère les coordonnées de la zone client de la fenêtre
  rgnWindow = CreateRectRgn_(0, 0, rc\right, rc\bottom) ; Crée une région de dimensions égales à la zone client de la fenêtre
  rgnHole   = CreateEllipticRgn_(80, 80, 260, 260)      ; Crée une région en forme de cercle
  CombineRgn_(rgnWindow, rgnWindow, rgnHole, #RGN_DIFF) ; Perce la fenêtre
  SetWindowRgn_(hwnd, rgnWindow, #True)                 ; Déclare que la fenêtre prendra désormais l'aparence d'une fenêtre trouée.
  
  ; Crée une police logique
  HFont  = CreateFont_(120,0,0,0,#FW_BOLD,#False,#False,#False,#DEFAULT_CHARSET,#OUT_DEFAULT_PRECIS,#CLIP_DEFAULT_PRECIS,#PROOF_QUALITY,#DEFAULT_PITCH | #FF_DONTCARE,"Comic Sans MS")
  ; Crée un pinceau logique
  HBrush = CreateSolidBrush_(#Green)
  
  FillRgn_(hDC, rgnWindow, hBrush) ; Peint la fenêtre en vert
  
  ; Sélectionne des objects dans le DC
  Old_Font   = SelectObject_(HDc,HFont)
  Old_Brush  = SelectObject_(HDc,HBrush) ; Ne semble pas nécessaire ?
  
  BeginPath_(rgnWindow)     ; Ouvre le chemin vers la région définie
  SetTextColor_(HDc, #Red ) ; Couleur des caractères
  SetBkColor_(HDc, #Blue )  ; Couleur d'arrière plan des caractères
  SetBkMode_(HDc, #OPAQUE)  ; #OPAQUE ou #TRANSPARENT -> pour l'arrière plan des caractères uniquement, pas pour la fenêtre
  Text.s = "007"
  DrawText_(HDc,Text,Len(Text),rc,#DT_SINGLELINE | #DT_CENTER | #DT_VCENTER)
  ;TextOut_(HDc,0,0,Text,Len(Text))
  EndPath_(rgnWindow)       ; Ferme le chemin (Il n'y a plus de dessin a réaliser
  
  
EndIf

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      MessageRequester("Test","Sorti par la fenêtre !",#PB_MessageRequester_Error)
      End
    Default     
  EndSelect
ForEver
La ligne 11 me pose un énorme problème :

Code : Tout sélectionner

SetWindowRgn_(hwnd, rgnWindow, #True)
Si je la laisse, j'obtiens bien une fenêtre percée, mais sans couleur et sans texte.
Si je la passe en commentaire, j'obtiens une fenêtre bien peinte, avec le texte et avec un rond blanc "opaque", qui ne laisse pas voir l'arrière de la fenêtre.

Pourriez-vous m'expliquer pourquoi lorsque je perce la fenêtre je ne peux plus dessiner dessus ? Pour moi, mais apparemment je me trompe, SetWindowRgn redéfini que la forme de la fenêtre et conserve le handle hwnd et donc le HDc ce qui, a mes yeux, me permettrait de peindre.
J'aurais voulu aller plus loin en trouant également le texte, mais déjà là avec des couleurs pas terribles, j'avoue sécher lamentablement.

Un très grand merci pour vos lumières.

François.

Re: Créer des régions en couleur.

Publié : jeu. 08/janv./2026 19:43
par falsam
Une solution avec un CanvasGadget sur une fenêtre transparente.

Code : Tout sélectionner

EnableExplicit

Define Text.s = "007"
Define Font = LoadFont(#PB_Any, "Arial", 50)
Procedure Exit()
  End
EndProcedure

OpenWindow(0,0,0,800,300,"My name is james.... ")

; Fond transparent
SetWindowLong_(WindowID(0), #GWL_EXSTYLE, #WS_EX_LAYERED)
SetLayeredWindowAttributes_(WindowID(0), RGB(0,0,0), 0, #LWA_COLORKEY)

; Mise en place d'un canvas de meme dimension que le fenetre
CanvasGadget(0, 0, 0, 800, 300)

; Dessin
StartDrawing(CanvasOutput(0))

; Background 
Box(0, 0, 800, 300, #Green)

; Cercle transparent
Circle(180, 150, 100, RGBA(0, 0, 0, 0))

; 007
DrawingFont(FontID(Font))
DrawText(130, 110, Text, #Red)

; Fin du dessin
StopDrawing()

; Evenement
BindEvent(#PB_Event_CloseWindow, @Exit())

; Loop
Repeat : WaitWindowEvent() : ForEver

Re: Créer des régions en couleur.

Publié : ven. 09/janv./2026 10:27
par Francois
Merci pour ta solution qui fonctionne parfaitement, mais qui ne m’explique pas pourquoi SetWindowRgn ne me permet pas ni de peindre la fenêtre ni d’écrire dessus. Je pensais, a priori que mon raisonnement était le bon :
OpenWindow -> crée une fenêtre.
CreateRectRgn -> crée une région de dimensions égales à la zone client de la fenêtre précédemment créée.
CreateEllipticRgn -> crée une région ronde
CombineRgn -> avec #RGN_DIFF pour trouer la fenêtre originale.
SetWindowRgn -> donne à la fenêtre la forme de la fenêtre trouée.
à partir de ce moment-là, je n’arrive plus à peindre ou à écrire sur la fenêtre. Peut-être est-ce le handle sur le DC (HDc) qui n'est plus le bon ? Si c'est le cas que dois-je faire pour le récupérer ?
Je reste perplexe...

François.

Re: Créer des régions en couleur.

Publié : ven. 09/janv./2026 18:08
par falsam
Une autre solution pas à pas avec les API Windows. Commentaires dans le code.

Code : Tout sélectionner

EnableExplicit

#WIDTH  = 800
#HEIGHT = 300
#RADIUS = 90
#CKEY   = $FF00FF

Define hWnd, hDC
Define ps.PAINTSTRUCT
Define rc.RECT
Define cx, cy

Define Text.s = "007"

Define CurrentBrush
Define hFont

; Création d'une fenetre Windows
OpenWindow(0, 0, 0, #WIDTH, #HEIGHT, "My Name is James... ", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)

; Récupération du handle Windows
hWnd = WindowID(0)

; Activer la transparence
SetWindowLongPtr_(hWnd, #GWL_EXSTYLE, GetWindowLongPtr_(hWnd, #GWL_EXSTYLE) | #WS_EX_LAYERED)

; Couleur clé (magenta invisible) utilisation de l'API SetLayeredWindowAttributes_()
;
;BOOL SetLayeredWindowAttributes(
;  [in] HWND     hwnd,      Handle de la fenêtre en couches.
;  [in] COLORREF crKey,     Spécifie la clé de couleur de transparence à utiliser
;  [in] BYTE     bAlpha,    0, la fenêtre est complètement transparente.
;  [in] DWORD    dwFlags    #LWA_COLORKEY, utilisez #CKEY comme couleur de transparence.
;);
SetLayeredWindowAttributes_(hWnd, #CKEY, 0, #LWA_COLORKEY)

;- Début du dessin
; La fonction BeginPaint prépare la fenêtre spécifiée pour la peinture 
; et remplit une Structure PAINTSTRUCT avec des informations sur la peinture.

; Principe : Créer une brush, dessiner et supprimer la brush

hDC = BeginPaint_(hWnd, ps)

;- Fond de la fenetre en vert
With rc
  \left = 0
  \top = 0
  \right = #WIDTH
  \bottom = #HEIGHT
EndWith 

CurrentBrush = CreateSolidBrush_(RGB(0, 255, 0))
SelectObject_(hDC, CurrentBrush)
FillRect_(hDC, rc, CurrentBrush)
DeleteObject_(CurrentBrush)

;- Cercle transparent
cx = 80;(#WIDTH  - #RADIUS * 2) / 2
cy = 80;(#HEIGHT - #RADIUS * 2) / 2

; Petit rappel : Les dessins avec la couleur d'opacité définit dans #CKEY serons transparents
CurrentBrush = CreateSolidBrush_(#CKEY)
SelectObject_(hDC, CurrentBrush)
Ellipse_(hDC, cx, cy, cx + #RADIUS * 2, cy + #RADIUS * 2)
DeleteObject_(CurrentBrush)

;- Texte en rouge au centre du cercle transparent
SetBkMode_(hDC, #TRANSPARENT)
SetTextColor_(hDC, RGB(255, 0, 0))

With rc
  \left   = cx
  \top    = cy
  \right  = cx + #RADIUS * 2
  \bottom = cy + #RADIUS * 2
EndWith 

hFont = CreateFont_(120, 0, 0, 0, #FW_BOLD, #False, #False, #False, #DEFAULT_CHARSET, #OUT_TT_PRECIS, #CLIP_DEFAULT_PRECIS, #ANTIALIASED_QUALITY, #DEFAULT_PITCH | #FF_DONTCARE, "Segoe UI")
SelectObject_(hDC, hFont)
DrawText_(hDC, Text, -1, rc, #DT_CENTER | #DT_VCENTER | #DT_SINGLELINE)
DeleteObject_(hFont)

;- Fin du dessin
EndPaint_(hWnd, ps)

; Loop
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow