It is currently Sun Jan 24, 2021 1:26 pm

All times are UTC + 1 hour




Post new topic Reply to topic  [ 24 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Owner-drawn buttons
PostPosted: Wed Feb 15, 2012 9:32 am 
Offline
Addict
Addict
User avatar

Joined: Mon Jun 06, 2005 2:35 pm
Posts: 1259
Location: germany
Hi,

I just want to share my button include to make such buttons:
Image

It works on Windows and Linux in single-byte or unicode-mode. I did not test on x64 architecture.

Update on 14th April 2012: added multi window capabilities and horizontal icon (left from text) using rbutton_CreateH()

Update on 16th July 2012: added rbutton_Hide() function to effectively hide/unhide buttons

Code of rbutton_include.pbi:
Code:
; Compiles on Windows and Linux (tested 32 Bit, 64bit, single-byte and unicode)
; works with EnableExplicit

; Usage example with loaded backgrounds (normal and hover):
; rbutton_SetFont("Verdana", 16, 0, RGB(255,255,255), -120)
; rbutton_Init(CatchImage(#PB_Any, ?Back), CatchImage(#PB_Any, ?BackHover))
; Define regButton1.i = rbutton_Create(#PB_Any, "display", 10, 10, LoadImage(#PB_Any, "display.png"))
;
; Usage example with self drawn background
; rbutton_SetFont("Verdana", 16, 0, RGB(255,255,255), -120)
; rbutton_Init_OwnerDrawn(120, 120, RGBA(255,255,255,255), RGBA(214,226,236,255), RGBA(120,158,191,255), RGBA(255,255,255,255), RGBA(90,167,255,255),15, 2)
; Define regButton1.i = rbutton_Create(#PB_Any, WindowID, "display", 10, 10, LoadImage(#PB_Any, "display.png"))
;
; Do a call to rbutton_CheckHover(WinID) in your event-loop to enable hover effect
;
; HINT: You can call rbutton_Init(), rbutton_Init_OwnerDrawn() and rbutton_SetFont() multiple
;       times to make different buttons on the same window/screen.
UsePNGImageDecoder()

#button_ShaddowWidth   = 5  ; how wide the shaddow will be around the button (default 5)
#button_ShaddowOpacity = 30 ; 'darkness' of the surrounding shaddow: 10 = light 100 = heavy (default 30)
#button_HoverDimm      = 20 ; hover-effect dimming of the background gradient (>0 = lighten, <0 = darken) (default 20)
#button_ScaleFactor    = 2  ; making smoother, do not change (default 2)

Structure structrButtonList
  Caption.s                 ; Gadget Caption
  Disabled.b                ; #True or #False
  Hidden.b                  ; #True or #False
  GadgetID.i                ; image-gadget ID
  ButtonImageID_draw.i      ; image-id of image to draw onto
  ButtonImageID_normal.i    ; image-id of background image normal
  ButtonImageID_hover.i     ; image-id of background image hover
  X.i                       ; Gadget X
  Y.i                       ; Gadget Y
  Width.i                   ; Gadget Width
  Height.i                  ; Gadget Height
  IconImageID.i             ; Icon image-id
  IconWidth.i               ; Icon Width
  IconHeight.i              ; Icon Height
  IconX.i                   ; Icon position X in Gadget
  IconY.i                   ; Icon position Y in Gadget
  TextX.i                   ; Text Position X in Gadget
  TextY.i                   ; Text Position Y in Gadget
  FontName.s
  FontSize.i
  FontStyle.i
  FontColor.i
  ShaddowDimm.i
  WindowID.i                ; ID of the window this button is drawn on
EndStructure

Structure structrButton
  rButtonImageID_normal.i
  rButtonImageID_hover.i
  FontName.s
  FontSize.i
  FontStyle.i
  FontColor.i
  ShaddowDimm.i
  LineThickness.i
  List ButtonList.structrButtonList()
EndStructure

Global rButton.structrButton

; Makes the cursor in the window (parent of given Gadget) to a hand
; Works both windows and linux
Procedure.b rbutton_MakeCursorHand(GadgetID.i)
  CompilerSelect #PB_Compiler_OS
  CompilerCase #PB_OS_Windows
   
    ; WINDOWS
    Static *cursor
    If *cursor = 0
      *cursor = LoadCursor_(0, #IDC_HAND)
    EndIf
    SetCursor_(*cursor)
   
  CompilerCase #PB_OS_Linux
   
    ; LINUX
    Static *cursor.GdkCursor
    If *cursor = 0
      *cursor = gdk_cursor_new_(#GDK_HAND1);
    EndIf
    gdk_window_set_cursor_(gtk_widget_get_parent_window_(GadgetID(GadgetID.i)), *cursor)
   
  CompilerCase #PB_OS_MacOS
    ; MAC
    ; write me!
   
  CompilerEndSelect
EndProcedure

; Checks, if the current mouse position is over the given gadget.
; Returns #True in case of success, otherwise #False.
; Use this in your GUI loop (for example to change the cursor in
; conjunction with rbutton_MakeCursorHand()).
Procedure.b rbutton_MouseOverGadget(WindowID.i, GadgetID.i)
 
  Protected MX.i = WindowMouseX(WindowID.i)
  Protected MY.i = WindowMouseY(WindowID.i)
  Protected GX.i = GadgetX(GadgetID.i)
  Protected GY.i = GadgetY(GadgetID.i)
  Protected GW.i = GadgetWidth(GadgetID.i)
  Protected GH.i = GadgetHeight(GadgetID.i)
 
  If MX.i > GX.i And MX.i < (GX.i + GW.i) And MY.i > GY.i And MY.i < (GY.i + GH.i)
    ProcedureReturn #True
  EndIf
  ProcedureReturn #False
EndProcedure

; Helping function to dimm a color.
; Example:
; NewColor.i = rbutton_DimmColor(OriginalColor.i, -50); reduce by 50
Procedure.i rbutton_DimmColor(OriginalColor.i, Dimm.i)
  Protected R.i = Red(OriginalColor.i)
  Protected G.i = Green(OriginalColor.i)
  Protected B.i = Blue(OriginalColor.i)
 
  R.i = R.i + Dimm.i: If R.i < 0: R.i = 0: EndIf: If R.i > 255: R.i = 255: EndIf
  G.i = G.i + Dimm.i: If G.i < 0: G.i = 0: EndIf: If G.i > 255: G.i = 255: EndIf
  B.i = B.i + Dimm.i: If B.i < 0: B.i = 0: EndIf: If B.i > 255: B.i = 255: EndIf
 
  ProcedureReturn RGB(R.i, G.i, B.i)
EndProcedure

; Set the font for the r-style buttons.
; Need to be called before creating the first button.
; FontStyle.i follows the purebasic LoadFont() constants like #PB_Font_Bold.
Procedure.b rbutton_SetFont(FontName.s, FontSize.i, FontStyle.i = 0, FontColor.i = 0, ShaddowDimm.i = 0)
  With rButton
    \FontName     = FontName.s
    \FontSize     = FontSize.i
    \FontStyle    = FontStyle.i
    \FontColor    = FontColor.i
    \ShaddowDimm  = ShaddowDimm.i
  EndWith
  ProcedureReturn #True
EndProcedure

; Initialize main rbutton preferences with own drawn images
Procedure.b rbutton_Init_OwnerDrawn(Width.i, Height.i, BackgroundColor.i, TopColor.i, BottomColor.i, LineColor.i, LineColorSelected.i, EdgeRadius.f = 15, LineThickness.i = 2)
  Protected x.i, EdgeRadiusUse.f
 
  Width.i         = Width.i * #button_ScaleFactor
  Height.i        = Height.i * #button_ScaleFactor
  EdgeRadiusUse.f = EdgeRadius.f * #button_ScaleFactor
  LineThickness.i = LineThickness.i * #button_ScaleFactor
 
  Protected BackImage.i = CreateImage(#PB_Any, Width.i, Height.i, #PB_Image_Transparent  | 32)
 
  Protected ShaddowWidth.f = #button_ShaddowWidth
 
  Protected CenterX.f = Width.i / 2
  Protected CenterY.f = Height.i / 2
 
  Protected XRadius.f = Width.i / 2 + #button_ScaleFactor
  Protected YRadius.f = Height.i / 2 + #button_ScaleFactor
 
  StartDrawing(ImageOutput(BackImage.i))
 
  DrawingMode(#PB_2DDrawing_AlphaBlend)
 
  ; make background with background color
  Box(0, 0, Width.i, Height.i, RGBA(Red(BackgroundColor.i), Green(BackgroundColor.i), Blue(BackgroundColor.i), 255))
  LineColor.i = RGBA(Red(LineColor.i), Green(LineColor.i), Blue(LineColor.i), 255)
  LineColorSelected.i = RGBA(Red(LineColorSelected.i), Green(LineColorSelected.i), Blue(LineColorSelected.i), 255)
 
  ; make shaddows
  DrawingMode(#PB_2DDrawing_AlphaBlend)
  Protected ShaddowStep.f = #button_ShaddowOpacity / ShaddowWidth.f
  For x.i = 1 To ShaddowWidth.f
    XRadius.f = XRadius.f - #button_ScaleFactor
    YRadius.f = YRadius.f - #button_ScaleFactor
    EdgeRadiusUse.f = EdgeRadiusUse.f - #button_ScaleFactor / 2
    If EdgeRadiusUse.f < 0: EdgeRadiusUse.f = 0: EndIf
    RoundBox(CenterX.f - XRadius.f, CenterY.f - YRadius.f, XRadius.f * 2, YRadius.f * 2, EdgeRadiusUse.f, EdgeRadiusUse.f, RGBA(0,0,0, x.i * ShaddowStep.f))
  Next
 
  ; make border with LineColor
  DrawingMode(#PB_2DDrawing_AllChannels)
  RoundBox(CenterX.f - XRadius.f, CenterY.f - YRadius.f, XRadius.f * 2, YRadius.f * 2, EdgeRadiusUse.f, EdgeRadiusUse.f, LineColor.i)
  XRadius.f = XRadius.f - LineThickness.i
  YRadius.f = YRadius.f - LineThickness.i
  EdgeRadiusUse.f = EdgeRadiusUse.f - LineThickness.i
  If EdgeRadiusUse.f < 0: EdgeRadiusUse.f = 0: EndIf
 
  ; background gradient
  DrawingMode(#PB_2DDrawing_Gradient)
  BackColor(TopColor.i)
  FrontColor(BottomColor.i)
  Protected Rotate.f = YRadius.f / 2
  LinearGradient(CenterX.f, CenterY.f - YRadius.f, CenterX.f + Rotate.f, CenterY.f + YRadius.f)
  RoundBox(CenterX.f - XRadius.f, CenterY.f - YRadius.f, XRadius.f * 2, YRadius.f * 2, EdgeRadiusUse.f, EdgeRadiusUse.f)
  StopDrawing()
 
  ResizeImage(BackImage.i, Width.i / #button_ScaleFactor, Height.i / #button_ScaleFactor, #PB_Image_Smooth)
 
  Protected ButtonImageNormalID.i = BackImage.i
 
  ; HOVER IMAGE
 
  Protected BackImageHover.i = CreateImage(#PB_Any, Width.i, Height.i, #PB_Image_Transparent  | 32)
 
  EdgeRadiusUse.f = EdgeRadius.f * #button_ScaleFactor
  XRadius.f       = Width.i / 2 + #button_ScaleFactor
  YRadius.f       = Height.i / 2 + #button_ScaleFactor
 
  StartDrawing(ImageOutput(BackImageHover.i))
 
  DrawingMode(#PB_2DDrawing_AlphaBlend)
 
  ; make background with background color
  Box(0, 0, Width.i, Height.i, RGBA(Red(BackgroundColor.i), Green(BackgroundColor.i), Blue(BackgroundColor.i), 255))
 
  ; dimm colors for hover effect
  TopColor.i    = rbutton_DimmColor(TopColor.i, #button_HoverDimm)
  BottomColor.i = rbutton_DimmColor(BottomColor.i, #button_HoverDimm)
 
  ; make shaddows
  DrawingMode(#PB_2DDrawing_AlphaBlend)
  ShaddowStep.f = #button_ShaddowOpacity / ShaddowWidth.f
  For x.i = 1 To ShaddowWidth.f
    XRadius.f = XRadius.f - #button_ScaleFactor
    YRadius.f = YRadius.f - #button_ScaleFactor
    EdgeRadiusUse.f = EdgeRadiusUse.f - #button_ScaleFactor / 2
    If EdgeRadiusUse.f < 0: EdgeRadiusUse.f = 0: EndIf
    RoundBox(CenterX.f - XRadius.f, CenterY.f - YRadius.f, XRadius.f * 2, YRadius.f * 2, EdgeRadiusUse.f, EdgeRadiusUse.f, RGBA(0,0,0, x.i * ShaddowStep.f))
  Next
 
  ; make border with LineColor
  DrawingMode(#PB_2DDrawing_AllChannels)
  RoundBox(CenterX.f - XRadius.f, CenterY.f - YRadius.f, XRadius.f * 2, YRadius.f * 2, EdgeRadiusUse.f, EdgeRadiusUse.f, LineColorSelected.i)
  XRadius.f = XRadius.f - LineThickness.i
  YRadius.f = YRadius.f - LineThickness.i
  EdgeRadiusUse.f = EdgeRadiusUse.f - LineThickness.i
  If EdgeRadiusUse.f < 0: EdgeRadiusUse.f = 0: EndIf
 
  ; background gradient
  DrawingMode(#PB_2DDrawing_Gradient)
  BackColor(TopColor.i)
  FrontColor(BottomColor.i)
  Rotate.f = YRadius.f / 2
  LinearGradient(CenterX.f, CenterY.f - YRadius.f, CenterX.f + Rotate.f, CenterY.f + YRadius.f)
  RoundBox(CenterX.f - XRadius.f, CenterY.f - YRadius.f, XRadius.f * 2, YRadius.f * 2, EdgeRadiusUse.f, EdgeRadiusUse.f)
  StopDrawing()
 
  ResizeImage(BackImageHover.i, Width.i / #button_ScaleFactor, Height.i / #button_ScaleFactor, #PB_Image_Smooth)
 
  Protected ButtonImageHoverID.i  = BackImageHover.i
 
  With rButton
    \rButtonImageID_normal = ButtonImageNormalID.i
    \rButtonImageID_hover  = ButtonImageHoverID.i
    \LineThickness         = LineThickness.i ; for later use while drawing
  EndWith
EndProcedure

; Initialize main rbutton preferences:
; ButtonImageNormalID.i = ImageID of an image to use as button background
; ButtonImageHoverID.i  = ImageID of an image to use as button background in case of mouse-hover (same size!)
Procedure.b rbutton_Init(ButtonImageNormalID.i, ButtonImageHoverID.i)
  With rButton
    \rButtonImageID_normal = ButtonImageNormalID.i
    \rButtonImageID_hover  = ButtonImageHoverID.i
  EndWith
EndProcedure

; Filter-procedure for disabled icons in rbutton_Redraw-Function
Procedure rbutton_FilterCallback(x, y, SourceColor, DestinationColor)
  Protected AlphaVal = Alpha(SourceColor)
  Protected AlphaValNeg = 255-Alpha(SourceColor)
 
  Protected NewRed = (Green(SourceColor) * 0.7 * AlphaVal + Red(DestinationColor)   * AlphaValNeg) / 255
  Protected NewBlu = (Green(SourceColor) * 0.7 * AlphaVal + Blue(DestinationColor)  * AlphaValNeg) / 255
  Protected NewGre = (Green(SourceColor) * 0.7 * AlphaVal + Green(DestinationColor) * AlphaValNeg) / 255
 
  If NewRed > 255: NewRed = 255: EndIf
  If NewBlu > 255: NewBlu = 255: EndIf
  If NewGre > 255: NewGre = 255: EndIf
 
  Protected NewColor = RGBA(NewRed, NewGre, NewBlu, 255)
 
  ProcedureReturn NewColor
EndProcedure

; Redraws an existing r button
; state=0 -> normal
; state=1 -> hover / highlighted
Procedure.b rbutton_Redraw(rGadgetID.i, State.i)
  Protected Found.b = #False
  Protected TextColor.i
  Protected IconLift.i
  Protected FontName.s, FontSize.i, FontColor.i, FontStyle.i, ShaddowColor.i
  Protected XP.i, YP.i, Caption.s
 
  ForEach rButton\ButtonList()
    If rButton\ButtonList()\GadgetID = rGadgetID.i
      Found.b = #True
      Break
    EndIf
  Next
  If Found.b = #False
    ; Debug "rGadgetID " + Str(rGadgetID.i) + " not found (Redraw)!"
    ProcedureReturn #False
  EndIf
 
  If rButton\ButtonList()\Caption <> ""
    Protected MyFontID.i = LoadFont(#PB_Any, rButton\ButtonList()\FontName, rButton\ButtonList()\FontSize, rButton\ButtonList()\FontStyle) ; load font in desired size
  EndIf
 
  ; draw background
  StartDrawing(ImageOutput(rButton\ButtonList()\ButtonImageID_draw))
  Box(0, 0, rButton\ButtonList()\Width, rButton\ButtonList()\Height, RGBA(0,0,0,0)) ; init as transparent background
  If rButton\ButtonList()\Caption <> "" 
    DrawingFont(FontID(MyFontID.i))
  EndIf
  DrawingMode(#PB_2DDrawing_AlphaBlend)
 
  If rButton\ButtonList()\Disabled = #False
    ; -- ENABLED --
    If State.i = 0
      DrawImage(ImageID(rButton\ButtonList()\ButtonImageID_normal), 0, 0)
      FontColor.i    = rbutton_DimmColor(rButton\ButtonList()\FontColor, -10)
      ShaddowColor.i = rbutton_DimmColor(rButton\ButtonList()\FontColor, rButton\ButtonList()\ShaddowDimm - 10)
      IconLift.i = 0
    EndIf
    If State.i = 1
      DrawImage(ImageID(rButton\ButtonList()\ButtonImageID_hover), 0, 0)
      FontColor.i    = rButton\ButtonList()\FontColor
      ShaddowColor.i = rbutton_DimmColor(rButton\ButtonList()\FontColor, rButton\ButtonList()\ShaddowDimm)
      IconLift.i = -1
    EndIf
   
    ; draw icon
    If rButton\ButtonList()\IconImageID <> 0
      DrawImage(ImageID(rButton\ButtonList()\IconImageID), rButton\ButtonList()\IconX, rButton\ButtonList()\IconY + IconLift.i)
    EndIf
   
    If rButton\ButtonList()\Caption <> ""
      ; draw caption
      DrawingMode(#PB_2DDrawing_Transparent)
      Caption.s = rButton\ButtonList()\Caption
      If ShaddowColor.i <> FontColor.i
        DrawText(rButton\ButtonList()\TextX + 1, rButton\ButtonList()\TextY + 1 + IconLift.i, Caption.s, ShaddowColor.i); shaddow
      EndIf
      DrawText(rButton\ButtonList()\TextX, rButton\ButtonList()\TextY + IconLift.i, Caption.s, FontColor.i) ; real
    EndIf
  Else
    ; -- DISABLED --
    DrawImage(ImageID(rButton\ButtonList()\ButtonImageID_normal), 0, 0)
    ; draw icon
    If rButton\ButtonList()\IconImageID <> 0
      DrawingMode(#PB_2DDrawing_CustomFilter)
      CustomFilterCallback(@rbutton_FilterCallback())
     
      DrawImage(ImageID(rButton\ButtonList()\IconImageID), rButton\ButtonList()\IconX, rButton\ButtonList()\IconY)
    EndIf
   
    If rButton\ButtonList()\Caption <> ""
      ; draw caption
      FontColor.i    = rbutton_DimmColor(rButton\ButtonList()\FontColor, 120)
      ShaddowColor.i = rbutton_DimmColor(rButton\ButtonList()\FontColor, 180)
      IconLift.i = 0
      DrawingMode(#PB_2DDrawing_Transparent)
      Caption.s = rButton\ButtonList()\Caption
      If ShaddowColor.i <> FontColor.i
        DrawText(rButton\ButtonList()\TextX+1, rButton\ButtonList()\TextY + 1, Caption.s, ShaddowColor.i); shaddow
      EndIf
      DrawText(rButton\ButtonList()\TextX, rButton\ButtonList()\TextY, Caption.s, FontColor.i) ; real
    EndIf
   
  EndIf
  StopDrawing()
 
  If IsFont(MyFontID.i)
    FreeFont(MyFontID.i)
  EndIf
 
  ; set final image to ImageGadget
  SetGadgetState(rGadgetID.i, ImageID(rButton\ButtonList()\ButtonImageID_draw))
 
  ProcedureReturn #True
EndProcedure

; Creates a new r-style button in vertical mode (icon on top of text).
; The size depends on the used background-image.
Procedure.i rbutton_Create(Gadget.i, WindowID.i, Caption.s, PosX.i, PosY.i, IconImageID.i = 0)
  Protected FontName.s, FontSize.i, FontColor.i, FontStyle.i, ShaddowColor.i
 
  With rButton
   
    If \FontName = "" : FontName.s = "Verdana": Else : FontName.s = \FontName: EndIf ; use defaults
    If \FontSize = 0  : FontSize.i = 16       : Else : FontSize.i = \FontSize: EndIf ; use defaults
   
    FontStyle.i    = \FontStyle
    FontColor.i    = rbutton_DimmColor(\FontColor, -10)
    ShaddowColor.i = rbutton_DimmColor(\FontColor, \ShaddowDimm - 10)
   
    ; load images, if needed
    If \rButtonImageID_normal = 0
      Debug "Need to call rbutton_Init() at first!"
      ProcedureReturn
    EndIf
    If \rButtonImageID_hover = 0
      Debug "Need to call rbutton_Init() at first!"
      ProcedureReturn
    EndIf
   
    ; prepare button and load images
    AddElement(\ButtonList())
   
    \ButtonList()\ButtonImageID_normal = \rButtonImageID_normal
    \ButtonList()\ButtonImageID_hover  = \rButtonImageID_hover
    \ButtonList()\IconImageID          = IconImageID.i
    \ButtonList()\X                    = PosX.i
    \ButtonList()\Y                    = PosY.i
    \ButtonList()\Width                = ImageWidth(\rButtonImageID_normal)
    \ButtonList()\Height               = ImageHeight(\rButtonImageID_normal)
    \ButtonList()\Caption              = Caption.s
    \ButtonList()\ButtonImageID_draw   = CreateImage(#PB_Any, \ButtonList()\Width, \ButtonList()\Height, 32)
    \ButtonList()\FontName             = \FontName
    \ButtonList()\FontSize             = \FontSize
    \ButtonList()\FontStyle            = \FontStyle
    \ButtonList()\FontColor            = \FontColor
    \ButtonList()\ShaddowDimm          = \ShaddowDimm
    \ButtonList()\WindowID             = WindowID.i
    If IconImageID.i <> 0
      \ButtonList()\IconWidth          = ImageWidth(\ButtonList()\IconImageID)
      \ButtonList()\IconHeight         = ImageHeight(\ButtonList()\IconImageID)
    Else
      \ButtonList()\IconWidth          = 0
      \ButtonList()\IconHeight         = 0
    EndIf
   
    Protected XP.i
    Protected YP.i
    If \ButtonList()\Caption <> ""
      ; with caption (icon shifted up)
      XP.i = \ButtonList()\Width / 2 - \ButtonList()\IconWidth / 2
      YP.i = (\ButtonList()\Height * 0.8) / 2 - \ButtonList()\IconHeight / 2
    Else
      ; no caption (center icon)
      XP.i = \ButtonList()\Width / 2 - \ButtonList()\IconWidth / 2
      YP.i = \ButtonList()\Height / 2 - \ButtonList()\IconHeight / 2
    EndIf
    \ButtonList()\IconX      = XP.i
    \ButtonList()\IconY      = YP.i
   
    ; draw caption
    ; start drawing only for gathering the correct values for textwidth/height
    ; generate image values
    Protected MyFontID.i = LoadFont(#PB_Any, FontName.s, FontSize.i, FontStyle.i) ; load font in desired size
    StartDrawing(ImageOutput(\ButtonList()\ButtonImageID_draw))
   
      DrawingFont(FontID(MyFontID.i))
      If IconImageID.i <> 0
        ; text lowered
        XP.i = \ButtonList()\Width / 2 - TextWidth(Caption.s) / 2
        YP.i = \ButtonList()\Height * 0.75 - TextHeight(Caption.s) / 2
      Else
        ; text centered
        XP.i = \ButtonList()\Width / 2  - TextWidth(Caption.s) / 2
        YP.i = \ButtonList()\Height / 2 - TextHeight(Caption.s) / 2
      EndIf
      \ButtonList()\TextX = XP.i
      \ButtonList()\TextY = YP.i

    StopDrawing()
    FreeFont(MyFontID.i)
   
    ; create gadget
    Protected newGadgetID.i = ImageGadget(Gadget.i, PosX.i, PosY.i, \ButtonList()\Width, \ButtonList()\Height, ImageID(\ButtonList()\ButtonImageID_draw))
    If Gadget.i = #PB_Any
      \ButtonList()\GadgetID = newGadgetID.i
    Else
      \ButtonList()\GadgetID = Gadget.i
    EndIf
   
    rbutton_Redraw(\ButtonList()\GadgetID, 0)
   
  EndWith
 
  ProcedureReturn newGadgetID.i
 
EndProcedure

; Creates a new r-style button in horizontal mode (icon left from text).
; The size depends on the used background-image.
Procedure.i rbutton_CreateH(Gadget.i, WindowID.i, Caption.s, PosX.i, PosY.i, IconImageID.i = 0)
  Protected FontName.s, FontSize.i, FontColor.i, FontStyle.i, ShaddowColor.i
 
  With rButton
   
    If \FontName = "" : FontName.s = "Verdana": Else : FontName.s = \FontName: EndIf ; use defaults
    If \FontSize = 0  : FontSize.i = 16       : Else : FontSize.i = \FontSize: EndIf ; use defaults
   
    FontStyle.i    = \FontStyle
    FontColor.i    = rbutton_DimmColor(\FontColor, -10)
    ShaddowColor.i = rbutton_DimmColor(\FontColor, \ShaddowDimm - 10)
   
    ; load images, if needed
    If \rButtonImageID_normal = 0
      Debug "Need to call rbutton_Init() at first!"
      ProcedureReturn
    EndIf
    If \rButtonImageID_hover = 0
      Debug "Need to call rbutton_Init() at first!"
      ProcedureReturn
    EndIf
   
    ; prepare button and load images
    AddElement(\ButtonList())
   
    \ButtonList()\ButtonImageID_normal = \rButtonImageID_normal
    \ButtonList()\ButtonImageID_hover  = \rButtonImageID_hover
    \ButtonList()\IconImageID          = IconImageID.i
    \ButtonList()\X                    = PosX.i
    \ButtonList()\Y                    = PosY.i
    \ButtonList()\Width                = ImageWidth(\rButtonImageID_normal)
    \ButtonList()\Height               = ImageHeight(\rButtonImageID_normal)
    \ButtonList()\Caption              = Caption.s
    \ButtonList()\ButtonImageID_draw   = CreateImage(#PB_Any, \ButtonList()\Width, \ButtonList()\Height, 32)
    \ButtonList()\FontName             = \FontName
    \ButtonList()\FontSize             = \FontSize
    \ButtonList()\FontStyle            = \FontStyle
    \ButtonList()\FontColor            = \FontColor
    \ButtonList()\ShaddowDimm          = \ShaddowDimm
    \ButtonList()\WindowID             = WindowID.i
    If IconImageID.i <> 0
      \ButtonList()\IconWidth          = ImageWidth(\ButtonList()\IconImageID)
      \ButtonList()\IconHeight         = ImageHeight(\ButtonList()\IconImageID)
    Else
      \ButtonList()\IconWidth          = 0
      \ButtonList()\IconHeight         = 0
    EndIf
   
    Protected MyFontID.i = LoadFont(#PB_Any, FontName.s, FontSize.i, FontStyle.i) ; load font in desired size
    ; start drawing only for gathering the correct values for textwidth/height
    ; generate image values
    StartDrawing(ImageOutput(\ButtonList()\ButtonImageID_draw))
      DrawingFont(FontID(MyFontID.i))
   
      Protected XP.i
      Protected YP.i
      Protected IconSpace.i = \ButtonList()\IconWidth * 0.1
      If \ButtonList()\Caption <> ""
        ; with caption (icon shifted left)
        XP.i = \ButtonList()\Width / 2 - (\ButtonList()\IconWidth + TextWidth(Caption.s) + IconSpace.i) / 2
        YP.i = \ButtonList()\Height / 2 - \ButtonList()\IconHeight / 2
        ; take care about the left position of icon...
        If XP.i < #button_ShaddowWidth + \LineThickness
          XP.i = #button_ShaddowWidth + \LineThickness
        EndIf
      Else
        ; no caption (center icon)
        XP.i = \ButtonList()\Width / 2 - \ButtonList()\IconWidth / 2
        YP.i = \ButtonList()\Height / 2 - \ButtonList()\IconHeight / 2
      EndIf
      \ButtonList()\IconX      = XP.i
      \ButtonList()\IconY      = YP.i
     
      ; draw caption
      If IconImageID.i <> 0
        ; text right
        XP.i = \ButtonList()\IconX + \ButtonList()\IconWidth + IconSpace.i
        YP.i = \ButtonList()\Height / 2 - TextHeight(Caption.s) / 2
      Else
        ; text centered
        XP.i = \ButtonList()\Width / 2  - TextWidth(Caption.s) / 2
        YP.i = \ButtonList()\Height / 2 - TextHeight(Caption.s) / 2
      EndIf
      \ButtonList()\TextX = XP.i
      \ButtonList()\TextY = YP.i

    StopDrawing()
    FreeFont(MyFontID.i)
   
    ; create gadget
    Protected newGadgetID.i = ImageGadget(Gadget.i, PosX.i, PosY.i, \ButtonList()\Width, \ButtonList()\Height, ImageID(\ButtonList()\ButtonImageID_draw))
    If Gadget.i = #PB_Any
      \ButtonList()\GadgetID = newGadgetID.i
    Else
      \ButtonList()\GadgetID = Gadget.i
    EndIf
   
    rbutton_Redraw(\ButtonList()\GadgetID, 0)
   
  EndWith
 
  ProcedureReturn newGadgetID.i
 
EndProcedure

; Checks, if the mouse in the given window is over a r-style button.
; In that case, the button will get hover-effect.
; Simply add this to the event-loop of your window.
Procedure rbutton_CheckHover(WindowID.i)
  Static LastHighlightGadgetID.i
 
  Protected x.i
  Protected FoundSome.b = #False
 
  ; remove dead elements
  ForEach rButton\ButtonList()
    If Not IsGadget(rButton\ButtonList()\GadgetID)
      DeleteElement(rButton\ButtonList())
    EndIf
  Next
   
  For x.i = 0 To ListSize(rButton\ButtonList()) - 1
    SelectElement(rButton\ButtonList(), x.i)
   
    With rButton\ButtonList()
     
      If \WindowID = WindowID.i
        ; actualize gadget position information
        \X      = GadgetX(\GadgetID)
        \Y      = GadgetY(\GadgetID)
        \Width  = GadgetWidth(\GadgetID)
        \Height = GadgetHeight(\GadgetID)
       
        If rbutton_MouseOverGadget(WindowID.i, \GadgetID) = #True
          ; matching
          FoundSome.b = #True
          ; enable cursor symbol on this gadget
          If \Disabled = #False And \Hidden = #False
            rbutton_MakeCursorHand(\GadgetID) ; change current cursor to a hand
          EndIf
          If LastHighlightGadgetID.i <> \GadgetID
            ; remove old hover gadget
            Protected CurrentGadget.i = \GadgetID
            ; set state of new gadget
            rbutton_Redraw(CurrentGadget.i, 1)
            ; remove state of previous gadget
            If LastHighlightGadgetID.i <> 0
              rbutton_Redraw(LastHighlightGadgetID.i, 0)
            EndIf
            LastHighlightGadgetID.i = CurrentGadget.i
            Break
          EndIf
        EndIf
      EndIf
    EndWith
  Next
  If FoundSome.b = #False
    If LastHighlightGadgetID.i <> 0
      rbutton_Redraw(LastHighlightGadgetID.i, 0)
    EndIf
    LastHighlightGadgetID.i = 0
  EndIf
 
EndProcedure

; disable/enable a rbutton (State = #False -> enabled, State = #True -> disabled)
Procedure rbutton_Disable(rGadgetID.i, State.b)
  Protected Found.b = #False
 
  ForEach rButton\ButtonList()
    If rButton\ButtonList()\GadgetID = rGadgetID.i
      Found.b = #True
      Break
    EndIf
  Next
  If Found.b = #False
    Debug "rGadgetID " + Str(rGadgetID.i) + " not found (Disable)!"
    ProcedureReturn #False
  EndIf
 
  rButton\ButtonList()\Disabled = State.b
 
  DisableGadget(rGadgetID.i, State.b)
 
  rbutton_Redraw(rButton\ButtonList()\GadgetID, 0)
 
EndProcedure

; Hide or unhide a given rbutton (use this instead
; of HideGadget() function for rbutton gadgets).
Procedure rbutton_Hide(rGadgetID.i, State.b)
  Protected Found.b = #False
 
  ForEach rButton\ButtonList()
    If rButton\ButtonList()\GadgetID = rGadgetID.i
      Found.b = #True
      Break
    EndIf
  Next
  If Found.b = #False
    Debug "rGadgetID " + Str(rGadgetID.i) + " not found (Hide)!"
    ProcedureReturn #False
  EndIf
 
  rButton\ButtonList()\Hidden = State.b
 
  HideGadget(rGadgetID.i, State.b)
 
EndProcedure

; Determine the maximum space needed for the buttons. You can give multiple captions
; to the routine, if you divide the captions with the PIPE character (|).
; You will get the maximum button width needed.
; This makes only sense, if you are using the rbutton_Init_OwnerDrawn() with this value as width.
Procedure.i rbutton_GetButtonWidth(Captions.s)
  Static TextImage
  Protected MaxWidth.i = 0
  Protected Width.i = 0
  Protected Caption.s = ""
 
  If rButton\FontName = ""
    Debug "You can not call rbutton_GetButtonWidth() before calling rbutton_SetFont()!"
    ProcedureReturn 0
  EndIf
 
  Protected MyFontID.i = LoadFont(#PB_Any, rButton\FontName, rButton\FontSize, rButton\FontStyle) ; load font in desired size
  If IsImage(TextImage) = 0
    TextImage = CreateImage(#PB_Any, 500, 30)
  EndIf
 
  StartDrawing(ImageOutput(TextImage))
  DrawingFont(FontID(MyFontID.i))
  Protected Idx = 0
  Repeat
    Idx = Idx + 1
    Caption.s = StringField(Captions.s, Idx, "|")
    Width.i = TextWidth(Caption.s) + (#button_ShaddowWidth * #button_ScaleFactor) + #button_ScaleFactor
    If Width.i > MaxWidth.i
      MaxWidth.i = Width.i
    EndIf
  Until Caption.s = ""
 
  StopDrawing()
 
  ProcedureReturn MaxWidth.i
EndProcedure


Example code:
Code:
; TEST AND EXAMPLE CODE
XIncludeFile "rbutton_include.pbi"

OpenWindow(0, 100, 200, 300, 400, "rButton test window", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget)
SetWindowColor(0, RGB(255, 255, 255))

; rbutton_Init(LoadImage(#PB_Any, "regButton_normal.png"), LoadImage(#PB_Any, "regButton_hover.png"))
rbutton_SetFont("Georgia", 9, 0, RGB(255,255,255), -120)
;Define ButtonWidth.i = rbutton_GetButtonWidth("display|print|disabled");
rbutton_Init_OwnerDrawn(120, 120, GetWindowColor(0), RGBA(214,226,236,255), RGBA(120,158,191,255), RGBA(255,255,255,255), RGBA(90,167,255,255),15, 2)

Define regDisplay.i  = rbutton_Create(#PB_Any, 0, "display", 10, 10, LoadImage(#PB_Any, "display.png"))
Define regPrint.i    = rbutton_Create(#PB_Any, 0, "print (disabled)", 160, 10, LoadImage(#PB_Any, "print.png"))
Define regDisplayD.i = rbutton_Create(#PB_Any, 0, "no image", 10, 150, 0)
Define regNoCaption.i= rbutton_Create(#PB_Any, 0, "", 160, 150, LoadImage(#PB_Any, "print.png"))

rbutton_SetFont("Arial", 9, #PB_Font_Bold | #PB_Font_Italic, RGB(255,255,255), -120)
rbutton_Init_OwnerDrawn(80, 30, GetWindowColor(0), RGBA(214,236,226,255), RGBA(120,191,158,255), RGBA(255,255,255,255), RGBA(60,225,137,255),5, 2)
Define regSmall1.i = rbutton_Create(#PB_Any, 0, "yes", 10, 280, 0)
Define regSmall2.i = rbutton_Create(#PB_Any, 0, "no", 105, 280, 0)
rbutton_Init_OwnerDrawn(80, 30, GetWindowColor(0), RGBA(236,214,214,255), RGBA(191,120,120,255), RGBA(255,255,255,255), RGBA(225,60,60,255),5, 2)
Define regSmall3.i = rbutton_Create(#PB_Any, 0, "cancel", 200, 280, 0)

rbutton_SetFont("Courier New", 16, #PB_Font_Bold, RGB(40,30,50), 150)
rbutton_Init_OwnerDrawn(130, 70, GetWindowColor(0), RGBA(206,200,216,255), RGBA(120,100,158,255), RGBA(255,255,255,255), RGBA(100,90,140,255),10, 2)
Define Printer.i = LoadImage(#PB_Any, "print.png")
ResizeImage(Printer.i, 28, 28)
Define regHoriz1.i = rbutton_CreateH(#PB_Any, 0, "print", 10, 320, Printer.i)
Define regHoriz1.i = rbutton_CreateH(#PB_Any, 0, "OK", 150, 320, Printer.i)

rbutton_Disable(regPrint.i, #True)

Define Quit.i = 0

Repeat
  Define Event.i = WaitWindowEvent()

  If Event.i = #PB_Event_CloseWindow  ; If the user has pressed on the close button
    Quit.i = 1
  EndIf
 
  If Event.i = #PB_Event_Gadget
    If EventGadget() = regSmall3.i
      Quit.i = 1
    EndIf
  EndIf
 
  rbutton_CheckHover(0)

Until Quit.i = 1

End


There are two images needed for the above example:
- display.png
- print.png

You may find some on iconfinder.com.

Best,

Kukulkan


Last edited by Kukulkan on Mon Jul 16, 2012 3:23 pm, edited 2 times in total.

Top
 Profile  
Reply with quote  
 Post subject: Re: Owner-drawn buttons
PostPosted: Wed Feb 15, 2012 11:10 am 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Tue Jan 05, 2010 10:35 am
Posts: 119
Hi, Kukulkan
very nice thank you for sharing
can be : yes = green, orange = cancel , No = red
goodbye


Top
 Profile  
Reply with quote  
 Post subject: Re: Owner-drawn buttons
PostPosted: Wed Feb 15, 2012 11:39 am 
Offline
Addict
Addict
User avatar

Joined: Sat Oct 17, 2009 10:51 pm
Posts: 1387
Location: Nashville
Absolutely gorgeous, Kukulkan! Excellent job!

Thank you VERY much for sharing this.


Top
 Profile  
Reply with quote  
 Post subject: Re: Owner-drawn buttons
PostPosted: Wed Feb 15, 2012 11:47 am 
Offline
Addict
Addict
User avatar

Joined: Mon Jun 06, 2005 2:35 pm
Posts: 1259
Location: germany
kernadec wrote:
can be : yes = green, orange = cancel , No = redgoodbye

Yes, no problem. Simply call rbutton_Init_OwnerDrawn() with orange colors before creating the "cancel" button. Theoretical, every button can have a new border-radius, color, font etc. I try'd to be very carefull about ressource usage. We have no problems with about 20 buttons on a window here.

Kukulkan


Top
 Profile  
Reply with quote  
 Post subject: Re: Owner-drawn buttons
PostPosted: Wed Feb 15, 2012 12:00 pm 
Offline
Addict
Addict
User avatar

Joined: Mon Jun 06, 2005 2:35 pm
Posts: 1259
Location: germany
How we use this on Windows and Linux:

Image

The optimal width for the buttons is calculated using rbutton_GetButtonWidth() provided with all captions. This works great with different languages (we currently support english, german and french).

Kukulkan


Top
 Profile  
Reply with quote  
 Post subject: Re: Owner-drawn buttons
PostPosted: Thu Feb 16, 2012 9:26 am 
Offline
Addict
Addict
User avatar

Joined: Mon May 14, 2007 2:13 am
Posts: 979
Location: Darling River
I like it. :)

_________________
PureBasic Rocks! Even More! And More!
PureBasic 5, Now We're Really Rockin!


Top
 Profile  
Reply with quote  
 Post subject: Re: Owner-drawn buttons
PostPosted: Thu Feb 16, 2012 12:05 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Fri Oct 06, 2006 3:57 pm
Posts: 572
Location: England
Stoopid question - but could you give en example of handling clicking on a button ??

cheers


Top
 Profile  
Reply with quote  
 Post subject: Re: Owner-drawn buttons
PostPosted: Thu Feb 16, 2012 3:04 pm 
Offline
Addict
Addict
User avatar

Joined: Sun Nov 05, 2006 11:42 pm
Posts: 4844
Location: Lyon - France
Nice job, thanks for sharing 8)

_________________
ImageThe happiness is a road...
Not a destination


Top
 Profile  
Reply with quote  
 Post subject: Re: Owner-drawn buttons
PostPosted: Thu Feb 16, 2012 3:25 pm 
Offline
Addict
Addict
User avatar

Joined: Mon Jun 06, 2005 2:35 pm
Posts: 1259
Location: germany
captain_skank wrote:
Stoopid question - but could you give en example of handling clicking on a button ??

You can use it like any other button. You can use #PB_Any while creation (like the example) or fixed gadget IDs. You can use all events that a image-gadget would do (in fact, this are simple image gadgets).

Kukulkan


Top
 Profile  
Reply with quote  
 Post subject: Re: Owner-drawn buttons
PostPosted: Fri Feb 17, 2012 3:00 pm 
Offline
PureBasic Expert
PureBasic Expert
User avatar

Joined: Fri Apr 25, 2003 4:51 pm
Posts: 2809
Location: Portugal, Lisbon
Works on x64 with no problems.
The only thing missing is key navigation, but that can be achieved by extra code!

Thanks for this one!

_________________
Elevator Maintenance: http://central-elevadores.pt
Good web hosting![/size]


Top
 Profile  
Reply with quote  
 Post subject: Re: Owner-drawn buttons
PostPosted: Sat Apr 14, 2012 2:34 pm 
Offline
Addict
Addict
User avatar

Joined: Mon Jun 06, 2005 2:35 pm
Posts: 1259
Location: germany
Hello,

I just updated the code on the first page.

New:
- rbutton_CreateH() makes a horizontal button (icon left beside the caption)
- now works on multiple windows
- reduced initial memory usage

Important: The rbutton_Create() syntax changed somewhat because you need to give the WindowID you are drawing on, too.

Kukulkan


Top
 Profile  
Reply with quote  
 Post subject: Re: Owner-drawn buttons
PostPosted: Fri Apr 20, 2012 4:59 am 
Offline
User
User

Joined: Fri Aug 14, 2009 2:26 pm
Posts: 58
Location: Afghanistan
very nice and excellent ,Please update if it can...merci :D


Top
 Profile  
Reply with quote  
 Post subject: Re: Owner-drawn buttons
PostPosted: Mon May 14, 2012 3:04 am 
Offline
Enthusiast
Enthusiast

Joined: Thu Feb 16, 2006 1:41 am
Posts: 180
Location: New Zealand
Very nice, Kukulkan, thanks for sharing, this makes for a very slick-looking GUI.

_________________
Win8.1, PB5.x, okayish CPU, onboard video card, fuzzy monitor (or is that my eyesight?)
"When the facts change, I change my mind" - John Maynard Keynes


Top
 Profile  
Reply with quote  
 Post subject: Re: Owner-drawn buttons
PostPosted: Mon May 14, 2012 10:57 pm 
Offline
PureBasic Team
PureBasic Team
User avatar

Joined: Fri Apr 25, 2003 6:14 pm
Posts: 1872
Location: Germany (Saxony, Deutscheinsiedel)
Looks very nice! :D
Any chance for a MacOS adaption?

_________________
Bye,
...André
(PureBasicTeam::Docs & Support - PureArea.net | Order:: PureBasic | PureVisionXP)


Top
 Profile  
Reply with quote  
 Post subject: Re: Owner-drawn buttons
PostPosted: Mon May 14, 2012 11:37 pm 
Offline
Addict
Addict
User avatar

Joined: Tue Oct 09, 2007 2:15 am
Posts: 1151
The only thing to convert is the "rbutton_MakeCursorHand(GadgetID.i)" procedure...

If you know, how to change the mousepointer... so it's no problem... or let the pointer like it is... ;)

_________________
PureBasic 5.72 LTS (Windows x86/x64) | Windows10 Pro x64 | Z370 Extreme4 | i7 8770k | 64GB RAM | iChill GeForce RTX 2080 Super | HAF XF Evo​​
English is not my native language... (I often use DeepL to translate my texts.)


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 24 posts ]  Go to page 1, 2  Next

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 14 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye