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.

Thanks, Infratec. I'll take a look right away and see if I can figure out how it all works.infratec wrote: Tue Sep 30, 2025 8:16 pm Only examples:
viewtopic.php?t=63941
viewtopic.php?t=43558
viewtopic.php?t=74267
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
Thank you very much mk-soft with a few minor changes, I think your code would be perfect for what I need.!!!mk-soft wrote: Tue Sep 30, 2025 11:32 pm I found something else of myself ...
Without modules or OOP
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
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