Transparent background for canvas ?

Just starting out? Need help? Post your questions and find answers here.
Joubarbe
Enthusiast
Enthusiast
Posts: 703
Joined: Wed Sep 18, 2013 11:54 am
Location: France

Transparent background for canvas ?

Post by Joubarbe »

Hi,

I'd like to have three-states buttons (on, hot and off), so I use canvas to make them, with custom images. My problem is that canvas has a white background by default, and I'm unable to make it 100% transparent. That way, I could have alpha gradients on my buttons and disregard the background color of my window, which can use alpha channel too.

What I'm currently doing is something like this :

Code: Select all

; ...
CanvasGadget(0, 0, 0, 50, 50)
SetGadgetAttribute(0, #PB_Canvas_Image, ImageID(#CanvasOff)) ; I use a Redraw() procedure to make it persistent when the user moves the window out of the screen
ImageGadget(1, 0, 0, 640, 480, ImageID(#BackgroundImage))

BindGadgetEvent(0, @CanvasMouseEnter(), #PB_EventType_MouseEnter)
BindGadgetEvent(0, @CanvasMouseLeave(), #PB_EventType_MouseLeave)
BindGadgetEvent(0, @CanvasMouseClick(), #PB_EventType_LeftClick) 
; and I use SetGadgetAttribute() in each procedure to change the image of the canvas
... and in that case, if the image of my button uses the alpha channel, then the white background color of the canvas will appear and mess things up.
davido
Addict
Addict
Posts: 1890
Joined: Fri Nov 09, 2012 11:04 pm
Location: Uttoxeter, UK

Re: Transparent background for canvas ?

Post by davido »

You normally change the background colour of a CanvasGadget by drawing a Box with the required colour.

It should be possible to use the alpha channel to make it transparent.
DE AA EB
Joubarbe
Enthusiast
Enthusiast
Posts: 703
Joined: Wed Sep 18, 2013 11:54 am
Location: France

Re: Transparent background for canvas ?

Post by Joubarbe »

Well I've tried that of course, but drawing a box does not replace the background color. It just adds a box over the background.
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Transparent background for canvas ?

Post by IdeasVacuum »

Not sure why you need the canvas to be transparent, if it's 'back' is an image anyway? Unfortunately, a CanvasGadget() can't be made transparent (perhaps it can on Windows via the API).
That way, I could have alpha gradients on my buttons and disregard the background color of my window, which can use alpha channel too.
If that were to happen, you would see right through to the desktop - surely you don't want to do that?
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
Joubarbe
Enthusiast
Enthusiast
Posts: 703
Joined: Wed Sep 18, 2013 11:54 am
Location: France

Re: Transparent background for canvas ?

Post by Joubarbe »

IdeasVacuum wrote:Not sure why you need the canvas to be transparent, if it's 'back' is an image anyway? Unfortunately, a CanvasGadget() can't be made transparent (perhaps it can on Windows via the API).
I use photoshop elements such as glows and shadows and if I want to use this button on a window whose background is a gradient (even a subtle one), I need to have a transparent support, otherwise a part of the button won't have seamless borders.
If that were to happen, you would see right through to the desktop - surely you don't want to do that?
Sorry, I meant "... which can use gradients too".
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Re: Transparent background for canvas ?

Post by netmaestro »

Here's a technique that lets you draw anything alphablended to a transparent canvasgadget. A lot of the code is boilerplate, so it really isn't too much work to customize it for a specific purpose. It only works on windows, so if you aren't on windows I just did a lot of work for nothing :lol:

Code: Select all

Prototype AlphaBlend(hdcDest,DestX,DestY,DestW,DestH,hdcSrc,SrcX,SrcY,SrcW,SrcH,BLENDFUNCTION)

msimg32 = OpenLibrary(#PB_Any, "msimg32.dll")
Global AlphaBlend_.AlphaBlend = GetFunction(msimg32, "AlphaBlend")

Global hBkgndBrush
Global MyCanvasOutput = CreateImage(#PB_Any, 120,40,32,#PB_Image_Transparent)

Procedure PreMultiply(image)
  StartDrawing(ImageOutput(image))
    DrawingMode(#PB_2DDrawing_AllChannels)
    For j=0 To ImageHeight(image)-1
      For i=0 To ImageWidth(image)-1
        color = Point(i,j)
        Plot(i,j, RGBA(Red(color)   & $FF * Alpha(color) & $FF / $FF,
                       Green(color) & $FF * Alpha(color) & $FF / $FF,
                       Blue(color)  & $FF * Alpha(color) & $FF / $FF,
                       Alpha(color)))
      Next
    Next
  StopDrawing()
EndProcedure

Procedure canvasproc(hwnd, msg, wparam, lparam)
  
  oldproc = GetProp_(hwnd, "oldproc")
  
  Select msg
    Case #WM_NCDESTROY
      RemoveProp_(hwnd, "oldproc")
      
    Case #WM_ERASEBKGND
      
      hdc = wparam
      GrabImage(0,1,GadgetX(0),GadgetY(0),GadgetWidth(0),GadgetHeight(0))
      hBrush = CreatePatternBrush_(ImageID(1))
      hPen = GetStockObject_(#NULL_PEN)
      SelectObject_(hdc, hBrush )
      SelectObject_(hdc, hPen)
      Rectangle_(hdc,0,0,121,41)
      DeleteObject_(hBrush)
      ProcedureReturn #True
      
    Case #WM_PAINT
      BeginPaint_(hwnd, ps.PAINTSTRUCT)
      hdcDest = ps\hdc
      hdcSrc = StartDrawing(ImageOutput(MyCanvasOutput))
      result=AlphaBlend_(hdcDest,0,0,ImageWidth(MyCanvasOutput),ImageHeight(MyCanvasOutput),hdcSrc,0,0,ImageWidth(MyCanvasOutput),ImageHeight(MyCanvasOutput),$1FF0000)
      StopDrawing()
      EndPaint_(hwnd, hdcDest)
      ProcedureReturn #False
      
  EndSelect
  
  ProcedureReturn  CallWindowProc_(oldproc, hwnd, msg, wparam, lparam)
EndProcedure

OpenWindow(0,0,0,320,240,"",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
CreateImage(0, 320,240)
StartDrawing(ImageOutput(0))
  DrawingMode(#PB_2DDrawing_Gradient)
  GradientColor(0.0, #Blue)
  GradientColor(1.0, #White)
  LinearGradient(0,0,0,240)
  Box(0,0,320,240)
StopDrawing()
hBkgndBrush = CreatePatternBrush_(ImageID(0))
SetClassLong_(WindowID(0), #GCL_HBRBACKGROUND, hBkgndBrush)
InvalidateRect_(WindowID(0),0,1)

CanvasGadget(0,100,100,120,40)
SetProp_(GadgetID(0), "oldproc", SetWindowLongPtr_(GadgetID(0), #GWL_WNDPROC, @canvasproc()))

StartDrawing(ImageOutput(MyCanvasOutput))
  DrawingMode(#PB_2DDrawing_AllChannels|#PB_2DDrawing_Outlined)
  Box(3,3,106,30,RGBA(255,0,0,255))
  DrawingMode(#PB_2DDrawing_AlphaBlend|#PB_2DDrawing_Transparent)
  DrawText(8,9,"Veni, Vidi, Vici.", RGBA(255,0,0,255))
StopDrawing()
PreMultiply(MyCanvasOutput)

Repeat:Until WaitWindowEvent() = #PB_Event_CloseWindow

If IsLibrary(msimg32)
  CloseLibrary(msimg32)
EndIf
BERESHEIT
Joubarbe
Enthusiast
Enthusiast
Posts: 703
Joined: Wed Sep 18, 2013 11:54 am
Location: France

Re: Transparent background for canvas ?

Post by Joubarbe »

Thanks netmaestro ; indeed that's a lot of lines :)
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Re: Transparent background for canvas ?

Post by netmaestro »

You're welcome! Unfortunately there is no native way to accomplish transparency in a canvasgadget. Mind you, the task can be done in quite some fewer lines. The WM_ERASEBACKGROUND message could be done away with and its brush moved to WM_PAINT, where it could be combined with the foreground stuff via DrawAlphaImage and then output with BitBlt. Because it would cover the entire background, no erase would be needed and the premultiply and imports for AlphaBlend_() could be removed. The result would be a lot slimmer.
BERESHEIT
Post Reply