How to add an extra button to the WindowTitle?

Just starting out? Need help? Post your questions and find answers here.
va!n
Addict
Addict
Posts: 1104
Joined: Wed Apr 20, 2005 12:48 pm

How to add an extra button to the WindowTitle?

Post by va!n »

An window has normaly three buttons.... Minimize, Maximize, CloseButton...
How is it possible to add an own (4th) button to the window? If a user press on the button, i would like to minimize the app only to the systray. thanks.

I am looking for something like eMule support...
va!n aka Thorsten

Intel i7-980X Extreme Edition, 12 GB DDR3, Radeon 5870 2GB, Windows7 x64,
JCV
Enthusiast
Enthusiast
Posts: 580
Joined: Fri Jun 30, 2006 4:30 pm
Location: Philippines

Post by JCV »

Check the sourcecode of JaPBe. Locate "Stay on Top" on files.
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

GPI's code is good, I believe Tailbite has something similar. Also, I have a much simpler implementation here:

http://www.purebasic.fr/english/viewtopic.php?t=22476
BERESHEIT
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

I have an improved version of this with a themed look, here's a demo:

http://www.networkmaestro.com/titlebar.exe

Here's the source and resources in a zip:

http://www.networkmaestro.com/titlebutton.zip

You will have to edit the resource file to reflect the path to the icons on your machine. Relative paths don't seem to work in resource files.

One thing to note, neither my version nor the GPI / El_Choni versions found in Japbe and Tailbite work on Vista. Not sure why, I'll have to see if it can be tweaked to support Vista too.
BERESHEIT
Sparkie
PureBatMan Forever
PureBatMan Forever
Posts: 2307
Joined: Tue Feb 10, 2004 3:07 am
Location: Ohio, USA

Post by Sparkie »

Works great netmaestro :!:

...well except for the nasty memory leak. Adding some ReleaseDC_()'s in there seems to fix it :wink:
What goes around comes around.

PB 5.21 LTS (x86) - Windows 8.1
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

:oops: :oops: :oops:

Dreadful coding!!!
BERESHEIT
Sparkie
PureBatMan Forever
PureBatMan Forever
Posts: 2307
Joined: Tue Feb 10, 2004 3:07 am
Location: Ohio, USA

Post by Sparkie »

Been there...done that :wink:
What goes around comes around.

PB 5.21 LTS (x86) - Windows 8.1
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

Will the window dc stay the same for the life of the window? If so, I could just get it, make it global, use as needed and release it once at the end. What do you think?

[edit] For my excuse, see my sig :wink:
BERESHEIT
User avatar
Fluid Byte
Addict
Addict
Posts: 2336
Joined: Fri Jul 21, 2006 4:41 am
Location: Berlin, Germany

Post by Fluid Byte »

I don't want to picky netmaestro 'cuz this is nice work so far but I got 2 things I'd like to point out:

1.) You have take into account that users have set different heights for their titlebar like me:

Image

2.) Any chance to remove the "nasty" focus rect when you hover over the button with the mouse?
Windows 10 Pro, 64-Bit / Whose Hoff is it anyway?
xgp
Enthusiast
Enthusiast
Posts: 128
Joined: Mon Jun 13, 2005 6:03 pm

Post by xgp »

EDITED: too late, Fluid Byte already said the same i wanted to say.


Wow!
Excellent netmaestro! :D

But, just one thing which i'm sure you already know..

It doesn't work that good with XP styles disabled.
Oh... well, here is mine:

Image


It's easy to understand why this happens, but it might (i have no idea right now) be a bit difficult to workaround it.
To make it look good on my machine, i just modified the yTop parameter in all DrawIconEx_ calls from 7 to 3.

Image


Anyway, Excellent piece of code!
xgp
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Post by Trond »

Code: Select all

; Original by William Yu
EnableExplicit

Global OldWndProc

#ANTIALIASED_QUALITY = 4
#NONANTIALIASED_QUALITY = 3

Procedure Callback(WindowID, Message, wParam, lParam)
  Protected Result = 0
  Static Pushed.l
  Protected Rect.RECT
  Protected X.l, Y.l
  Protected hDC.l
  Protected Border.l
  Protected Pen.l
  Protected PenSize.l
  Protected PB_WindowProc.l
  Protected Font
  Protected Caption.s{2}
  Select Message
    Case #WM_NCLBUTTONDOWN
      GetWindowRect_(WindowID, @Rect)
      X = lParam & $FFFF
      Y = lParam >> 16
      With Rect
        \Left   = \Right - GetSystemMetrics_(#SM_CXFRAME) - GetSystemMetrics_(#SM_CXSIZE) * 4 + 1
        \Top    = \Top + GetSystemMetrics_(#SM_CYFRAME) + 2
        \Right  = \Left + GetSystemMetrics_(#SM_CXSIZE) -1
        \Bottom = \Top + GetSystemMetrics_(#SM_CYSIZE) - 4
        If x >= \Left And x <= \Right And y >= \Top And y <= \Bottom
          Pushed = 1
          SendMessage_(WindowID, #WM_NCPAINT, 0, 0)
          Result = 0
        Else
          CallWindowProc_(OldWndProc, WindowID, Message, wParam, lParam)
          Result = 0
        EndIf
      EndWith
    Case #WM_NCLBUTTONUP
        CallWindowProc_(OldWndProc, WindowID, Message, wParam, lParam)
        Result = 0
      If Pushed
        Pushed = 0
        MessageRequester("", "Send to tray...")
      EndIf
    Case #WM_NCPAINT, #WM_NCACTIVATE
      CallWindowProc_(OldWndProc, WindowID, Message, wParam, lParam)
      hDC = GetWindowDC_(WindowID)
      GetWindowRect_(WindowID, @Rect)
      With Rect
        \Left = \Right - \Left - GetSystemMetrics_(#SM_CXFRAME) - GetSystemMetrics_(#SM_CXSIZE) * 4 + 2
        \Top = GetSystemMetrics_(#SM_CYFRAME) + 2
        \Right = \Left + GetSystemMetrics_(#SM_CXSIZE) - 2
        \Bottom = \Top + GetSystemMetrics_(#SM_CYSIZE) - 4
        If Pushed
          Border = #BDR_SUNKEN
        Else
          Border = #BDR_RAISED
        EndIf
        DrawEdge_(hDC, @Rect, Border, #BF_RECT | #BF_SOFT | #BF_MIDDLE)
        Font = CreateFont_(Int(GetSystemMetrics_(#SM_CXSIZE)*1.5), 0, 0, 0, 0, 0, 0, 0, #DEFAULT_CHARSET, 0, 0, #NONANTIALIASED_QUALITY, 0, @"Arial")
        SelectObject_(hDC, Font)
        Caption = "."
        SetBkMode_(hDC, #TRANSPARENT)
        \Right - 2
        \Bottom + 3
        DrawText_(hDC, @Caption, -1, @Rect, #DT_BOTTOM | #DT_SINGLELINE | #DT_RIGHT)
        DeleteObject_(Font)
        Result = 1
      EndWith
    Default
      Result = CallWindowProc_(OldWndProc, WindowID, Message, wParam, lParam)
  EndSelect
  ProcedureReturn Result
EndProcedure

OpenWindow(0, 0, 0, 512, 384, "", #PB_Window_ScreenCentered | #PB_Window_SystemMenu | #PB_Window_MaximizeGadget | #PB_Window_MinimizeGadget | #PB_Window_SizeGadget | #PB_Window_Invisible)
CreateGadgetList(WindowID(0))
TextGadget(0, 10, 10, 100, 25, "Click on the dot button to minimize window to tray")
OldWndProc = SetWindowLong_(WindowID(0), #GWL_WNDPROC, @Callback())
HideWindow(0, 0)

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Break
  EndSelect
ForEver
User avatar
Fluid Byte
Addict
Addict
Posts: 2336
Joined: Fri Jul 21, 2006 4:41 am
Location: Berlin, Germany

Post by Fluid Byte »

@netmaestro: Forget my second point. I just see that you are using bitmaps.

So I guess you need to access the XP theme lib?

@Trond: Please update your system respectivley use the XP theme feature. Then you would know that this code certainly corectly places/sizes the button but lacks XP skinning representation.
Windows 10 Pro, 64-Bit / Whose Hoff is it anyway?
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

This code should pretty much size the button to fit correctly on the titlebar of the window. To test it, I added code to change the window style to ToolWindow and it looked right. Also, the memory leak should be fixed.

Code: Select all

;=====================================================================
; Program:            TitleBar Button Example - skinned look
; Author:             netmaestro
; Date:               December 27, 2006
; Target OS:          Microsoft Windows All
; Target Compiler:    PureBasic 4.02
; License:            Free, Unrestricted, credit appreciated
;                     but not required
; Required Resources: http://www.networkmaestro.com/TitleButton.zip
;=====================================================================

Global pencilup=LoadImage_(GetModuleHandle_(0),"IconUp",#IMAGE_ICON,0,0,0) 
Global pencilhover=LoadImage_(GetModuleHandle_(0),"IconHover",#IMAGE_ICON,0,0,0) 
Global pencilpushed=LoadImage_(GetModuleHandle_(0),"IconPushed",#IMAGE_ICON,0,0,0) 
Global WindowDC, ButtonSize, ButtonTop

Procedure ButtonAction() 
  SetGadgetText(0, GetGadgetText(0)+"Pencil... ") 
EndProcedure 

Procedure MouseOnButton() 
  GetCursorPos_(@pt.point) 
  If pt\x >= WindowX(0)+540 And pt\x <= WindowX(0)+560 
    If pt\y >=WindowY(0)+ButtonTop And pt\y <= WindowY(0)+ButtonTop+ButtonSize 
      ProcedureReturn 1 
    Else 
      ProcedureReturn 0 
    EndIf 
  EndIf 
EndProcedure 

Procedure ProcessTitleButtons() 
  If MouseOnButton() 
    While GetAsyncKeyState_(#VK_LBUTTON) & 32768 
      If MouseOnButton() 
        DrawIconEx_(WindowDC, 540,ButtonTop, pencilpushed, ButtonSize, ButtonSize, 0, #Null, #DI_NORMAL ) 
      Else 
        DrawIconEx_(WindowDC, 540,ButtonTop, pencilup, ButtonSize, ButtonSize, 0, #Null, #DI_NORMAL ) 
      EndIf 
      Delay(1) 
    Wend 
    While WindowEvent():Wend 
    If MouseOnButton() 
      ButtonAction() 
    EndIf 
    DrawIconEx_(WindowDC, 540,ButtonTop, pencilup, ButtonSize, ButtonSize, 0, #Null, #DI_NORMAL ) 
  EndIf 
EndProcedure 

Procedure CallBack(hwnd, msg, wparam, lparam) 
  result = #PB_ProcessPureBasicEvents 
  Select msg 
    Case #WM_PAINT,#WM_ACTIVATE,#WM_MOVE 
      DrawIconEx_(WindowDC, 540,ButtonTop, pencilup, ButtonSize, ButtonSize, 0, #Null, #DI_NORMAL ) 
    Case #WM_SYSCOMMAND 
      ProcessTitleButtons() 
  EndSelect 
  ProcedureReturn result 
EndProcedure 

Procedure TitleButtonHover()
  Repeat
    If GetAsyncKeyState_(#VK_LBUTTON) & 32768 = 0
      If MouseOnButton() 
        DrawIconEx_(WindowDC, 540,ButtonTop, pencilhover, ButtonSize, ButtonSize, 0, #Null, #DI_NORMAL ) 
      Else
        DrawIconEx_(WindowDC, 540,ButtonTop, pencilup, ButtonSize, ButtonSize, 0, #Null, #DI_NORMAL ) 
      EndIf
    EndIf
    Delay(50)
  ForEver
EndProcedure

OpenWindow(0,0,0,640,480,"TitleBarButton Example by netmaestro",#PB_Window_ScreenCentered|#PB_Window_SystemMenu|#PB_Window_MinimizeGadget) 
WindowDC = GetWindowDC_(WindowID(0))

wi.WINDOWINFO
wi\cbSize = SizeOf(WINDOWINFO)
GetWindowInfo_(WindowID(0), @wi)
TitleBarHeight = (wi\rcClient\top - wi\rcWindow\top)
ButtonSize = TitleBarHeight * 0.62
buttonTop  = TitleBarHeight * 0.25

SetWindowCallback(@CallBack()) 
CreateThread(@TitleButtonHover(), 0)
CreateGadgetList(WindowID(0)) 
TextGadget(0,220,200,240,200,"") 

Repeat : Until WaitWindowEvent() = #WM_CLOSE 

ReleaseDC_(WindowID(0), WindowDC)
End 
BERESHEIT
User avatar
ts-soft
Always Here
Always Here
Posts: 5756
Joined: Thu Jun 24, 2004 2:44 pm
Location: Berlin - Germany

Post by ts-soft »

it's easier to use a *.res, so no changes for path and so on:
Download the ButtonIcons.res
and add this line on top of netmeastro's code:

Code: Select all

Import "buttonicons.res" : EndImport
I hope it's usefull
PureBasic 5.73 | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Old bugs good, new bugs bad! Updates are evil: might fix old bugs and introduce no new ones.
Image
Sparkie
PureBatMan Forever
PureBatMan Forever
Posts: 2307
Joined: Tue Feb 10, 2004 3:07 am
Location: Ohio, USA

Post by Sparkie »

@Trond: I'm getting the memory leak with yours as well. Adding ReleaseDC_() fixes it.

Starts off using 2,256K with 32 GDI Objects

After moving the window back and forth past the screen edges a few times, it's using 2,688K with 1,376 GDI Objects
What goes around comes around.

PB 5.21 LTS (x86) - Windows 8.1
Post Reply