Add Buttons to Windows Title Bar(Windows)

Share your advanced PureBasic knowledge/code with the community.
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4946
Joined: Sun Apr 12, 2009 6:27 am

Add Buttons to Windows Title Bar(Windows)

Post by RASHAD »

You need 2 images
state1.bmp 24 x 24 pixel to represent the button in normal state
state2.bmp 24 x 24 pixel to represent the button in hover state

You can make it 3 state button
Tested with XP SP2 & Win 7 x64 PB x86 4.51

Code: Select all

Global x,y,buttonW,buttonH,borderW


Procedure WndProc(hwnd, uMsg, wParam, lParam)

      GetWindowRect_(WindowID(1),r.RECT)
      x = r\right - (buttonW*5) - borderW   ;5 = for Max & Restore & Min and 2 more buttons
      y = r\top
      If OSVersion() <= #PB_OS_Windows_XP
        y = y + 5
      Else
        x = x + 10
      EndIf
      result = #PB_ProcessPureBasicEvents 

 Select uMsg
   
        Case #WM_NOTIFY     
        
        Case #WM_GETMINMAXINFO     
            *pMinMax.MINMAXINFO = lParam
            *pMinMax\ptMinTrackSize\x=buttonW*5
        
      
        Case #WM_SIZE,#WM_MOVE,#WM_PAINT
           If GetWindowState(1) = #PB_Window_Maximize
              ResizeWindow(2,x,y+4,buttonW*2,buttonH)    
           Else
               ResizeWindow(2,x,y,buttonW*2,buttonH) 
           EndIf
             
   EndSelect
   
  ProcedureReturn result 
EndProcedure

LoadImage(0, "state1.bmp")              ;24 x 24 pixel    Button state 1
LoadImage(1, "state2.bmp")              ;24 x 24 pixel    Button state 2

buttonW = GetSystemMetrics_(#SM_CXSIZE)
buttonH = GetSystemMetrics_(#SM_CYSIZE)
borderW = GetSystemMetrics_(#SM_CXBORDER)

OpenWindow(1,0,0,600,400,"Add Button to Title Bar", #PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget|#PB_Window_SizeGadget|#PB_Window_ScreenCentered)
OpenWindow(2,0,0,buttonW*2,buttonH,"",#WS_POPUP,WindowID(1))
SetWindowColor(2,#Red)
SetWindowLong_(WindowID(2),#GWL_EXSTYLE,GetWindowLong_(WindowID(2),#GWL_EXSTYLE)|#WS_EX_LAYERED)
SetLayeredWindowAttributes_(WindowID(2),#Red,0,#LWA_COLORKEY)
ImageGadget(10,2,0,30,20,ImageID(0))
ImageGadget(11,28,0,30,20,ImageID(0))

SetWindowCallback(@WndProc())
SetActiveWindow(1)

Repeat
  Select WaitWindowEvent()
      
      Case #PB_Event_CloseWindow
           Q = 1
      
      Case #PB_Event_Gadget
          Select EventGadget()
            Case 10
              Debug "Button 10 Pressed"

            Case 11
              Debug "Button 11 Pressed"

           EndSelect
           SetActiveWindow(1)
           
      Case #WM_MOUSEMOVE
         GetCursorPos_(@p.POINT)
         If p\x >= x+5 And p\x <= x+30 And p\y >= y+4 And p\y <=y+25
           SetGadgetState(10,ImageID(1))
         Else
           SetGadgetState(10,ImageID(0))
         EndIf
         If p\x >= x+35 And p\x <= x+55 And p\y >= y+4 And p\y <=y+25
           SetGadgetState(11,ImageID(1))
         Else
           SetGadgetState(11,ImageID(0))
         EndIf
           
  EndSelect 
Until Q =1
End

Egypt my love
User avatar
electrochrisso
Addict
Addict
Posts: 989
Joined: Mon May 14, 2007 2:13 am
Location: Darling River

Re: Add Buttons to Windows Title Bar(Windows)

Post by electrochrisso »

Nice one RASHAD, I am now pretty well clued up on Title Bar Buttons. :D
PureBasic! Purely the best 8)
User avatar
Rook Zimbabwe
Addict
Addict
Posts: 4322
Joined: Tue Jan 02, 2007 8:16 pm
Location: Cypress TX
Contact:

Re: Add Buttons to Windows Title Bar(Windows)

Post by Rook Zimbabwe »

Excellent Rashad!!! You are rocking PB!!! :D
Binarily speaking... it takes 10 to Tango!!!

Image
http://www.bluemesapc.com/
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6166
Joined: Sat May 17, 2003 11:31 am
Contact:

Re: Add Buttons to Windows Title Bar(Windows)

Post by blueznl »

Cool!
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
PB
PureBasic Expert
PureBasic Expert
Posts: 7581
Joined: Fri Apr 25, 2003 5:24 pm

Re: Add Buttons to Windows Title Bar(Windows)

Post by PB »

Rashad's code has 3 problems though:

(1) It doesn't work if #PB_Window_Tool is used for the window,
because the images are too large. So, you'll need 2 additional
sized buttons for those. This is not a major problem.


(2) If the window gets maximized, the buttons are not aligned
correctly in the vertical position of the title bar:

Image


(3) It doesn't work with different color schemes. Check this:

Image


So, still some work to do to make it 100% bullet-proof on all PCs. ;)
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4946
Joined: Sun Apr 12, 2009 6:27 am

Re: Add Buttons to Windows Title Bar(Windows)

Post by RASHAD »

@electrochrisso
Thanks man "I am now pretty well clued up on Title Bar Buttons."
Yes you just summarized the whole idea, it is just an approach

@Rook thanks I definitely like you mate
You are rock

@blueznl
Thank you
You are always in the spot with your nice comments

@PB
Most of your comments is the coder responsibility
But I will see what I can do

Thank you guys
Egypt my love
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4946
Joined: Sun Apr 12, 2009 6:27 am

Re: Add Buttons to Windows Title Bar(Windows)

Post by RASHAD »

New Update :
Now you can use any size for the images (Reasonable Size)
It will be resized to be fine with any TitleBar height

#1 :
Modified by MV
For solving a problem when the minimize animation is enabled in win 7

Code: Select all

Global x,y,w,buttonW,buttonH,borderW,r1.RECT,r2.RECT,ma


Procedure CreateButton(image,x,y,text.s="×",color=$c0c0c0)
   
    If CreateImage(image,x,y)
        StartDrawing(ImageOutput(image))
        Box(1,1,x-2,y-2,color)
        Plot(0,y-1,color)
        Plot(x-1,y-1,color)
        DrawingMode(#PB_2DDrawing_Transparent)
        x-TextWidth(text)
        y-TextHeight(text)
        DrawText(x>>1,y>>1,text)
        StopDrawing()
    EndIf
   
EndProcedure

Procedure WndProc(hwnd, uMsg, wParam, lParam)

      GetWindowRect_(WindowID(1),r.RECT)
      x = r\right - (buttonW*5) - borderW   ;5 = for Max & Restore & Min and 2 more buttons
      y = r\top
      If OSVersion() <= #PB_OS_Windows_XP
        y = y + 5
      Else
        x = x + 20
      EndIf
;       If w < 20
;         x = x = r\right - (buttonW*4) - borderW + 8
;       EndIf
      result = #PB_ProcessPureBasicEvents 

 Select uMsg
   
        Case #WM_NOTIFY     
        
        Case #WM_GETMINMAXINFO     
            *pMinMax.MINMAXINFO = lParam
            *pMinMax\ptMinTrackSize\x=buttonW*5
        
      
        Case #WM_SIZE,#WM_MOVE,#WM_PAINT
          GetWindowRect_(GadgetID(10),r1.RECT)
          GetWindowRect_(GadgetID(11),r2.RECT)
          r1\top = r1\top + 2
          r2\top = r2\top + 2
          If GetWindowState(1) = #PB_Window_Maximize
            If OSVersion() <= #PB_OS_Windows_XP
              ResizeWindow(2,x,y,(w+4)*2,buttonH)
            Else
              ResizeWindow(2,x-4,y+6,(w+4)*2,buttonH)
            EndIf
           Else
              ResizeWindow(2,x,y,(w+4)*2,buttonH) 
           EndIf
             
   EndSelect
   
  ProcedureReturn result 
EndProcedure

anm.ANIMATIONINFO\cbSize = SizeOf(ANIMATIONINFO)
SystemParametersInfo_($0048, SizeOf(ANIMATIONINFO), @anm, 0)
ma = anm.ANIMATIONINFO\iMinAnimate
If ma = 1
    anm.ANIMATIONINFO\iMinAnimate = 0
    SystemParametersInfo_($0049, SizeOf(ANIMATIONINFO), @anm, 0)
EndIf



;LoadImage(0, "state1.bmp")              ;24 x 24 pixel    Button state 1
;LoadImage(1, "state2.bmp")              ;24 x 24 pixel    Button state 2

OpenWindow(1,0,0,600,400,"Add Button to Title Bar",#PB_Window_SystemMenu|#PB_Window_MinimizeGadget| #PB_Window_MaximizeGadget|#PB_Window_SizeGadget|#PB_Window_ScreenCentered)
  
w = GetSystemMetrics_(#SM_CYCAPTION) - 2  ;2 to 3
CreateButton(0,w,w)
CreateButton(1,w,w,"?",$f0c0c0)
  buttonW = GetSystemMetrics_(#SM_CXSIZE)
  buttonH = GetSystemMetrics_(#SM_CYSIZE)
  borderW = GetSystemMetrics_(#SM_CXBORDER)
OpenWindow(2,0,0,w*5,w,"",#WS_POPUP,WindowID(1))
SetWindowColor(2,#Red)
SetWindowLongPtr_(WindowID(2),#GWL_EXSTYLE,GetWindowLongPtr_(WindowID(2),#GWL_EXSTYLE)|#WS_EX_LAYERED)
SetLayeredWindowAttributes_(WindowID(2),#Red,0,#LWA_COLORKEY)
;ResizeImage(0,w,w)
;ResizeImage(1,w,w)
;ImageGadget(10,0,0,0,0,ImageID(0))
;ImageGadget(11,0,0,0,0,ImageID(0))
ImageGadget(10,4,0,w,w,ImageID(0))
ImageGadget(11,4+w,0,w,w,ImageID(0))
SetWindowCallback(@WndProc())     
SetActiveWindow(1)

Repeat
  Select WaitWindowEvent()
      
      Case #PB_Event_CloseWindow
          If ma = 1
              anm.ANIMATIONINFO\iMinAnimate = 1
              SystemParametersInfo_($0049, SizeOf(ANIMATIONINFO), @anm, 0)
          EndIf
           Q = 1
      
      Case #PB_Event_Gadget
          Select EventGadget()
            Case 10
              Debug "Button 10 Pressed"

            Case 11
              Debug "Button 11 Pressed"

           EndSelect
           SetActiveWindow(1)
           
           
      Case #WM_MOUSEMOVE,#WM_NCMOUSEMOVE
         GetCursorPos_(@p.POINT)
         If PtInRect_(@r1,PeekQ(@p))
           SetGadgetState(10,ImageID(1))
         Else
           SetGadgetState(10,ImageID(0))
         EndIf
         If PtInRect_(@r2,PeekQ(@p))
           SetGadgetState(11,ImageID(1))
         Else
           SetGadgetState(11,ImageID(0))
         EndIf
           
  EndSelect 
Until Q =1
End

#2 :
Keeping the min anim enabled
#2-1: Using Delay(350) to compensate the lag in timing
#2-2:Or using Windows Timer to do the job

Code: Select all

Global x,y,w,buttonW,buttonH,borderW,r1.RECT,r2.RECT,ma


Procedure WndProc(hwnd, uMsg, wParam, lParam)

      GetWindowRect_(WindowID(1),r.RECT)
      x = r\right - (buttonW*5) - borderW   ;5 = for Max & Restore & Min and 2 more buttons
      y = r\top
      If OSVersion() <= #PB_OS_Windows_XP
        y = y + 5
      Else
        x = x + 20
      EndIf
;       If w < 20
;         x = x = r\right - (buttonW*4) - borderW + 8
;       EndIf
      result = #PB_ProcessPureBasicEvents 

 Select uMsg
   
        Case #WM_NOTIFY     
        
        Case #WM_GETMINMAXINFO     
            *pMinMax.MINMAXINFO = lParam
            *pMinMax\ptMinTrackSize\x=buttonW*5
        
      
        Case #WM_SIZE,#WM_MOVE,#WM_PAINT
          GetWindowRect_(GadgetID(10),r1.RECT)
          GetWindowRect_(GadgetID(11),r2.RECT)
          r1\top = r1\top + 2
          r2\top = r2\top + 2
          If GetWindowState(1) = #PB_Window_Maximize
            If OSVersion() <= #PB_OS_Windows_XP
              ResizeWindow(2,x,y,(w+4)*2,buttonH)
            Else
              ResizeWindow(2,x-4,y+6,(w+4)*2,buttonH)
            EndIf
           Else
              ResizeWindow(2,x,y,(w+4)*2,buttonH) 
           EndIf
             
   EndSelect
   
  ProcedureReturn result 
EndProcedure

anm.ANIMATIONINFO\cbSize = SizeOf(ANIMATIONINFO)
SystemParametersInfo_($0048, SizeOf(ANIMATIONINFO), @anm, 0)
ma = anm.ANIMATIONINFO\iMinAnimate

LoadImage(0, "state1.bmp")              ;24 x 24 pixel    Button state 1
LoadImage(1, "state2.bmp")              ;24 x 24 pixel    Button state 2

OpenWindow(1,0,0,600,400,"Add Button to Title Bar",#PB_Window_SystemMenu|#PB_Window_MinimizeGadget| #PB_Window_MaximizeGadget|#PB_Window_SizeGadget|#PB_Window_ScreenCentered)
;If GetWindowLongPtr_(WindowID(1),#GWL_EXSTYLE) <= 256
  w = GetSystemMetrics_(#SM_CYCAPTION) - 2
  buttonW = GetSystemMetrics_(#SM_CXSIZE)
  buttonH = GetSystemMetrics_(#SM_CYSIZE)
  borderW = GetSystemMetrics_(#SM_CXBORDER)
; Else
;   w = GetSystemMetrics_(#SM_CYSMCAPTION) - 2
;   buttonW = w
;   buttonH = w
; EndIf
OpenWindow(2,0,0,w*5,w,"",#WS_POPUP,WindowID(1))
SetWindowColor(2,#Red)
SetWindowLongPtr_(WindowID(2),#GWL_EXSTYLE,GetWindowLongPtr_(WindowID(2),#GWL_EXSTYLE)|#WS_EX_LAYERED)
SetLayeredWindowAttributes_(WindowID(2),#Red,0,#LWA_COLORKEY)
ResizeImage(0,w,w)
ResizeImage(1,w,w)
ImageGadget(10,4,0,w,w,ImageID(0))
ImageGadget(11,4+w,0,w,w,ImageID(0))
SetWindowCallback(@WndProc())     
SetActiveWindow(1)

Repeat
  Select WaitWindowEvent()
      
      Case #PB_Event_CloseWindow
           Q = 1
      
      Case #PB_Event_Gadget
          Select EventGadget()
            Case 10
              Debug "Button 10 Pressed"

            Case 11
              Debug "Button 11 Pressed"

           EndSelect
           SetActiveWindow(1)
           
      Case #PB_Event_MinimizeWindow
      If ma = 1 And OSVersion() > #PB_OS_Windows_XP
          HideWindow(2,1)
      EndIf
           
      Case #PB_Event_RestoreWindow
      If ma = 1 And OSVersion() > #PB_OS_Windows_XP
          Delay(350)
          ;AddWindowTimer(2, 10, 350)
          HideWindow(2,0)
          SetActiveWindow(1)
      EndIf          
          
      ;Case #PB_Event_Timer
          ;RemoveWindowTimer(2,10)
          ;HideWindow(2,0)
          ;SetActiveWindow(1)
           
      Case #WM_MOUSEMOVE,#WM_NCMOUSEMOVE
         GetCursorPos_(@p.POINT)
;          GetWindowRect_(GadgetID(10),r1.RECT)
;          GetWindowRect_(GadgetID(11),r2.RECT)
;          r1\top = r1\top + 2
;          r2\top = r2\top + 2
         If PtInRect_(@r1,PeekQ(@p))
           SetGadgetState(10,ImageID(1))
         Else
           SetGadgetState(10,ImageID(0))
         EndIf
         If PtInRect_(@r2,PeekQ(@p))
           SetGadgetState(11,ImageID(1))
         Else
           SetGadgetState(11,ImageID(0))
         EndIf
           
  EndSelect 
Until Q =1
End


To do:(If I have some free time)
Using Transparent Images to be compatible with different color schemes

Edit:
#1 Just updated taking into consideration yrriti & MV suggestions

Have fun
Last edited by RASHAD on Fri Nov 12, 2010 5:55 pm, edited 2 times in total.
Egypt my love
Mistrel
Addict
Addict
Posts: 3415
Joined: Sat Jun 30, 2007 8:04 pm

Re: Add Buttons to Windows Title Bar(Windows)

Post by Mistrel »

If you packed some sample images into your code it would be a lot easier for people to quickly paste into their IDE and test it.
PB
PureBasic Expert
PureBasic Expert
Posts: 7581
Joined: Fri Apr 25, 2003 5:24 pm

Re: Add Buttons to Windows Title Bar(Windows)

Post by PB »

@Mistrel: That's exactly why my screenshots show 2 x black boxes. :)

I just replaced "LoadImage(0, "state1.bmp")" with "CreateImage(0,24,24)"
and "LoadImage(1, "state1.bmp")" with "CreateImage(1,24,24)". ;)
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
User avatar
kernadec
Enthusiast
Enthusiast
Posts: 146
Joined: Tue Jan 05, 2010 10:35 am

Re: Add Buttons to Windows Title Bar(Windows)

Post by kernadec »

hi RASHAD
thanks for sharing
really well for the creation of toolbars included in the window

Good Bye
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4946
Joined: Sun Apr 12, 2009 6:27 am

Re: Add Buttons to Windows Title Bar(Windows)

Post by RASHAD »

Hi guys

Last Post updated
Any comments are welcomed
Egypt my love
yrreti
Enthusiast
Enthusiast
Posts: 546
Joined: Tue Oct 31, 2006 4:34 am

Re: Add Buttons to Windows Title Bar(Windows)

Post by yrreti »

Thanks a lot for this. It looks nice.
Just a little change I made that some might like, as I didn't want the buttons so close to
the min/max, and also to have a little spacing between the buttons. (using XP Pro)
I used PB's temp for the images.

Code: Select all

;LoadImage(0, "state1.bmp")              ;24 x 24 pixel    Button state 1
;LoadImage(1, "state2.bmp")              ;24 x 24 pixel    Button state 2
CreateImage(0,24,24)
CreateImage(1,24,24)
and changed the following lines:

Code: Select all

w = GetSystemMetrics_(#SM_CYCAPTION) - 3  ;2 to 3

;ImageGadget(10,4,0,w,w,ImageID(0))
ImageGadget(10,-2,0,w,w,ImageID(0))

;ImageGadget(11,4+w,0,w,w,ImageID(0))
ImageGadget(11,w,0,w,w,ImageID(0))
Thanks again
User avatar
Michael Vogel
Addict
Addict
Posts: 2797
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: Add Buttons to Windows Title Bar(Windows)

Post by Michael Vogel »

Some more changes to do some more checks without the need of bitmaps...

Code: Select all

Procedure CreateButton(image,x,y,text.s="×",color=$c0c0c0)
    
    If CreateImage(image,x,y)
        StartDrawing(ImageOutput(image))
        Box(1,1,x-2,y-2,color)
        Plot(0,y-1,color)
        Plot(x-1,y-1,color)
        DrawingMode(#PB_2DDrawing_Transparent)
        x-TextWidth(text)
        y-TextHeight(text)
        DrawText(x>>1,y>>1,text)
        StopDrawing()
    EndIf
    
EndProcedure

Code: Select all

w = GetSystemMetrics_(#SM_CYCAPTION) - 2  ;2 to 3
CreateButton(0,w,w)
CreateButton(1,w,w,"?",$f0c0c0)
ImageGadget(10,0,0,0,0,ImageID(0))
ImageGadget(11,0,0,0,0,ImageID(0))
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4946
Joined: Sun Apr 12, 2009 6:27 am

Re: Add Buttons to Windows Title Bar(Windows)

Post by RASHAD »

Hey 'yrreti' 'MV' brought it back to
w = GetSystemMetrics_(#SM_CYCAPTION) - 2

Shoot him :mrgreen: :mrgreen:


Edit:
Thank you guys
Just beautiful MV we can use some symbols from webdings or wingdings

Edit:
#1 Just updated taking into consideration yrreti & MV suggestions
Egypt my love
User avatar
Lewis
User
User
Posts: 47
Joined: Fri Nov 25, 2005 1:12 pm

Re: Add Buttons to Windows Title Bar(Windows)

Post by Lewis »

Hi folks!

This is an interesting thread! 8) However, it occurred to me that code to remove system icons in the titlebar would be of interest to many a programmer. For example, it's not unusual to see games with just the close icon visible/available.

Anyone care to propose a solution? ...

Cheers,
Lewis
Post Reply