Page 1 of 1

transparent StringGadget

Posted: Sun Sep 19, 2004 11:13 pm
by newbie
Hi,

I was trying to set a transparent background to my string gadget (gadget containing many lines of text with a scroll on the right).

I successed to do it by using this code, originally done for transparent labels:

Code: Select all

; Original code by Danilo and Num3 (thanks, guys).
; Modified by PB to get a transparent TextGadget.

Global TextGadgetBackground,TextGadgetForeground

TextGadgetBackground=GetStockObject_(#HOLLOW_BRUSH)
TextGadgetForeground=RGB($00,$00,$00)

Procedure WinProc(hwnd,Msg,wParam,lParam)
    If Msg=#WM_CTLCOLORSTATIC
        SetBkMode_(wParam,#TRANSPARENT)
        SetTextColor_(wParam,TextGadgetForeground)
        ProcedureReturn TextGadgetBackground
    Else
        ProcedureReturn #PB_ProcessPureBasicEvents
    EndIf
EndProcedure 
Then you use in the open window :

Code: Select all

SetWindowCallback(@WinProc())
The background is transparent, I can see the window background image and the string gadget text, all seems right.
But when I scroll down, the text is not redrawed properly and does "traces", it is unreadable :

http://perso.wanadoo.fr/jugesoftware/bugPB.JPG

there was not an image backgrounf for this example, I was just using the transparent trick.

Is it possible to make a transparent effect on a string gadget ?

Posted: Sun Sep 19, 2004 11:30 pm
by Dare2
Hiya newbie,

Can't test this and so taking a wild guess here, but perhaps try:

SetBkMode_(wParam,#OPAQUE)

instead of

SetBkMode_(wParam,#TRANSPARENT)

I know that with color (solid brush) backgrounds this seems to do the trick. Not sure how it will go with hollow brush. But can't hurt to try. :)

Posted: Mon Sep 20, 2004 9:52 am
by newbie
That was a good idea, but with OPAQUE I don't see anymore the window background image, the gadget is no more transparent :-/
The good point is that the text glitch is solved by using this parameter, so it gives a clue about what's wrong.

Posted: Tue Sep 21, 2004 1:12 am
by Sparkie
Maybe you can find something helpful in this Win32 only code. I didn't use a standard PB StriingGadget because I wanted to lose the #ES_AUTOHSCROLL that PB seems to add to all StringGadgets. This allowed for better control of the auto word wrap.

I used PB logo for the background since everyone should have it available. You can change the image path to suit your needs. :)

Quickly tested on WinXPhome and Win98fe with PB 3.91. Sorry it's not commented very well. :oops:

Code: Select all

Global hString1, stringBrush, windowBrush, OldCallback
; change LoadImage() path to your image of choice
myImage = LoadImage(0, "C:\Program Files\PureBasic\Examples\Sources\Data\PureBasicLogo.bmp") 
windowBrush = CreatePatternBrush_(myImage) 
stringBrush = GetStockObject_(#HOLLOW_BRUSH)

Procedure myWindowCallback(hWnd, message, wParam, lParam) 
  result = #PB_ProcessPureBasicEvents 
  
  Select message 
    Case #WM_COMMAND
      If lParam = hString1
        InvalidateRect_(lParam, 0, 1) 
      EndIf
      
    Case #WM_CTLCOLOREDIT 
      SetBkMode_(wParam, #TRANSPARENT) 
      SetTextColor_(wParam, RGB(215, 215, 0)) 
      result = windowBrush 
      
  EndSelect 
  
  ProcedureReturn result 
EndProcedure 

Procedure.l myScrollCallback(hWnd, msg, wParam, lParam) 
  result = CallWindowProc_(OldCallback, hWnd, msg, wParam, lParam)
 
  Select msg
    Case #WM_VSCROLL
      InvalidateRect_(hWnd, 0, 1)
  EndSelect
  
  ProcedureReturn result
EndProcedure 

If OpenWindow(0, 0, 0, 381, 138, #PB_Window_ScreenCentered |#PB_Window_MaximizeGadget | #PB_Window_MinimizeGadget | #PB_Window_SizeGadget| #PB_Window_SystemMenu, "Transparent StringGadget") 
  SetWindowCallback(@myWindowCallback()) 
  CreateStatusBar(0, WindowID(0))
  StatusBarText(0, 0, "** NOTE ** There will be some minor flickering from time to time.") 
  SetClassLong_(WindowID(),#GCL_HBRBACKGROUND,windowBrush)
  hString1 = CreateWindowEx_(#WS_EX_CONTROLPARENT | #WS_EX_CLIENTEDGE, "EDIT", "", #WS_TABSTOP | #WS_CHILD | #WS_VISIBLE | #WS_VSCROLL | #ES_LEFT | #ES_AUTOVSCROLL | #ES_MULTILINE | #ES_WANTRETURN, 10, 10, 361, 60, WindowID(0) ,1 ,GetModuleHandle_(0), 0) 
  SetClassLong_(hString1, #GCL_HBRBACKGROUND, stringBrush) 
  OldCallback = SetWindowLong_(hString1, #GWL_WNDPROC, @myScrollCallback())
  style = GetWindowLong_(WindowID(0), #GWL_STYLE)
  newstyle = style | #WS_CLIPCHILDREN
  SetWindowLong_(WindowID(0), #GWL_STYLE, newstyle)
  Restore stringdata
  For i = 0 To 19
    Read sd$
    sAll$ + sd$
  Next
  SendMessage_(hString1, #EM_REPLACESEL, 0, sAll$)
EndIf 

Repeat 
  
  Event = WaitWindowEvent() 
   
  Select Event
    Case #PB_EventSizeWindow
      MoveWindow_(hString1, 0, 0, WindowWidth()+3, WindowHeight()-20, 1)
  EndSelect
  
Until Event = #PB_Event_CloseWindow 

DeleteObject_(windowBrush) 

End
; sample text for Edit control aka StringGadget
DataSection
stringdata:
Data.s "Global hString1, stringBrush, windowBrush, OldCallback"
Data.s "; change LoadImage() path to your image of choice"
Data.s "myImage = LoadImage(0, 'C:\Program Files\PureBasic\Examples\Sources\Data\PureBasicLogo.bmp')"
Data.s "windowBrush = CreatePatternBrush_(myImage)" 
Data.s "stringBrush = GetStockObject_(#HOLLOW_BRUSH)"
Data.s "Procedure myWindowCallback(hWnd, message, wParam, lParam)" 
Data.s "  result = #PB_ProcessPureBasicEvents" 
Data.s "  Debug hString1"
Data.s "  Select message" 
Data.s "    Case #WM_COMMAND"
Data.s "      If lParam = hString1"
Data.s "        InvalidateRect_(lParam, 0, 1)" 
Data.s "      EndIf"
Data.s "    Case #WM_CTLCOLOREDIT" 
Data.s "      SetBkMode_(wParam, #TRANSPARENT)" 
Data.s "      SetTextColor_(wParam, #BLACK)" 
Data.s "      result = windowBrush" 
Data.s "  EndSelect" 
Data.s "  ProcedureReturn result"
Data.s "EndProcedure" 
EndDataSection

Posted: Wed Sep 22, 2004 8:54 am
by newbie
This basically works but oblige me to modify my whole code where I am using the PB gadgets... :?
Wouldn't it be possible keeping the PB gadgets ?

Posted: Wed Sep 22, 2004 2:41 pm
by Sparkie
Yes it's possible to use with a normal PB StringGadget. I'm off to work right now but I'll post some updated code later today. :)

Posted: Wed Sep 22, 2004 2:45 pm
by newbie
I stay tuned :P

Posted: Wed Sep 22, 2004 6:49 pm
by TerryHough
@newbie

See if this code will help you. It is the original code you used just
modified a bit to catch the message for the string gadget in the
callback.

The StringGadget events are a different type than the TextGadgets.

Code: Select all

; From PBForum topic http://jconserv.net/purebasic/viewtopic.php?t=9202
;
; by Num3
;   Many thanks to Danilo for the base code
;   My contribution is getting the background color
;   so the text background always "looks" transparent!
;
; by Terry Hough - addition of StringGadget background coloring - Sep, 22, 2004
;                - addition of StringGadget foreground coloring - Sep, 22, 2004

Global TextGadgetBackground, TextGadgetForeground
Global StringGadgetBackground, StringGadgetForeground

tgcolor = RGB($FF,$FF,$D0)
sgcolor = RGB($FF,$AA,$00)
TextGadgetBackground    = CreateSolidBrush_(tgcolor)
TextGadgetForeground    = RGB($00,$00,$00)
StringGadgetBackground  = CreateSolidBrush_(sgcolor)
StringGadgetForeground  = RGB($00,$00,$00)

Procedure WinProc(hWnd,Msg,wParam,lParam)
  If Msg = #WM_CTLCOLORSTATIC
    Select lParam
      
      Case GadgetID(1)    ; Exclude text gadget 1 from coloring
      
      Default
        SetBkMode_(wParam,#TRANSPARENT)
        SetTextColor_(wParam,TextGadgetForeground)
        ProcedureReturn TextGadgetBackground
        
    EndSelect
  ElseIf Msg = #WM_CTLCOLOREDIT
    Select lParam
      
      Case GadgetID(3)    ; Exclude string gadget 3 from coloring
      
      Case GadgetID(4)    ; Color string gadget foreground too
        SetBkMode_(wParam, #TRANSPARENT)
        SetTextColor_(wParam, RGB($FF,$FF,$FF))
        ProcedureReturn StringGadgetBackground

      Default
        SetBkMode_(wParam, #TRANSPARENT)
        SetTextColor_(wParam, StringGadgetForeground)
        ProcedureReturn StringGadgetBackground
        
    EndSelect
  Else
    ProcedureReturn #PB_ProcessPureBasicEvents
  EndIf
EndProcedure

If OpenWindow(0, 0, 0, 200, 200, #PB_Window_SystemMenu|#PB_Window_ScreenCentered,"Text & String Gadget Color")
  SetWindowCallback(@WinProc())
  If CreateGadgetList(WindowID())
    TextGadget  (0,   5,   5, 190, 15,"This background is colored")
    TextGadget  (1,   5,  25, 190, 15,"This text box is not colored")
    StringGadget(2,   5,  45, 190, 20,"This is a string gadget colored")
    StringGadget(3,   5,  70, 190, 20,"This string gadget is not colored")
    StringGadget(4,   5, 100, 190, 50,"This string gadget's background is"+Chr(13)+Chr(10)+"colored and the text is too, except it is"+Chr(13)+Chr(10)+"now white",#PB_String_Multiline  )
  EndIf
  
  Repeat
  Until WaitWindowEvent()=#PB_EventCloseWindow
  
  DeleteObject_(TextGadgetBackground)
  DeleteObject_(StringGadgetBackground)
EndIf
End
Hope this helps,
Terry

Posted: Wed Sep 22, 2004 9:20 pm
by Sparkie
Ok, here's some quick code for using a normal PB StringGadget. It does not have word wrap enabled because of combatibility issues. That's the main reason my previous code used CreateWindowEx_() to create a pure Win32 API Edit Control. The PB EditorGadget is better suited for word wrapping, but AFAIK, there's no way to set transparent background. :(

Briefly tested on WinXPhome with PB 3.91

Code: Select all

Global hString1, stringBrush, windowBrush, OldCallback 
; change LoadImage() path to your image of choice 
myImage = LoadImage(0, "C:\Program Files\PureBasic\Examples\Sources\Data\PureBasicLogo.bmp") 

; --> create brush for our window background
windowBrush = CreatePatternBrush_(myImage) 

; --> Use #HOLLOW_BRUSH (#NULL) brush for our StringGadget background
stringBrush = GetStockObject_(#HOLLOW_BRUSH) 

Procedure MyWindowCallback(hWnd, message, wParam, lParam) 
  result = #PB_ProcessPureBasicEvents 
  
  Select message 
    
    Case #WM_COMMAND 
      If lParam = hString1
        InvalidateRect_(lParam, 0, 1) 
      EndIf 
      
    Case #WM_CTLCOLOREDIT
      ; --> update StringGadget background 
      SetBkMode_(wParam, #TRANSPARENT) 
      SetTextColor_(wParam, RGB(215, 215, 0)) 
      result = windowBrush 
      
  EndSelect 
  
  ProcedureReturn result 
EndProcedure 

; --> needed to catch #WM_VSCROLL (user scrolled by dragging scrollbar thumb)
Procedure.l myScrollCallback(hWnd, msg, wParam, lParam) 
  result = CallWindowProc_(OldCallback, hWnd, msg, wParam, lParam) 
  
  Select msg 
    Case #WM_VSCROLL 
      InvalidateRect_(hWnd, 0, 1) 
  EndSelect 
  
  ProcedureReturn result 
EndProcedure 

If OpenWindow(0, 0, 0, 381, 138, #PB_Window_ScreenCentered | #PB_Window_MaximizeGadget | #PB_Window_MinimizeGadget | #PB_Window_SizeGadget| #PB_Window_SystemMenu, "Transparent StringGadget") And CreateGadgetList(WindowID(0))
  
  SetWindowCallback(@MyWindowCallback()) 
  CreateStatusBar(0, WindowID(0)) 
  StatusBarText(0, 0, "** NOTE ** There will be some minor flickering from time to time.") 
  
  ; --> Set our window background brush (image)
  SetClassLong_(WindowID(),#GCL_HBRBACKGROUND,windowBrush) 
  
  ; --> No word wrap StringGadget
  hString1 = StringGadget(1, 10, 10, 361, 60, "Hello World!", #PB_String_MultiLine | #WS_VSCROLL | #ES_AUTOVSCROLL)
  
  ; --> Comment out the above line and uncomment the next line to use a word wrap StringGadget.
  ; --> Not reccomended as it will Not work as expected on all Windows OS
  ;hString1 = StringGadget(1, 10, 10, 361, 60, sAll$, #PB_String_MultiLine | #WS_VSCROLL | #ES_AUTOVSCROLL | #ESB_DISABLE_LEFT | #ESB_DISABLE_RIGHT)
  
  ; --> Set our Stringgadget background brush
  SetClassLong_(hString1, #GCL_HBRBACKGROUND, stringBrush) 
  
  ; --> Subclass StringGadget so we can catch #WM_VSCROLL
  OldCallback = SetWindowLong_(hString1, #GWL_WNDPROC, @myScrollCallback()) 
  
  ; --> Reduce filcker
  style = GetWindowLong_(WindowID(0), #GWL_STYLE) 
  newstyle = style | #WS_CLIPCHILDREN 
  SetWindowLong_(WindowID(0), #GWL_STYLE, newstyle)  
  
EndIf 

Repeat 
  
  Event = WaitWindowEvent() 
  
  Select Event 
    Case #PB_EventSizeWindow 
      MoveWindow_(hString1, 0, 0, WindowWidth()+3, WindowHeight()-20, 1) 
  EndSelect 
  
Until Event = #PB_Event_CloseWindow 

DeleteObject_(windowBrush) 

End

Posted: Sat Sep 25, 2004 3:25 pm
by newbie
Thanks you Sparkie !! :D

Using your method, I have found myself a workaround for not being able to set a rreal transparent stringgadget background :
- I set an image background to the window
- I set to each string gadget a picture being the picture background which is a cut of the part that should have appeared if the gadget was transparent... hope that make sense ;)