Help custom gadget

Just starting out? Need help? Post your questions and find answers here.
User avatar
le_magn
Enthusiast
Enthusiast
Posts: 288
Joined: Wed Aug 24, 2005 12:11 pm
Location: Italia

Help custom gadget

Post by le_magn »

Hello everyone, I would like to create a custom button, flat like the ones in the image, which changes background color when you hover over it with the mouse or select it. Do you have any simple examples to start with or a guide that explains step by step how to create custom gadgets? Thank you very much.

P.S. In the past, I used simple image gadgets to get around the problem, but it's inconvenient and I would prefer to create my own custom gadgets.

Image
Image
infratec
Always Here
Always Here
Posts: 7658
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Help custom gadget

Post by infratec »

User avatar
le_magn
Enthusiast
Enthusiast
Posts: 288
Joined: Wed Aug 24, 2005 12:11 pm
Location: Italia

Re: Help custom gadget

Post by le_magn »

infratec wrote: Tue Sep 30, 2025 8:16 pm Only examples:

viewtopic.php?t=63941

viewtopic.php?t=43558

viewtopic.php?t=74267
Thanks, Infratec. I'll take a look right away and see if I can figure out how it all works.
Image
User avatar
mk-soft
Always Here
Always Here
Posts: 6284
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Help custom gadget

Post by mk-soft »

I found something else of myself ...
Without modules or OOP

Code: Select all

;- CanvasButtonGadget by mk-soft, v1.05, 08.12.2023

Procedure DrawCanvasButton(Gadget, Image, BackColor, Offset = 0)
  Protected dx, dy, Image2
  
  dx = DesktopScaledX(GadgetWidth(Gadget))
  dy = DesktopScaledY(GadgetHeight(Gadget))
  
  If StartDrawing(CanvasOutput(Gadget))
    If Offset
      Box(0, 0, dx, dy, $DCDCDC)
      Box(Offset, Offset, dx, dy, BackColor)
    Else
      Box(0, 0, dx, dy, BackColor)
    EndIf
    If IsImage(Image)
      If ImageWidth(image) = dx
        DrawAlphaImage(ImageID(Image), Offset, Offset)
      Else
        Image2 = CopyImage(Image, #PB_Any)
        ResizeImage(Image2, dx, dy)
        DrawAlphaImage(ImageID(Image2), Offset, Offset)
        FreeImage(Image2)
      EndIf
    EndIf
    StopDrawing()
  EndIf
EndProcedure

Procedure DoCanvasButtonEvent()
  Protected Gadget = EventGadget()
  Protected Image = GetGadgetData(Gadget)
  
  Select EventType()
    Case #PB_EventType_MouseEnter
      DrawCanvasButton(Gadget, Image, $FFFFE0)
    Case #PB_EventType_MouseLeave
      DrawCanvasButton(Gadget, Image, $DCDCDC)
    Case #PB_EventType_LeftButtonDown
      DrawCanvasButton(Gadget, Image, $EEEEAF, 1)
    Case #PB_EventType_LeftButtonUp
      DrawCanvasButton(Gadget, Image, $FFFFE0)
    
  EndSelect
EndProcedure

Procedure CanvasButtonGadget(Gadget, x, y, Width, Height, Image)
  Protected r1
  r1 = CanvasGadget(Gadget, x, y, Width, Height)
  If Gadget = #PB_Any
    Gadget = r1
  EndIf
  If r1
    SetGadgetData(Gadget, Image)
    DrawCanvasButton(Gadget, Image, $DCDCDC)
    BindGadgetEvent(Gadget, @DoCanvasButtonEvent())
  EndIf
  ProcedureReturn r1
EndProcedure

; ****

Procedure CreateButtonImage(Image, Width, Height, Text.s, IconID)
  Static Font
  Protected r1, dx, dy
  
  If Not Font
    Font = LoadFont(#PB_Any, "Segoe UI", 11, #PB_Font_HighQuality)
  EndIf
  
  dx = DesktopScaledX(Width)
  dy = DesktopScaledY(Height)
  
  r1 = CreateImage(Image, dx, dy, 32, #PB_Image_Transparent)
  If Image = #PB_Any
    Image = r1
  EndIf
  If r1
    If StartDrawing(ImageOutput(Image))
      DrawImage(IconID, DesktopScaledX(4), DesktopScaledY(4))
      DrawingFont(FontID(Font))
      DrawingMode( #PB_2DDrawing_AlphaChannel | #PB_2DDrawing_Transparent ) 
      DrawText(DesktopScaledX(40), DesktopScaledY(10), Text.s)
      StopDrawing()
    EndIf
  EndIf
  ProcedureReturn r1
EndProcedure

Procedure CreateButtonVectorImage(Image, Width, Height, Text.s, IconID)
  Static Font
  Protected r1, dx, dy
  
  If Not Font
    Font = LoadFont(#PB_Any, "Segoe UI", 11, #PB_Font_HighQuality)
  EndIf
  
  dx = DesktopScaledX(Width)
  dy = DesktopScaledY(Height)
  
  r1 = CreateImage(Image, dx, dy, 32, #PB_Image_Transparent)
  If Image = #PB_Any
    Image = r1
  EndIf
  If r1
    If StartVectorDrawing(ImageVectorOutput(Image))
      MovePathCursor(DesktopScaledX(4), DesktopScaledY(4))
      DrawVectorImage(IconID, 255, DesktopScaledX(32), DesktopScaledY(32))
      VectorFont(FontID(Font), DesktopScaledX(12 * 96 / 72))
      MovePathCursor(DesktopScaledX(8+32+4), (VectorOutputHeight() - DesktopScaledY(2*4) - VectorTextHeight(Text, #PB_VectorText_Visible))/2)
      DrawVectorText(Text)    
      StopVectorDrawing()
    EndIf
  EndIf
  ProcedureReturn r1
EndProcedure

UsePNGImageDecoder()

CompilerIf #PB_Compiler_OS = #PB_OS_Windows
  
  hIcon = ExtractIcon_(0,"imageres.dll", 100)
  CreateButtonImage(10, 120, 40, "Hi there", hIcon)
  DestroyIcon_(hIcon)
  
  hIcon = ExtractIcon_(0,"imageres.dll", 101)
  CreateButtonVectorImage(11, 120, 40, "Its Nice", hIcon)
  DestroyIcon_(hIcon)
 
CompilerElse
  
  hIcon = LoadImage(0, #PB_Compiler_Home + "examples/3d/Data/Textures/GLX_icon.png")
  CreateButtonVectorImage(10, 120, 40, "Hi there", hIcon)
  
  hIcon = LoadImage(0, #PB_Compiler_Home + "examples/3d/Data/Textures/grass1.png")
  CreateButtonVectorImage(11, 120, 40, "Its Nice", hIcon)
  
CompilerEndIf

OpenWindow(0,0,0,640,480,"Canvas Button Test",#PB_Window_SystemMenu| #PB_Window_ScreenCentered)

CanvasButtonGadget(1, 10, 10, 120, 40, 10)
CanvasButtonGadget(2, 140, 10, 120, 40, 11)
CanvasButtonGadget(3, 10, 60, 360, 120, 11)

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Quit = 1
      
    Case #PB_Event_Gadget
      Select EventGadget()
        Case 1
          Select EventType()
            Case #PB_EventType_LeftClick
              Debug "Button 1"
              
          EndSelect
        Case 2
          Select EventType()
            Case #PB_EventType_LeftClick
              Debug "Button 2"
              
          EndSelect
          
      EndSelect
      
  EndSelect
Until Quit = 1
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
User avatar
blueb
Addict
Addict
Posts: 1118
Joined: Sat Apr 26, 2003 2:15 pm
Location: Cuernavaca, Mexico

Re: Help custom gadget

Post by blueb »

Thanks mk-soft,
I just completed a project, and had to use a combination of Image and Hyperlinks.. workable but difficult to move around. Wished I would have found this sooner. Better late than never. :mrgreen:
- It was too lonely at the top.

System : PB 6.21(x64) and Win 11 Pro (x64)
Hardware: AMD Ryzen 9 5900X w/64 gigs Ram, AMD RX 6950 XT Graphics w/16gigs Mem
User avatar
le_magn
Enthusiast
Enthusiast
Posts: 288
Joined: Wed Aug 24, 2005 12:11 pm
Location: Italia

Re: Help custom gadget

Post by le_magn »

mk-soft wrote: Tue Sep 30, 2025 11:32 pm I found something else of myself ...
Without modules or OOP
Thank you very much mk-soft with a few minor changes, I think your code would be perfect for what I need.!!!
Image
User avatar
blueb
Addict
Addict
Posts: 1118
Joined: Sat Apr 26, 2003 2:15 pm
Location: Cuernavaca, Mexico

Re: Help custom gadget

Post by blueb »

This is an example of using mk-soft's CanvasButtonGadget.
I have modified the PBI file to create 'vertical' icon/text rather than mk-soft's horizontal layout. The vertical layout is very similar to most Android phone icon layouts, which is popular at the moment.

First the PBI include source code... followed by the sample code.

Note you will need to supply your own 6 PNG icons labelled #1 to #6 see the code) My icons are 48 by 48, but I think most sizes will work.

PBI include...

Code: Select all

;- CanvasButtonGadget by mk-soft, v1.05, 08.12.2023
;- Modified for vertical icon/text layout with configurable sizing

; NOTE: Define color globals BEFORE using the PBI file (in your main program)
;Global WindowBackColor = 16252927, BtnBackColor = 16252927 (example backcolor)
;
; XIncludeFile "VectorCanvas.pbi"
; ====================================

Procedure DrawCanvasButton(Gadget, Image, BtnBackColor, Offset = 0)
  Protected dx, dy, Image2
  
  dx = DesktopScaledX(GadgetWidth(Gadget))
  dy = DesktopScaledY(GadgetHeight(Gadget))
  
  If StartDrawing(CanvasOutput(Gadget))
    If Offset
      Box(0, 0, dx, dy, BtnBackColor)
      Box(Offset, Offset, dx - Offset * 2, dy - Offset * 2, BtnBackColor)
    Else
      Box(0, 0, dx, dy, BtnBackColor)
    EndIf
    If IsImage(Image)
      If ImageWidth(Image) = dx And ImageHeight(Image) = dy
        DrawAlphaImage(ImageID(Image), Offset, Offset)
      Else
        Image2 = CopyImage(Image, #PB_Any)
        ResizeImage(Image2, dx, dy)
        DrawAlphaImage(ImageID(Image2), Offset, Offset)
        FreeImage(Image2)
      EndIf
    EndIf
    StopDrawing()
  EndIf
EndProcedure

Procedure DoCanvasButtonEvent()
  Protected Gadget = EventGadget()
  Protected Image = GetGadgetData(Gadget)
  
  Select EventType()
    Case #PB_EventType_MouseEnter
      DrawCanvasButton(Gadget, Image, $FFFFE0)
    Case #PB_EventType_MouseLeave
      DrawCanvasButton(Gadget, Image, BtnBackColor)
    Case #PB_EventType_LeftButtonDown
      DrawCanvasButton(Gadget, Image, $EEEEAF, 1)
    Case #PB_EventType_LeftButtonUp
      DrawCanvasButton(Gadget, Image, $FFFFE0)
    
  EndSelect
EndProcedure

Procedure CanvasButtonGadget(Gadget, x, y, Width, Height, Image)
  Protected r1
  r1 = CanvasGadget(Gadget, x, y, Width, Height)
  If Gadget = #PB_Any
    Gadget = r1
  EndIf
  If r1
    SetGadgetData(Gadget, Image)
    DrawCanvasButton(Gadget, Image, BtnBackColor)
    BindGadgetEvent(Gadget, @DoCanvasButtonEvent())
  EndIf
  ProcedureReturn r1
EndProcedure

Procedure CreateButtonVectorImage(Image, Width, Height, Text.s, IconID, IconSize.i = 32, TextSize.i = 11)
  Static Font
  Protected r1, dx, dy
  
  ; Load font with specified size
  If Not Font Or TextSize <> 11  ; Reload if size changes
    If Font : FreeFont(Font) : EndIf
    ;Font = LoadFont(#PB_Any, "Segoe UI", TextSize, #PB_Font_HighQuality)
    Font = LoadFont(#PB_Any, "Segoe UI", TextSize, #PB_Font_HighQuality | #PB_Font_Bold)
  EndIf
  
  dx = DesktopScaledX(Width)
  dy = DesktopScaledY(Height)
  
  r1 = CreateImage(Image, dx, dy, 32, #PB_Image_Transparent)
  If Image = #PB_Any
    Image = r1
  EndIf
  If r1
    If StartVectorDrawing(ImageVectorOutput(Image))
      ; Center icon at top
      Protected IconX.i = (DesktopScaledX(Width) - DesktopScaledX(IconSize)) / 2
      Protected IconY.i = DesktopScaledY(8)
      MovePathCursor(IconX, IconY)
      DrawVectorImage(IconID, 255, DesktopScaledX(IconSize), DesktopScaledY(IconSize))
      
      ; Center text below icon
      VectorFont(FontID(Font), DesktopScaledX(TextSize * 96 / 72))
      Protected TextWidth.f = VectorTextWidth(Text, #PB_VectorText_Visible)
      Protected TextX.i = (VectorOutputWidth() - TextWidth) / 2
      Protected TextY.i = DesktopScaledY(IconY + IconSize + 4)
      MovePathCursor(TextX, TextY)
      DrawVectorText(Text)    
      StopVectorDrawing()
    EndIf
  EndIf
  ProcedureReturn r1
EndProcedure
Sample code...

Code: Select all

; =============================================================================
;        File Name:  Vertical Demo.pb  (based on mk-softs code)
;      Description:  Vertical CanvasGadget Buttons Demo
;                    Shows 6 icon/text button combinations on left side of form
;           Author:  Blueb   
;             Date:  Oct 6, 2025
;       PB-Version:  Tested with 6.30 b3 (x64)
;    Typical Usage:  based on CanvasButtonGadget  (horizontal buttons) by mk-soft, v1.05, 08.12.2023
;
;            Forum:  https://www.purebasic.fr/english/viewtopic.php?p=645982#p645982       
; =============================================================================

; Define color globals BEFORE including the PBI file
Global WindowBackColor = $E4F4D4, BtnBackColor = $E4F4D4

XIncludeFile "VerticalCanvas.pbi"

;-----[ Main Program ]-----
UsePNGImageDecoder()

Enumeration
  #MainWindow
  #Image1
  #Image2
  #Image3
  #Image4
  #Image5
  #Image6
  #BtnOne
  #BtnTwo
  #BtnThree
  #BtnFour
  #BtnFive
  #BtnSix
  #InfoText
EndEnumeration

Define Quit.i = 0
Define.i ButtonWidth = 90, ButtonHeight = 70, ButtonSpacing = 10
Define.i StartY = 20
Define.i CurrentPage = 1

; Text content for two pages
Define.s Page1Text, Page2Text

Page1Text = "Vertical CanvasGadget Buttons Demo" + #LF$ + #LF$ +
            "These buttons demonstrate icon/text combinations using the CanvasButtonGadget." + #LF$ + #LF$ +
            "Features:" + #LF$ +
            "• Icons centered at top" + #LF$ +
            "• Text centered below icon" + #LF$ +
            "• Hover effects (yellow highlight)" + #LF$ +
            "• Click feedback (pressed state)" + #LF$ +
            "• Configurable icon and text sizes" + #LF$ +
            "• Uses transparent PNG files (1.png - 6.png)" + #LF$ + #LF$ +
            "PNG Files Used:" + #LF$ +
            "  1.png, 2.png, 3.png, 4.png, 5.png, 6.png" + #LF$ + #LF$ +
            "To customize:" + #LF$ +
            "• Replace PNG files with your own icons" + #LF$ +
            "• Modify button text in CreateButtonVectorImage calls" + #LF$ +
            "• Adjust ButtonWidth, ButtonHeight, and spacing" + #LF$ + #LF$ +
            "Click the buttons to see them in action!" + #LF$ +
            "Check the Debug output window for button click events."

Page2Text = "Button Click Event Detected!" + #LF$ + #LF$ +
            "Congratulations! You've successfully clicked a button." + #LF$ + #LF$ +
            "This demonstrates how button events work:" + #LF$ + #LF$ +
            "Each button can trigger unique actions when clicked. In this demo, " +
            "clicking any button toggles between two informational pages. " + #LF$ + #LF$ +
            "In a real application, you could:" + #LF$ +
            "• Navigate to different sections" + #LF$ +
            "• Open dialog windows" + #LF$ +
            "• Execute specific functions" + #LF$ +
            "• Update database records" + #LF$ +
            "• Start/stop processes" + #LF$ +
            "• Load different content" + #LF$ + #LF$ +
            "The possibilities are endless! Each button (#BtnOne through #BtnSix) " +
            "can be programmed to perform completely different tasks based on your needs." + #LF$ + #LF$ +
            "Click any button again to return to the main information page."

; Create the button images with icon/text combinations
CreateButtonVectorImage(#Image1, ButtonWidth, ButtonHeight, "Home", LoadImage(0, "1.png"), 32, 10)
CreateButtonVectorImage(#Image2, ButtonWidth, ButtonHeight, "Settings", LoadImage(0, "2.png"), 32, 10)
CreateButtonVectorImage(#Image3, ButtonWidth, ButtonHeight, "Play", LoadImage(0, "3.png"), 32, 10)
CreateButtonVectorImage(#Image4, ButtonWidth, ButtonHeight, "Favorites", LoadImage(0, "4.png"), 32, 10)
CreateButtonVectorImage(#Image5, ButtonWidth, ButtonHeight, "Add New", LoadImage(0, "5.png"), 32, 10)
CreateButtonVectorImage(#Image6, ButtonWidth, ButtonHeight, "Complete", LoadImage(0, "6.png"), 32, 10)

; Create main window
OpenWindow(#MainWindow, 0, 0, 600, 500, "Vertical CanvasGadget Buttons Demo", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
SetWindowColor(#MainWindow, WindowBackColor)

; Place created buttons on the form vertically on left side
CanvasButtonGadget(#BtnOne, 10, StartY, ButtonWidth, ButtonHeight, #Image1)
CanvasButtonGadget(#BtnTwo, 10, StartY + (ButtonHeight + ButtonSpacing), ButtonWidth, ButtonHeight, #Image2)
CanvasButtonGadget(#BtnThree, 10, StartY + 2 * (ButtonHeight + ButtonSpacing), ButtonWidth, ButtonHeight, #Image3)
CanvasButtonGadget(#BtnFour, 10, StartY + 3 * (ButtonHeight + ButtonSpacing), ButtonWidth, ButtonHeight, #Image4)
CanvasButtonGadget(#BtnFive, 10, StartY + 4 * (ButtonHeight + ButtonSpacing), ButtonWidth, ButtonHeight, #Image5)
CanvasButtonGadget(#BtnSix, 10, StartY + 5 * (ButtonHeight + ButtonSpacing), ButtonWidth, ButtonHeight, #Image6)

; Add description text
TextGadget(#InfoText, 120, 20, 450, 440, Page1Text, #PB_Text_Border)

;- Events ----------------
Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Quit = 1
      
    Case #PB_Event_Gadget
      Select EventGadget()
        Case #BtnOne
          Select EventType()
            Case #PB_EventType_LeftClick
              Debug "Button 1 - Home clicked"
              CurrentPage = 3 - CurrentPage  ; Toggle between 1 and 2
              If CurrentPage = 1
                SetGadgetText(#InfoText, Page1Text)
              Else
                SetGadgetText(#InfoText, Page2Text)
              EndIf
          EndSelect
          
        Case #BtnTwo
          Select EventType()
            Case #PB_EventType_LeftClick
              Debug "Button 2 - Settings clicked"
              CurrentPage = 3 - CurrentPage
              If CurrentPage = 1
                SetGadgetText(#InfoText, Page1Text)
              Else
                SetGadgetText(#InfoText, Page2Text)
              EndIf
          EndSelect
          
        Case #BtnThree
          Select EventType()
            Case #PB_EventType_LeftClick
              Debug "Button 3 - Play clicked"
              CurrentPage = 3 - CurrentPage
              If CurrentPage = 1
                SetGadgetText(#InfoText, Page1Text)
              Else
                SetGadgetText(#InfoText, Page2Text)
              EndIf
          EndSelect
          
        Case #BtnFour
          Select EventType()
            Case #PB_EventType_LeftClick
              Debug "Button 4 - Favorites clicked"
              CurrentPage = 3 - CurrentPage
              If CurrentPage = 1
                SetGadgetText(#InfoText, Page1Text)
              Else
                SetGadgetText(#InfoText, Page2Text)
              EndIf
          EndSelect
          
        Case #BtnFive
          Select EventType()
            Case #PB_EventType_LeftClick
              Debug "Button 5 - Add New clicked"
              CurrentPage = 3 - CurrentPage
              If CurrentPage = 1
                SetGadgetText(#InfoText, Page1Text)
              Else
                SetGadgetText(#InfoText, Page2Text)
              EndIf
          EndSelect
          
        Case #BtnSix
          Select EventType()
            Case #PB_EventType_LeftClick
              Debug "Button 6 - Complete clicked"
              CurrentPage = 3 - CurrentPage
              If CurrentPage = 1
                SetGadgetText(#InfoText, Page1Text)
              Else
                SetGadgetText(#InfoText, Page2Text)
              EndIf
          EndSelect
          
      EndSelect
      
  EndSelect
Until Quit = 1

End
- It was too lonely at the top.

System : PB 6.21(x64) and Win 11 Pro (x64)
Hardware: AMD Ryzen 9 5900X w/64 gigs Ram, AMD RX 6950 XT Graphics w/16gigs Mem
User avatar
le_magn
Enthusiast
Enthusiast
Posts: 288
Joined: Wed Aug 24, 2005 12:11 pm
Location: Italia

Re: Help custom gadget

Post by le_magn »

Thank you, Blueb, for this other fantastic sample.
Image
Post Reply