Page 1 sur 2

Texte OnTop avec fenêtre transparente avec GDI

Publié : sam. 14/févr./2015 16:48
par ChrisR
Bonjour à tous :)
Après quelques petits dev Autoit, je suis a mes débuts sur PB et j'ai besoin, pour l'instant d'exemple pour apprendre :wink:

J'aimerais porter sur PB cette petite application au3 sympa récupérée : Text on top of everything Post#18
J'ai commencé mais je coince maintenant sur les CallFunction mis en commentaire.

Edit: Code supprimé le 15/02/15 à 14H32

Code : Tout sélectionner

Sans intérêt pour la lecture. On oublie !!! 
Voir le code de Nico plus bas
:)

Re: Texte OnTop avec fenêtre transparente avec GDI

Publié : sam. 14/févr./2015 17:24
par Marc56
ChrisR a écrit :Bonjour à tous :)
Après quelques petits dev Autoit, je suis a mes débuts sur PB et j'ai besoin, pour l'instant d'exemple pour apprendre :wink:

J'aimerais porter sur PB cette petite application au3 sympa récupérée : Text on top of everything Post#18
J'ai commencé mais je coince maintenant sur les CallFunction mis en commentaire.
Bienvenue,

Pour apprendre, la meilleur façon est de copier, tester puis modifier les exemples de la doc. Évite de commencer tout de suite par la migration d'un "pavé" 8O

Si ton souhait est de faire un texte flottant au dessus de tout, le plus simple est une fenêtre sans bordures et il existe une fonction native dans PB qui permet de la mettre au dessus de tout:

StickyWindow()
Affiche une fenêtre toujours au premier plan, devant tous les autres programmes, même si elle n'est pas active.

Quant à faire une fenêtre (semi) transparente, voici une façon de procéder (tiré des exemples du forum)
(Nécessite une version enregistrée de PB, car fait appel aux API)

Code : Tout sélectionner

Procedure.i SetWindowTransparency(Window, Transparency=255) 
	Protected *windowID=WindowID(Window), exStyle=GetWindowLongPtr_(*windowID, #GWL_EXSTYLE) 
	If Transparency>=0 And Transparency<=255 
		SetWindowLongPtr_(*windowID, #GWL_EXSTYLE, exStyle | #WS_EX_LAYERED) 
		SetLayeredWindowAttributes_(*windowID, 0, Transparency, #LWA_ALPHA) 
		
		ProcedureReturn #True 
	EndIf 
EndProcedure 


If OpenWindow(0, 0, 0, 300, 300, "Fenêtre Transparente",#PB_Window_SystemMenu | #PB_Window_TitleBar | #PB_Window_ScreenCentered)
	SetWindowTransparency(0, 128)	
EndIf

Repeat 
	Select WaitWindowEvent() 
		Case #PB_Event_CloseWindow 
			Quit = 1 
	EndSelect 
Until Quit = 1
PS. pour lire le soir sur la tablette, la doc est aussi au format PDF (Version 5.30 en Français: 1711 pages) :wink:

Re: Texte OnTop avec fenêtre transparente avec GDI

Publié : sam. 14/févr./2015 19:01
par ChrisR
Marc56 a écrit : Pour apprendre, la meilleur façon est de copier, tester puis modifier les exemples de la doc. Évite de commencer tout de suite par la migration d'un "pavé" 8O
C'est bien comme cela que je souhaite apprendre, et partant d'exemple: doc ou en ligne sur les forums PB et en essayant en modifiant.
La syntaxe va rentrer au fur et a mesure en même temps qu'une base d'apps, exemple (copier coller)
La doc, hum, comme ton clin d'œil l'indique :wink:

Pour le pavé, si tu enlèves les déclarations de variables, il reste ~40 lignes de codes. Bon d'accord avec des fonctions GDI qui ne sont pas les plus simples.

J'ai déjà essayé avec StickyWindow(), il fonctionne sans soucis, il doirt pouvoir être fait également avec WS_POPUP style et WS_EX_TOPMOST!$WS_EX_TOOLWINDOW extended style
Ensuite j'ai essayé avec les trucs trouvés pour avoir la fenêtre transparente (ils sont nombreux) et n'avoir vraiment que le texte affiché mais sans succès.
en continuant a chercher, je suis tombé sur ce bout de code au3 qui fait exactement ce que je veux. Mais 805 Ko pour l'exe 64 bit uniquement pour écrire un texte 8O
je préfère persévérer en PureBasic et si quelqu'un peu m'aider ou est interressé, tant mieux 8)

Re: Texte OnTop avec fenêtre transparente avec GDI

Publié : sam. 14/févr./2015 19:05
par Marc56
Je viens juste d'ajouter à mon post précédent un exemple de fenêtre transparente :wink:

Re: Texte OnTop avec fenêtre transparente avec GDI

Publié : sam. 14/févr./2015 19:24
par ChrisR
Merci pour ton bout de code :)

Par contre si je met la transparence à 0, mon texte est également transperent
SetWindowTransparency(0, 0)
TextGadget(1,5,5,190,15,"blablablabla")
SetGadgetColor(1,#PB_Gadget_FrontColor,RGB($00,$00,$8B))

Ciné ce soir, je continue demain.

Re: Texte OnTop avec fenêtre transparente avec GDI

Publié : sam. 14/févr./2015 21:13
par nico
[Edit, code mise à jour, le 15/02/15 à 01H39]
Permet d'afficher du texte sur plusieurs lignes maintenant, le texte est toujours centré.


Salut,

J'ai regardé ton code autoit mais ça ma pas motivé, je l'ai quand même fait mais d'une autre façon avec principalement l'API UpdateLayeredWindow.
Ce code utilise une procédure du Soldat Inconnu et un autre de c4s du forum english.

Il transforme du texte en une image avec canal alpha puis l'affiche, on peut aussi dessiner du texte sur une image et l'afficher.

Code : Tout sélectionner

UsePNGImageDecoder()

Procedure.l SetLayeredWindow(WindowID) ; Mettre l'attribut WS_EX_LAYERED à la fenêtre
  SetWindowLong_(WindowID, #GWL_EXSTYLE, GetWindowLong_(WindowID, #GWL_EXSTYLE) | #WS_EX_LAYERED) ; Mettre l'attribut WS_EX_LAYERED à la fenêtre
EndProcedure

Procedure.l AlphaImageWindow(WindowID, ImageID) ; Mettre une image PNG comme fond d'une fenêtre
  Protected Image_HDC.i, Image_Bitmap.BITMAP, Image_BitmapInfo.BITMAPINFO, ContextOffset.POINT, Blend.BLENDFUNCTION
  Protected Image_Ancienne.i ,xx, yy, x, y, Rouge.l, Vert.l, Bleu.l, AlphaChannel.l
  
  ; Précalcul
  Protected Dim Echelle.f($FF)
  For x = 0 To $FF
    Echelle(x) = x / $FF
  Next
  
  ; Chargement du HDC
  Image_HDC = CreateCompatibleDC_(#Null)
  Image_Ancienne = SelectObject_(Image_HDC, ImageID)
  
  
  ; Dimension de l'image
  GetObject_(ImageID, SizeOf(BITMAP), @Image_Bitmap)
  Image_BitmapInfo\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER)
  Image_BitmapInfo\bmiHeader\biWidth = Image_Bitmap\bmWidth
  Image_BitmapInfo\bmiHeader\biHeight = Image_Bitmap\bmHeight
  Image_BitmapInfo\bmiHeader\biPlanes = 1
  Image_BitmapInfo\bmiHeader\biBitCount = 32
  
  ; Zone mémoire pour copier l'image
  xx = Image_Bitmap\bmWidth - 1
  yy = Image_Bitmap\bmHeight - 1
  Protected Dim Image.l(xx, yy)
  
  ; Copie de l'image en mémoire
  GetDIBits_(Image_HDC, ImageID, 0, Image_Bitmap\bmHeight, @Image(), @Image_BitmapInfo, #DIB_RGB_COLORS)
  
  ; Modification de l'image en mémoire
  For x = 0 To xx
    For y = 0 To yy
      Couleur = Image(x, y)
      AlphaChannel = Couleur >> 24 & $FF
      If AlphaChannel < $FF
        Rouge = (Couleur & $FF) * Echelle(AlphaChannel)
        Vert = (Couleur >> 8 & $FF) * Echelle(AlphaChannel)
        Bleu = (Couleur >> 16 & $FF) * Echelle(AlphaChannel)
        Image(x, y) = Rouge | Vert << 8 | Bleu << 16 | AlphaChannel << 24
      EndIf
    Next
  Next
  
  ; Transfert de la mémoire dans la l'image de base
  SetDIBits_(Image_HDC, ImageID, 0, Image_Bitmap\bmHeight, @Image(), @Image_BitmapInfo, #DIB_RGB_COLORS)
  
  ; L'image est mise en skin de la fenêtre
  Blend\SourceConstantAlpha = 255 ; niveau de transparence
  Blend\AlphaFormat = 1           ; Support de la couche alpha
  Blend\BlendOp = 0
  Blend\BlendFlags = 0
  UpdateLayeredWindow_(WindowID, 0, 0, @Image_BitmapInfo + 4, Image_HDC, @ContextOffset, 0, @Blend, 2)
  
  ; Fermeture du HDC
  SelectObject_(Image_HDC, Image_Ancienne)
  DeleteDC_(Image_HDC)
  
EndProcedure

Procedure.l GetDimensionText(Text.s, FontID.l, *Width.Long, *Height.Long)
  Protected Image.l, Res.l = 0, CountText.l
  Protected MaxLine.s, Line.s, MaxLen.l, Len.l, a.l
  
  CountText = CountString(Text, Chr(13))
  
  For a= 1 To CountText + 1
    Line = StringField(Text, a, Chr(13))
    Len = Len(Line)
    If MaxLen < Len
      MaxLen = Len
      MaxLine = Line
    EndIf 
  Next a
  
  Image = CreateImage(#PB_Any, 100, 100)
  If Image
    If StartDrawing(ImageOutput(Image))
      DrawingFont(FontID(FontID))
      *Width\l = TextWidth(MaxLine) 
      *Height\l = TextHeight(MaxLine)
      StopDrawing()
    EndIf
    FreeImage(Image)
  EndIf
  
  
  If *Width\l <> 0 And *Height\l <> 0
    *Height\l = *Height\l * (CountText + 1)
    Res = 1
  EndIf
  
  ProcedureReturn Res
EndProcedure


Procedure.l CreateText(Width.l, Height.l, Text.s, TextColor=$000000, TextFontID=#PB_Default)
  Protected Image.l, CountText.l, Line.s, MoveHeight.l = 0
  
  CountText = CountString(Text, Chr(13))
  
  Image = CreateImage(#PB_Any, Width, Height, 32 , #PB_Image_Transparent)
  If Image
    If StartDrawing(ImageOutput(Image))
      DrawingMode(#PB_2DDrawing_AlphaBlend|#PB_2DDrawing_Transparent)
      DrawingFont(FontID(TextFontID))
      For a = 1 To CountText +1
        Line = StringField(Text, a, Chr(13))
        DrawText((Width - TextWidth(Line))/2, MoveHeight, Line, TextColor | $FF000000)
        MoveHeight = MoveHeight + TextHeight(Line)
      Next a       
      StopDrawing()
    EndIf 
  EndIf
  
  ProcedureReturn Image
EndProcedure

Procedure.l CreateTextWithImage(Image.l, Text.s, HeightPosition.l, TextColor=$000000, TextFontID=#PB_Default)
  Protected CountText.l, Line.s, MoveHeight.l = 0
  
  CountText = CountString(Text, Chr(13))
  
  If StartDrawing(ImageOutput(Image))
    DrawingMode(#PB_2DDrawing_AlphaBlend|#PB_2DDrawing_Transparent)
    DrawingFont(FontID(TextFontID))
      For a = 1 To CountText +1
        Line = StringField(Text, a, Chr(13))
        DrawText((ImageWidth(Image) - TextWidth(Line)) / 2, HeightPosition + MoveHeight, Line, TextColor | $FF000000)
        MoveHeight = MoveHeight + TextHeight(Line)
      Next a   
    StopDrawing()
  Else
    Image = 0
  EndIf
  
  ProcedureReturn Image
EndProcedure


LoadFont (0, "Arial", 18)  

Texte.s = "PureBasic" + Chr(13) + "by" + Chr(13) + "Nico"

; Essayer l'une ou l'autre des options
;----------------------------------------------------------------------------------
If GetDimensionText(Texte, 0, @Width, @Height)
  Image = CreateText(Width, Height, Texte, RGB(255,0,0), 0)
EndIf 
;----------------------------------------------------------------------------------
;----------------------------------------------------------------------------------
; Si vous décochez ce qui suit, pensez à cocher les 3 lignes de code précédentes
;----------------------------------------------------------------------------------
; If LoadImage(1, "C:\ votre image avec canal alpha")
;   Image = CreateTextWithImage(1, Texte, 40, RGB(255,0,0), 0)
; EndIf 
;----------------------------------------------------------------------------------


If OpenWindow(0, 100, 100, ImageWidth(Image), ImageHeight(Image), "", #PB_Window_BorderLess | #PB_Window_ScreenCentered)
  
  SetLayeredWindow(WindowID(0))
  
  If Image
    AlphaImageWindow(WindowID(0), ImageID(Image))
  EndIf
  
  StickyWindow(0, 1)
  
  Repeat
    Event = WaitWindowEvent()
    
    Select Event 
      Case  #WM_LBUTTONDOWN
        SendMessage_(WindowID(0), #WM_NCLBUTTONDOWN, #HTCAPTION, 0)
        
      Case #PB_Event_CloseWindow
        Quit = 1
    EndSelect
    
  Until Quit = 1
EndIf


Re: Texte OnTop avec fenêtre transparente avec GDI

Publié : dim. 15/févr./2015 1:40
par nico
Code mis à jour, voir post précédent!

Re: Texte OnTop avec fenêtre transparente avec GDI

Publié : dim. 15/févr./2015 10:23
par ChrisR
Super, exactement ce que je voulais, merci Nico :D
Avec en plus la possibilité de faire la même chose avec une image transparente
et maintenant le texte sur plusieurs lignes, Cool :)

Le code semble en effet beaucoup plus clair que l'exemple au3 :roll:

Je vais prendre un peu de temps pour essayer de mieux comprendre et l'adapter a mon besoin.
ex: avec l'option pour que le prog soit invisible dans la barre des tâches:

Code : Tout sélectionner

;If OpenWindow(0, 100, 100, ImageWidth(Image), ImageHeight(Image), "", #PB_Window_BorderLess | #PB_Window_ScreenCentered)
If OpenWindow(0, 100, 100, ImageWidth(Image), ImageHeight(Image), "", #PB_Window_BorderLess | #PB_Window_Tool | #PB_Window_ScreenCentered)
Ajout d'un délai d'affichage avant de quitter. puis éventuellement texte, délai, position,... en paramètres.

8)

Re: Texte OnTop avec fenêtre transparente avec GDI

Publié : dim. 15/févr./2015 15:57
par ChrisR
Je me suis permis d'ajouter des petits trucs dans le process principal:
- Esc pour quitter
- Position du texte
- Délai d'affichage
- Cacher sur la barre des tâches

Vous pouvez jouer avec la partie paramètres du code pour tester.
;----------------------------------------------------------------------------------
; PARAMETRES
;----------------------------------------------------------------------------------
Texte.s = "PureBasic" + Chr(13) + "by" + Chr(13) + "Nico" ; Chr(13) = Retour chariot (nouvelle ligne)
LoadFont (0, "Arial", 18)
TextColor = RGB(0,0,255)
Xpos = 9999 ; 9999 = Centré | Droite = toute valeur supérieur à la largeur du bureau (ex: 8888)
Ypos = 9999 ; 9999 = Centré | Bas = toute valeur supérieur à la hauteur du bureau (ex: 8888)
Delai = 10 ; en seconde(s) | 0 = illimité
HideOnTaskBar = 1 ; 0 = false | 1 = true
Ils pourraient être ajoutés, plus tard, en paramètres d'entrées ;)


[Code mise à jour le 16/02/15 à 13h22 avec la correction de la procédure GetDimensionText, ci-dessous par Nico].

Code : Tout sélectionner

UsePNGImageDecoder()

Procedure.l SetLayeredWindow(WindowID) ; Mettre l'attribut WS_EX_LAYERED à la fenêtre
  SetWindowLong_(WindowID, #GWL_EXSTYLE, GetWindowLong_(WindowID, #GWL_EXSTYLE) | #WS_EX_LAYERED) ; Mettre l'attribut WS_EX_LAYERED à la fenêtre
EndProcedure

Procedure.l AlphaImageWindow(WindowID, ImageID) ; Mettre une image PNG comme fond d'une fenêtre
  Protected Image_HDC.i, Image_Bitmap.BITMAP, Image_BitmapInfo.BITMAPINFO, ContextOffset.POINT, Blend.BLENDFUNCTION
  Protected Image_Ancienne.i ,xx, yy, x, y, Rouge.l, Vert.l, Bleu.l, AlphaChannel.l
  
  ; Précalcul
  Protected Dim Echelle.f($FF)
  For x = 0 To $FF
    Echelle(x) = x / $FF
  Next
  
  ; Chargement du HDC
  Image_HDC = CreateCompatibleDC_(#Null)
  Image_Ancienne = SelectObject_(Image_HDC, ImageID)
  
  
  ; Dimension de l'image
  GetObject_(ImageID, SizeOf(BITMAP), @Image_Bitmap)
  Image_BitmapInfo\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER)
  Image_BitmapInfo\bmiHeader\biWidth = Image_Bitmap\bmWidth
  Image_BitmapInfo\bmiHeader\biHeight = Image_Bitmap\bmHeight
  Image_BitmapInfo\bmiHeader\biPlanes = 1
  Image_BitmapInfo\bmiHeader\biBitCount = 32
  
  ; Zone mémoire pour copier l'image
  xx = Image_Bitmap\bmWidth - 1
  yy = Image_Bitmap\bmHeight - 1
  Protected Dim Image.l(xx, yy)
  
  ; Copie de l'image en mémoire
  GetDIBits_(Image_HDC, ImageID, 0, Image_Bitmap\bmHeight, @Image(), @Image_BitmapInfo, #DIB_RGB_COLORS)
  
  ; Modification de l'image en mémoire
  For x = 0 To xx
    For y = 0 To yy
      Couleur = Image(x, y)
      AlphaChannel = Couleur >> 24 & $FF
      If AlphaChannel < $FF
        Rouge = (Couleur & $FF) * Echelle(AlphaChannel)
        Vert = (Couleur >> 8 & $FF) * Echelle(AlphaChannel)
        Bleu = (Couleur >> 16 & $FF) * Echelle(AlphaChannel)
        Image(x, y) = Rouge | Vert << 8 | Bleu << 16 | AlphaChannel << 24
      EndIf
    Next
  Next
  
  ; Transfert de la mémoire dans la l'image de base
  SetDIBits_(Image_HDC, ImageID, 0, Image_Bitmap\bmHeight, @Image(), @Image_BitmapInfo, #DIB_RGB_COLORS)
  
  ; L'image est mise en skin de la fenêtre
  Blend\SourceConstantAlpha = 255 ; niveau de transparence
  Blend\AlphaFormat = 1           ; Support de la couche alpha
  Blend\BlendOp = 0
  Blend\BlendFlags = 0
  UpdateLayeredWindow_(WindowID, 0, 0, @Image_BitmapInfo + 4, Image_HDC, @ContextOffset, 0, @Blend, 2)
  
  ; Fermeture du HDC
  SelectObject_(Image_HDC, Image_Ancienne)
  DeleteDC_(Image_HDC)
  
EndProcedure

Procedure.l GetDimensionText(Text.s, FontID.l, *Width.Long, *Height.Long)
  Protected Image.l, Res.l = 0, CountText.l
  Protected MaxLine.s, Line.s, MaxLen.l, Len.l, a.l
  
  CountText = CountString(Text, Chr(13))
  
  For a= 1 To CountText + 1
    Line = StringField(Text, a, Chr(13))
    Len = Len(Line)
    If MaxLen < Len
      MaxLen = Len
      MaxLine = Line
    EndIf 
  Next a
  
  Image = CreateImage(#PB_Any, 100, 100)
  If Image
    If StartDrawing(ImageOutput(Image))
      DrawingFont(FontID(FontID))
      *Width\l = TextWidth(MaxLine) 
      *Height\l = TextHeight(MaxLine)
      StopDrawing()
    EndIf
    FreeImage(Image)
  EndIf
  
  
  If *Width\l <> 0 And *Height\l <> 0
    *Height\l = *Height\l * (CountText + 1)
    Res = 1
  EndIf
  
  ProcedureReturn Res
EndProcedure


Procedure.l CreateText(Width.l, Height.l, Text.s, TextColor=$000000, TextFontID=#PB_Default)
  Protected Image.l, CountText.l, Line.s, MoveHeight.l = 0
  
  CountText = CountString(Text, Chr(13))
  
  Image = CreateImage(#PB_Any, Width, Height, 32 , #PB_Image_Transparent)
  If Image
    If StartDrawing(ImageOutput(Image))
      DrawingMode(#PB_2DDrawing_AlphaBlend|#PB_2DDrawing_Transparent)
      DrawingFont(FontID(TextFontID))
      For a = 1 To CountText +1
        Line = StringField(Text, a, Chr(13))
        DrawText((Width - TextWidth(Line))/2, MoveHeight, Line, TextColor | $FF000000)
        MoveHeight = MoveHeight + TextHeight(Line)
      Next a       
      StopDrawing()
    EndIf 
  EndIf
  
  ProcedureReturn Image
EndProcedure

Procedure.l CreateTextWithImage(Image.l, Text.s, HeightPosition.l, TextColor=$000000, TextFontID=#PB_Default)
  Protected CountText.l, Line.s, MoveHeight.l = 0
  
  CountText = CountString(Text, Chr(13))
  
  If StartDrawing(ImageOutput(Image))
    DrawingMode(#PB_2DDrawing_AlphaBlend|#PB_2DDrawing_Transparent)
    DrawingFont(FontID(TextFontID))
      For a = 1 To CountText +1
        Line = StringField(Text, a, Chr(13))
        DrawText((ImageWidth(Image) - TextWidth(Line)) / 2, HeightPosition + MoveHeight, Line, TextColor | $FF000000)
        MoveHeight = MoveHeight + TextHeight(Line)
      Next a   
    StopDrawing()
  Else
    Image = 0
  EndIf
  
  ProcedureReturn Image
EndProcedure

;----------------------------------------------------------------------------------
; PARAMETRES
;----------------------------------------------------------------------------------

Texte.s = "PureBasic" + Chr(13) + "by" + Chr(13) + "Nico"     ; Chr(13) = Retour chariot Cr (nouvelle ligne) 
LoadFont (0, "Arial", 18)  
TextColor = RGB(0,0,255)
Xpos = 9999        ; 9999 = Centré | Droite = toute valeur supérieur à la largeur du bureau (ex: 8888)
Ypos = 9999         ; 9999 = Centré | Bas = toute valeur supérieur à la hauteur du bureau (ex: 8888)
Delai = 10           ; en seconde(s) | 0 = illimité  
HideOnTaskBar = 1   ; 0 = false | 1 = true

;----------------------------------------------------------------------------------
; Essayer l'une ou l'autre des options
;----------------------------------------------------------------------------------
If GetDimensionText(Texte, 0, @Width, @Height)
  Image = CreateText(Width, Height, Texte, TextColor, 0)
EndIf 
;----------------------------------------------------------------------------------
; Si vous décochez ce qui suit, pensez à cocher les 3 lignes de code précédentes
;----------------------------------------------------------------------------------
; If LoadImage(1, "C:\ votre image avec canal alpha")
;   Image = CreateTextWithImage(1, Texte, 40, TextColor, 0)
; EndIf 
;----------------------------------------------------------------------------------

; Position
ExamineDesktops()
If Xpos = 9999
  Xpos = (DesktopWidth(0) / 2) - (ImageWidth(Image) / 2)
Else
  If Xpos > DesktopWidth(0)- ImageWidth(Image) : Xpos = DesktopWidth(0)- ImageWidth(Image) : EndIf 
EndIf
If Ypos = 9999
  Ypos = (DesktopHeight(0) / 2) - (ImageHeight(Image) / 2)
Else
  If Ypos > DesktopHeight(0)- ImageHeight(Image) : Ypos = DesktopHeight(0)- ImageHeight(Image) : EndIf 
EndIf

; Cacher sur la barre des tâches
If HideOnTaskBar = 0
  Option = #PB_Window_BorderLess  
Else
  Option = PB_Window_BorderLess | #PB_Window_Tool
EndIf      
    

If OpenWindow(0, Xpos, Ypos, ImageWidth(Image), ImageHeight(Image), "", Option)
  
  AddKeyboardShortcut(0, #PB_Shortcut_Escape, 1)   ; Escape pour quitter (Alt+F4) génère un évènement de type #PB_Event_Menu 
  SetLayeredWindow(WindowID(0))
  
  If Image
    AlphaImageWindow(WindowID(0), ImageID(Image))
  EndIf
  
  StickyWindow(0, 1)
  
  NbDelai = 0
  Repeat
    Event = WindowEvent()
    
    Select Event 
      Case  #WM_LBUTTONDOWN
        SendMessage_(WindowID(0), #WM_NCLBUTTONDOWN, #HTCAPTION, 0)
        
      Case #PB_Event_CloseWindow
        Quit = 1
      Case #PB_Event_Menu ; AddKeyboardShortcut Escape
        Quit = 1

    EndSelect
    
    Delay(100)
    NbDelai + 1
    If Delai <> 0 And NbDelai/10 > Delai
      Quit = 1
    EndIf
    
  Until Quit = 1
EndIf

Re: Texte OnTop avec fenêtre transparente avec GDI

Publié : dim. 15/févr./2015 22:11
par nico
Marche très bien, j'ai remarqué que la procédure GetDimensionText était mal codé, je l'ai complété et mis mon code précédent à jour.

Voici la correction:

Code : Tout sélectionner

Procedure.l GetDimensionText(Text.s, FontID.l, *Width.Long, *Height.Long)
  Protected Image.l, Res.l = 0, CountText.l
  Protected MaxLine.s, Line.s, MaxLen.l, Len.l, a.l
  
  CountText = CountString(Text, Chr(13))
  
  For a= 1 To CountText + 1
    Line = StringField(Text, a, Chr(13))
    Len = Len(Line)
    If MaxLen < Len
      MaxLen = Len
      MaxLine = Line
    EndIf 
  Next a
  
  Image = CreateImage(#PB_Any, 100, 100)
  If Image
    If StartDrawing(ImageOutput(Image))
      DrawingFont(FontID(FontID))
      *Width\l = TextWidth(MaxLine) 
      *Height\l = TextHeight(MaxLine)
      StopDrawing()
    EndIf
    FreeImage(Image)
  EndIf
  
  If *Width\l <> 0 And *Height\l <> 0
    *Height\l = *Height\l * (CountText + 1)
    Res = 1
  EndIf
  
  ProcedureReturn Res
EndProcedure

Re: Texte OnTop avec fenêtre transparente avec GDI

Publié : lun. 16/févr./2015 11:38
par nico
Ce code que tu fais, c'est pour un Splashscreen ?

Re: Texte OnTop avec fenêtre transparente avec GDI

Publié : lun. 16/févr./2015 13:13
par ChrisR
Salut Nico,
Merci pour l'ajustement de GetDimensionText. Tout semble Nickel :D
Je suis sur qu'il servira a d'autres.
nico a écrit :Ce code que tu fais, c'est pour un Splashscreen ?
Je veux utiliser cela pour mon projet WinPE: Win8.1SE
Il y a 2 types de constructions possibles:
"OS in RAM" qui utilise le compte administrateur
"PE in RAM" qui utilise le compte System

Dans le mode PE, la barre des tâches est inactive au démarrage.
Il est la même chose dans le vrai Win 8.1 si on utilise Shell Explorer avec le compte System. ex:
taskmgr -> kill explorer -> Psexec -s -i explorer.exe
ou
taskmgr -> kill explorer -> nircmd.exe elevatecmd runassystem explorer.exe

J'ai trouvé dernièrement que le raccourci clavier Win+T permet d'activer la barre des tâches :)
J'ai fait 2 petits prog PB avec keybd_event et SendInput pour le faire automatiquement.
Ils fonctionnent bien avec l'administrateur ou autres utilisateurs mais malheureusement pas avec le compte System :cry:
Win ou T tout seul fonctionne par programme mais pas la combinaison des 2.

En attendant de trouver une solution, je veux afficher un texte au démarrage:
"Use Win+T to activate the taskbar" dans la barre des tâches pendant 5-10 secondes.
J'espère que je suis clair?

D'ailleurs, envoyer Win+T par programme à explorer! Shell_TrayWnd! fonctionnant avec l'utilisateur system
Pourrait être un défi pour les développeurs expérimentés, mais il est un autre sujet ;)


Voici le bout de code avec keybd_event et Win+R (plus facile pour tester)

Code : Tout sélectionner

keys$ = "R"
handle = 0
For k = 1 To 240 ; wait 1mn max to find the taskbar
  handle=FindWindow_("Shell_TrayWnd", NULL) ; Retrieves the handle of Shell_TrayWnd class name window 
  If handle<>0 : Break : EndIf
   Sleep_(250)
Next
If handle=0 ; Does Shell_TrayWnd class name window found?
  End 1 ; Nope, so report 1 for failure to type.
Else
  If IsWindow_(handle)=0 ; Does the target window actually exist?
    End 1 ; Nope, so report 1 for failure to type.
  Else
    ; This block gives the target window the focus before typing.
    thread1=GetWindowThreadProcessId_(GetForegroundWindow_(),0)
    thread2=GetWindowThreadProcessId_(handle,0)
    If thread1<>thread2 : AttachThreadInput_(thread1,thread2,#True) : EndIf
    SetForegroundWindow_(handle) ; Target window now has the focus for typing.
    Sleep_(125) ; 1/8 second pause before typing to prevent fast CPU problems.

    keybd_event_(#VK_LWIN,0,#KEYEVENTF_KEYUP,0) ; Release WINDOWS key before typing.
        
    VkKey=VkKeyScanEx_(Asc(keys$),GetKeyboardLayout_(0)) ; Normal key found.
    keybd_event_(#VK_LWIN,0,0,0) ; Hold WINDOWS key
    keybd_event_(VkKey,0,0,0) : keybd_event_(VkKey,0,#KEYEVENTF_KEYUP,0)  ; Press the normal key.
    keybd_event_(#VK_LWIN,0,#KEYEVENTF_KEYUP,0) ; Release WINDOWS key

    If thread1<>thread2 : AttachThreadInput_(thread1,thread2,#False) : EndIf ; Finished typing to target window!
    End 0
  EndIf
EndIf

Re: Texte OnTop avec fenêtre transparente avec GDI

Publié : lun. 16/févr./2015 15:09
par nico
Compte administrateur et utilisateur, je vois; mais le compte system, c'est quoi?, le mode super administrateur?

Comment tester Win + T avec ton compte system?

Re: Texte OnTop avec fenêtre transparente avec GDI

Publié : lun. 16/févr./2015 15:48
par ChrisR
nico a écrit :Compte administrateur et utilisateur, je vois; mais le compte system, c'est quoi?, le mode super administrateur?

Comment tester Win + T avec ton compte system?
Oui, "en gros" un Super Administrateur avec pas mal d'avantage dans l'environnement PE
Le compte système et le compte d'administrateur (groupe des administrateurs) ont les mêmes privilèges de fichier, mais ils ont des fonctions différentes. Le compte système est utilisé par le système d'exploitation et les services qui s'exécutent sous Windows. Il existe de nombreux services et processus au sein de Windows qui ont besoin de la possibilité de se connecter en interne (par exemple lors d'une installation de Windows). Le compte système a été conçu à cet effet ; C'est un compte interne, il ne s'affiche pas dans le Gestionnaire des utilisateurs, il ne peut pas être ajouté à des groupes et aucun droit utilisateur ne peut lui être assigné. D'autre part, le compte système s'affiche sur un volume NTFS dans le Gestionnaire de fichiers dans la section autorisations du menu sécurité. Par défaut, le compte système est accordé le contrôle total à tous les fichiers sur un volume NTFS. Ici, le compte système a les mêmes privilèges fonctionnels que le compte d'administrateur.
Pour Tester Win+T avec le compte system (ton, pas le mien :lol:), dans Windows 8.1 (je n'ai pas le souci avec Win7) il faut Lancer le Shell (Explorer) avec ce compte
Avec par exemple Windows Sysinternals PsExec ici: https://technet.microsoft.com/en-us/sys ... s/bb897553
Ensuite depuis une session Windows 8.1 lance Taskmgr et arrête le(s) processus explorer
Puis fichier > Nouvelle tâches et tu lances
psexec.exe -s -i explorer.exe (-s Run the remote process in the System account)

F5 pour avoir les icones du bureau et Win+T pour activer la barre des tâches.
Tout tes programmes lancés maintenant sont avec le compte System.

Nota: le gestionnaire de fichier (explorer) ne fonctionne pas bien du tout. Il fonctionne beaucoup mieux dans Win8.1PESE

Win8.1SE est un projet qui permet de construire (légal) son propre LiveCD/USB basé sur Windows8.1 et l'environnement de préinstallation Windows pour dépanner, diagnostiquer, backup, partionnement, récupération fichiers/partition, anti-virus... En démarrant dessus, on a un environnement proche de Win8.1 desktop très allégé et qui fonctionne en Ram.
Un passe temps gratuit et pour le fun qui sert à de nombreux dépanneur PC, administrateur mais aussi des utilisateurs avancés, en cas de domage sur leur PC
mais je ne suis pas là pour parler de mon truc ou en faire de la pub :wink:

Re: Texte OnTop avec fenêtre transparente avec GDI

Publié : lun. 16/févr./2015 16:21
par nico
J'ai une erreur quand j'essaie, c'est pas grave.