Flat button with border when hovered ?

Just starting out? Need help? Post your questions and find answers here.
User avatar
Blue
Addict
Addict
Posts: 964
Joined: Fri Oct 06, 2006 4:41 am
Location: Canada

Re: Flat button with border when hovered ?

Post by Blue »

I think i understand the flow of the code... :shock:
So, "Really simple" is exactly what i said to myself too !

But when the drawing mode is changed from Default to Outlined in FlatBorderButtonEvents() or FlatBorderButtonDraw(), the buttons end up with a colored background (not just a border), plus they do no longer revert to their original state once they've been clicked.

So i still can't figure out how to make them start exactly as they currently are, with a border...
PB Forums : Proof positive that 2 heads (or more...) are better than one :idea:
User avatar
Blue
Addict
Addict
Posts: 964
Joined: Fri Oct 06, 2006 4:41 am
Location: Canada

Re: Flat button with border when hovered ?

Post by Blue »

Ok, after trying a zillion things, now i finally get it.

In order to start off with a bordered button, case 0 in proc FlatBorderButtonDraw() needs an additional box :

Code: Select all

  Case 0
      Box(0,0,OutputWidth(),OutputHeight(),#Black)                    ; for a black border 
      Box(1,1,OutputWidth()-2,OutputHeight()-2,*p\BackGroundColor)    ; the inner part of the button 
All along, I thought changing the Drawing mode to Outlined was the required change, but no.

Again, i bow deeply before Bisonte for a great piece of code. :D
Ah, the beautiful buttons one can now draw....

Kudos to charvista for raising a very interesting topic.
Last edited by Blue on Sun Apr 14, 2013 1:28 pm, edited 1 time in total.
PB Forums : Proof positive that 2 heads (or more...) are better than one :idea:
User avatar
charvista
Addict
Addict
Posts: 949
Joined: Tue Sep 23, 2008 11:38 pm
Location: Belgium

Re: Flat button with border when hovered ?

Post by charvista »

Blue wrote:Kudos to charvista for raising a very interesting topic.
:wink:
- Windows 11 Home 64-bit
- PureBasic 6.10 LTS (x64)
- 64 Gb RAM
- 13th Gen Intel(R) Core(TM) i9-13900K 3.00 GHz
- 5K monitor with DPI @ 200%
User avatar
Bisonte
Addict
Addict
Posts: 1305
Joined: Tue Oct 09, 2007 2:15 am

Re: Flat button with border when hovered ?

Post by Bisonte »

Blue wrote:Again, i flip my hat over and before Bisonte for a great piece of code.
The price goes not to me, it goes to my teacher ....

I learn it from the best : The PureBasic Community :!:
PureBasic 6.21 (Windows x64) | Windows 11 Pro | AsRock B850 Steel Legend Wifi | R7 9800x3D | 64GB RAM | RTX 5080 | ThermaltakeView 270 TG ARGB | build by vannicom​​
English is not my native language... (I often use DeepL.)
User avatar
charvista
Addict
Addict
Posts: 949
Joined: Tue Sep 23, 2008 11:38 pm
Location: Belgium

Re: Flat button with border when hovered ?

Post by charvista »

Blue wrote: Case 0
Box(0,0,OutputWidth(),OutputHeight(),#Black) ; for a black border
Box(1,1,OutputWidth()-2,OutputHeight()-2,*p\BackGroundColor) ; the inner part of the button
Very good, Blue! I have included this in my code as an optional argument (more flexiblity in the colors). Thank you!
I have also modified this original Bisonte's part:

Code: Select all

        x = (OutputWidth()/2) - (TextWidth(*p\Text)/2)
        y = (OutputHeight()/2) - (TextHeight(*p\Text)/2)
        DrawingMode(#PB_2DDrawing_Default|#PB_2DDrawing_Transparent)
        DrawText(x,y,*p\Text,*p\TextColor)
with this:

Code: Select all

                    If *p\Align=0; Horizontal align center
                        x=(OutputWidth()/2)-(TextWidth(*p\Text)/2)
                    ElseIf *p\Align>0; Horizontal align left
                        x=*p\Align
                    Else; (negative) Horizontal align right
                        x=OutputWidth()-TextWidth(*p\Text)+*p\Align
                    EndIf
                    y=(OutputHeight()/2)-(TextHeight(*p\Text)/2)-1; Vertical alignment always centered in its height
                    DrawingMode(#PB_2DDrawing_Default|#PB_2DDrawing_Transparent)
                    DrawText(x,y,*p\Text,*p\TextColor)
to adjust alignment positioning... Negative values will right-align the text, which might be nicer in some cases.
Yes, Bisonte's code is really fantastic! :D
Edit: Bisonte, then you had an excellent teacher!!! :D
- Windows 11 Home 64-bit
- PureBasic 6.10 LTS (x64)
- 64 Gb RAM
- 13th Gen Intel(R) Core(TM) i9-13900K 3.00 GHz
- 5K monitor with DPI @ 200%
User avatar
charvista
Addict
Addict
Posts: 949
Joined: Tue Sep 23, 2008 11:38 pm
Location: Belgium

Re: Flat button with border when hovered ?

Post by charvista »

I have to post the whole code, because I have added the Align.i variable, so the snippet in my previous post won't work, as it is incomplete.
Here is the complete procedure code:

Code: Select all

Prototype FlatPrototype(Pointer,Event=0)

Structure flat_border_button_datas
    Gadget.i
    Drawing.flatprototype
    Text.s
    Align.i
    TextColor.i
    InnerColor.i
    BorderColor.i
    BackGroundColorInner.i
    BackGroundColorBorder.i
    Font.i
    ExtraData.i
EndStructure
;*================================================================================================================================*
Procedure zFlatButtonGadget_Draw(*p.flat_border_button_datas,Event=0)
    Protected x,y,th
    If *p
        If IsGadget(*p\Gadget)
            If StartDrawing(CanvasOutput(*p\Gadget))
                    Select Event
                        Case 0
                            DrawingMode(#PB_2DDrawing_Default)
                            Box(0,0,OutputWidth(),OutputHeight(),*p\BackGroundColorBorder)
                            Box(1,1,OutputWidth()-2,OutputHeight()-2,*p\BackGroundColorInner)
                        Case 1
                            DrawingMode(#PB_2DDrawing_Default)
                            Box(0,0,OutputWidth(),OutputHeight(),*p\BorderColor)
                            Box(1,1,OutputWidth()-2,OutputHeight()-2,*p\InnerColor)
                    EndSelect
                    If IsFont(*p\Font)
                        DrawingFont(FontID(*p\Font))
                    EndIf
                    If *p\Align=0; Horizontal align center
                        x=(OutputWidth()/2)-(TextWidth(*p\Text)/2)
                    ElseIf *p\Align>0; Horizontal align left
                        x=*p\Align
                    Else; (negative) Horizontal align right
                        x=OutputWidth()-TextWidth(*p\Text)+*p\Align
                    EndIf
                    y=(OutputHeight()/2)-(TextHeight(*p\Text)/2)-1; Vertical alignment always centered in its height
                    DrawingMode(#PB_2DDrawing_Default|#PB_2DDrawing_Transparent)
                    DrawText(x,y,*p\Text,*p\TextColor)
                StopDrawing()
            EndIf
        EndIf
    EndIf
EndProcedure
;*================================================================================================================================*
Procedure zFlatButtonGadget(Gadget.i,X.i,Y.i,W.i,H.i,Text.s,Align.i=0,
                             TextColor.i=$000000,BackGroundColorBorder.i=$F0F0F0,BackGroundColorInner=$F0F0F0,
                             InnerColor.i=$FFE0C2,BorderColor.i=$FF9933,FontNumber.i=152)
    Protected *p.flat_border_button_datas=AllocateMemory(SizeOf(flat_border_button_datas))
    Protected ID
    
    If Not *p : ProcedureReturn #False : EndIf
    InitializeStructure(*p,flat_border_button_datas)
    
    ID=CanvasGadget(Gadget,X,Y,W,H)
    
    If Gadget=#PB_Any : Gadget=ID : EndIf
    
    SetGadgetData(Gadget,*p)
    
    *p\Gadget=Gadget
    *p\Text=Text
    *p\TextColor=TextColor
    *p\Align=Align
    *p\BorderColor=BorderColor
    *p\BackGroundColorBorder=BackGroundColorBorder
    *p\BackGroundColorInner=BackGroundColorInner
    *p\InnerColor=InnerColor
    *p\Font=_F(FontNumber,0)
    *p\Drawing=@zFlatButtonGadget_Draw()
    *p\Drawing(*p,0)
    ProcedureReturn ID    
EndProcedure
and you have to substitute your own font:

Code: Select all

*p\Font=_F(FontNumber,0)
- Windows 11 Home 64-bit
- PureBasic 6.10 LTS (x64)
- 64 Gb RAM
- 13th Gen Intel(R) Core(TM) i9-13900K 3.00 GHz
- 5K monitor with DPI @ 200%
User avatar
Blue
Addict
Addict
Posts: 964
Joined: Fri Oct 06, 2006 4:41 am
Location: Canada

Re: Flat button with border when hovered ?

Post by Blue »

Yes, that's what so great about Bisonte's code : You can adjust it very easily to get interesting effects.
And all that without having to keep track of a zillion different possible side effects.

For instance, where Bisonte had 2 cases in the drawing proc, i use 3 : normal (0), hover(1) and pressed (2).
Also, by offsetting the boxes 2 or 3 pixels over, for the various cases, you can have colored buttons with a press-down action as pleasant as the system's.

Another change that's significantly useful is refining the events that trigger the redrawing of the buttons.
Where Bisonte offered the following...

Code: Select all

  Select EventType
      Case #PB_EventType_MouseEnter, #PB_EventType_MouseMove, #PB_EventType_LeftButtonDown, #PB_EventType_RightButtonDown
         *p\Draw(*p, 1)
      Default
         *p\Draw(*p, 0)
  EndSelect            
you could do the following, adding flexibility to the operation :

Code: Select all

   Select EventType
       Case #PB_EventType_MouseEnter, #PB_EventType_LeftButtonUp
           *p\Draw(*p, #hover)
       Case #PB_EventType_MouseLeave
           *p\Draw(*p, #Normal)
       Case #PB_EventType_LeftButtonDown
           *p\Draw(*p, #pressed)
   EndSelect            
When i think of all the complicated spaghetti code i wrote to get a hovering effect on buttons :oops: , i feel humbled by Bisonte's code. So clear and manageable.

Where were you Bisonte when we needed you for the last 6 years ??? :D
PB Forums : Proof positive that 2 heads (or more...) are better than one :idea:
User avatar
charvista
Addict
Addict
Posts: 949
Joined: Tue Sep 23, 2008 11:38 pm
Location: Belgium

Re: Flat button with border when hovered ?

Post by charvista »

Thank you for the update, Blue! I haved implemented it too!
When pressed, the button now can have a different color and border! Super!
New idea: when pressed, you can even easily draw the text 1 or 2 pixels to the right and/or lower, to give a more professional effect (with shadow?)!! As well a parameter to make the shifting optional!
Yes, there are endless possibilities.....
:wink:
- Windows 11 Home 64-bit
- PureBasic 6.10 LTS (x64)
- 64 Gb RAM
- 13th Gen Intel(R) Core(TM) i9-13900K 3.00 GHz
- 5K monitor with DPI @ 200%
User avatar
Blue
Addict
Addict
Posts: 964
Joined: Fri Oct 06, 2006 4:41 am
Location: Canada

Re: Flat button with border when hovered ?

Post by Blue »

If i may, i'd like to post a complete example

Code: Select all

  >>> Code removed 
  >>>  replaced by the example in the following page
changes :
- replaced the #Normal constant by #buttonNormal because #Normal is already pre-defined in PureBasic
- the other 2 constants were then renamed along this pattern
- the #buttonNormal was not used in every instance where it was required
Last edited by Blue on Tue Apr 16, 2013 8:56 pm, edited 7 times in total.
PB Forums : Proof positive that 2 heads (or more...) are better than one :idea:
User avatar
Blue
Addict
Addict
Posts: 964
Joined: Fri Oct 06, 2006 4:41 am
Location: Canada

Re: Flat button with border when hovered ?

Post by Blue »

Charvista, post an example of the modifications you've implemented.

This is the most fun i've had in a long time.
All of a sudden, i've learned an awful lot of new and useful things in a very short time.

In spite of all the snow on the front lawn, Spring must have arrived... How else can this be explained ? :)
Last edited by Blue on Tue Apr 16, 2013 8:58 pm, edited 1 time in total.
PB Forums : Proof positive that 2 heads (or more...) are better than one :idea:
User avatar
Bisonte
Addict
Addict
Posts: 1305
Joined: Tue Oct 09, 2007 2:15 am

Re: Flat button with border when hovered ?

Post by Bisonte »

a litte improvement ...
that "marks" the last leftclicked gadget.

Code: Select all

EnableExplicit
;
Prototype flatprototype(Pointer, Event = 0)
;
Structure flat_border_button_datas
 
  Gadget.i
  Drawing.flatprototype
  Text.s
  TextColor.i
  InnerColor.i
  BorderColor.i
  BackGroundColor.i
  Font.i
  ExtraData.i
 
EndStructure
;
Global lastgadget.i
;
Procedure FlatBorderButtonDraw(*p.flat_border_button_datas, Event = 0)
 
  Protected x, y, th
 
  If *p
    If IsGadget(*p\Gadget)

      If StartDrawing(CanvasOutput(*p\Gadget))
        Select Event
          Case 0
            ; »»» The New Segment
            DrawingMode(#PB_2DDrawing_Default)
            If lastgadget = *p\Gadget
              Box(0,0,OutputWidth(),OutputHeight(),*p\BorderColor) 
              Box(1,1,OutputWidth()-2,OutputHeight()-2,*p\BackGroundColor)                  
            Else
              Box(0,0,OutputWidth(),OutputHeight(),*p\BackGroundColor)
            EndIf
            ; »»» The New Segment Ends
          Case 1
            DrawingMode(#PB_2DDrawing_Default)
            Box(0,0,OutputWidth(),OutputHeight(),*p\BorderColor) 
            Box(1,1,OutputWidth()-2,OutputHeight()-2,*p\InnerColor)           
        EndSelect
                   
        If IsFont(*p\Font)
          DrawingFont(FontID(*p\Font))
        EndIf
        x = (OutputWidth()/2) - (TextWidth(*p\Text)/2)
        y = (OutputHeight()/2) - (TextHeight(*p\Text)/2)
        DrawingMode(#PB_2DDrawing_Default|#PB_2DDrawing_Transparent)
        DrawText(x,y,*p\Text,*p\TextColor)
       
        StopDrawing()
      EndIf
    EndIf
  EndIf
 
EndProcedure
;
Procedure FlatBorderButton(Gadget, x, y, Width, Height, Text.s, TextColor, BackGroundColor, InnerColor, BorderColor, Font)
 
  Protected *p.flat_border_button_datas = AllocateMemory(SizeOf(flat_border_button_datas))
  Protected ID
 
  If Not *p : ProcedureReturn #False : EndIf
  InitializeStructure(*p, flat_border_button_datas)
 
  ID = CanvasGadget(Gadget, x, y, Width, Height)
 
  If Gadget = #PB_Any : Gadget = ID : EndIf
 
  SetGadgetData(Gadget, *p)
 
  *p\Gadget = Gadget
  *p\Text   = Text
  *p\BorderColor = BorderColor
  *p\BackGroundColor = BackGroundColor
  *p\InnerColor = InnerColor
  *p\Font = Font
  *p\Drawing = @FlatBorderButtonDraw()
 
  *p\Drawing(*p, 0)
  
  ProcedureReturn ID
 
EndProcedure
;
Procedure FlatBorderButtonEvents(Gadget, Event, EventType)
 
  Protected *p.flat_border_button_datas
  Protected *q.flat_border_button_datas ; »»» need to declare the last active gadget
  
  If IsGadget(Gadget)
    *p = GetGadgetData(Gadget)
    If *p
      If Event = #PB_Event_Gadget
        Select EventType
          Case #PB_EventType_MouseEnter, #PB_EventType_MouseMove, #PB_EventType_RightButtonDown
            *p\Drawing(*p, 1)
            
          Case #PB_EventType_LeftButtonDown ; »»» declares the lastgadget to the new click and delete the old
            If IsGadget(lastgadget)
              *q = GetGadgetData(lastgadget)
              lastgadget = *p\Gadget
              If *q
                *q\Drawing(*q, 0)
              EndIf
            EndIf
            lastgadget = *p\Gadget
            *p\Drawing(*p, 1)
          
          Default
            *p\Drawing(*p, 0)
        EndSelect   
        
      EndIf
    EndIf
  EndIf
   
EndProcedure
;
DisableExplicit

OpenWindow(0,200,300,800,600,"TestWindow")

Font = LoadFont(#PB_Any, "Segoe UI", 9)

FlatBorderButton(1, 20, 25, 300, 25, "Printer", 0, $F0F0F0, $FFE0C2, $FF9933, Font)
FlatBorderButton(2, 20, 50, 300, 25, "Computer", 0, $F0F0F0, $FFE0C2, $FF9933, Font)
FlatBorderButton(3, 20, 75, 300, 25, "Mouse", 0, $F0F0F0, $FFE0C2, $FF9933, Font)
FlatBorderButton(4, 20, 100, 300, 25, "Keyboard", 0, $F0F0F0, $FFE0C2, $FF9933, Font)
FlatBorderButton(5, 20, 125, 300, 25, "Hard Disk", 0, $F0F0F0, $FFE0C2, $FF9933, Font)

*p.flat_border_button_datas

Repeat
  Event = WaitWindowEvent()
 
  Select Event
    Case #PB_Event_LeftClick ; »»» need to delete the last mark if click somewhere in window
      If IsGadget(lastgadget)
        *p = GetGadgetData(lastgadget)
        If *p
          lastgadget = -1
          *p\Drawing(*p, 0)
        EndIf
      EndIf      
      lastgadget = -1 ; »»» make sure that no gadget can have this number
      
    Case #PB_Event_Gadget
      FlatBorderButtonEvents(EventGadget(), Event, EventType())
      Select EventType()
        Case #PB_EventType_LeftClick
          Select EventGadget()
            Case 1
              Debug "Click on Printer"
            Case 2
              Debug "Click on Computer"
            Case 3
              Debug "Click on Mouse"
            Case 4
              Debug "Click on Keyboard"
            Case 5
              Debug "Click on HardDisk"
          EndSelect         
      EndSelect
     
    Case #PB_Event_CloseWindow
      Quit = 1
     
  EndSelect
 
Until Quit > 0 
PureBasic 6.21 (Windows x64) | Windows 11 Pro | AsRock B850 Steel Legend Wifi | R7 9800x3D | 64GB RAM | RTX 5080 | ThermaltakeView 270 TG ARGB | build by vannicom​​
English is not my native language... (I often use DeepL.)
User avatar
em_uk
Enthusiast
Enthusiast
Posts: 366
Joined: Sun Aug 08, 2010 3:32 pm
Location: Manchester UK

Re: Flat button with border when hovered ?

Post by em_uk »

It's quite amusing really. Back when I started programming on the PC & Amiga the buttons looked like this, back then we tried to make them look 3D.

Years after 3D has been perfected, we are moving back to flat looking buttons :)
----

R Tape loading error, 0:1
User avatar
Blue
Addict
Addict
Posts: 964
Joined: Fri Oct 06, 2006 4:41 am
Location: Canada

Re: Flat button with border when hovered ?

Post by Blue »

em_uk wrote:It's quite amusing really [...] Years after 3D has been perfected, we are moving back to flat looking buttons :)
+1 :D Excellent observation.
Same goes for Operating systems : witness the new old look of Windows 8 !

I think i finally understand the meaning of "Back to the Future".
PB Forums : Proof positive that 2 heads (or more...) are better than one :idea:
davido
Addict
Addict
Posts: 1890
Joined: Fri Nov 09, 2012 11:04 pm
Location: Uttoxeter, UK

Re: Flat button with border when hovered ?

Post by davido »

Flat, Maybe.

Nice Work. Looks great from here. :D
DE AA EB
User avatar
charvista
Addict
Addict
Posts: 949
Joined: Tue Sep 23, 2008 11:38 pm
Location: Belgium

Re: Flat button with border when hovered ?

Post by charvista »

Thank you Bisonte, for this amazing improvement. In fact, I have done this too, but outside of the procedure. But doing it inside the procedure is indeed a lot more convenient!
Your code has been assimilated. Resistance is futile! :mrgreen:
em_uk wrote:Years after 3D has been perfected, we are moving back to flat looking buttons :)
I am also programming things inspired from Windows 3.11.... and even from IBM AS/400.
So yes, "retro" to recreate old things with newest technologies, that's "nostalgia".
And yes, I agree with Blue, for calling that "Back to the Future"!

But "Flat" is not always good. In Windows 8, the scrollbars are hard to find, because there is too few contrast. I hope Windows 9 will go back to Windows XP or 2000-style for the scrollbars and ListIconGadget's titles, where the contrast was perfect and nice looking.
- Windows 11 Home 64-bit
- PureBasic 6.10 LTS (x64)
- 64 Gb RAM
- 13th Gen Intel(R) Core(TM) i9-13900K 3.00 GHz
- 5K monitor with DPI @ 200%
Post Reply