Click here to Skip to main content
Click here to Skip to main content

Adding a 'Minimize to tray'-button to a Form's caption bar

By , 11 Jul 2005
 

Introduction

This short article shows you how to easily implement a 'Minimize to Tray' button to the caption bar of the form. The code that comes with this article only supports default forms and it doesn't support Visual Styles. Feel free to improve the code and to contact me if you need any help with it. It would be great if you send me a copy when you fix these previously mentioned limitations so that I can update this article.

Background

The current program I am working on needs to run in the background. So the best way to do this is to minimize that app to the tray bar where it is less annoying than in the task bar. So I added some code which causes the program to minimize when the user wants to close it via the Close button in the caption bar. It worked and for a time it was good. But it was a bad, not user-friendly way of doing it. I wanted to have a 'Minimize to Tray' button like eMule has - after doing some research, I noticed that this has not been done before in C#.

Using the code

  • Step 1: Add the file 'MinTrayBtn.cs' to your project, and add the NotifyIcon component with your IDE's designer. Set an icon for the NotifyIcon component and set the visibility to false.
  • Step 2: Now simply declare a MinTrayBtn variable in your Windows Form class to instantiate the object in the Form constructor.
    public class WinForm : System.Windows.Forms.Form {
    
        //... Some other code
        TyronM.MinTrayBtn mybutton;
        //... Some other code
    
        public WinForm() {
            mybutton = new TyronM.MinTrayBtn(this);
        }
    
    }
  • Step 3: Add a function to catch the MinTrayBtnClicked event and register the event handler. Use the Click-event of the NotifyIcon, then show the Form again.
    public class WinForm : System.Windows.Forms.Form {
        
        //... Some other code
        TyronM.MinTrayBtn mybutton;
        //... Some other code
    
        public WinForm() {
            mybutton = new TyronM.MinTrayBtn(this);
            mybutton.MinTrayBtnClicked += 
              new TyronM.MinTrayBtnClickedEventHandler(TrayBtn_clicked);
        }
        
        private void TrayBtn_clicked(object sender, EventArgs e) {
            this.Hide();
            this.notifyIcon1.Visible = true;
        }
    
    
        private void notifyIcon1_Click(object sender, System.EventArgs e) {
            this.Show();
            this.notifyIcon1.Visible = false;
        }
        
    }

Points of Interest

The caption bar is part of the non-client area of the window which is handled by Windows, so it isn't easy to add a button there. I had to draw the button by myself and capture various mouse events to clone the behaviour of the other buttons (this button behaves exactly like the others do, or at least it should do :)

Revision

  • 0.8.5

    11 Jul 2005

    • Changed: Variable caption button size (adjusts itself to the system metrics).
    • Fixed: Drawing issues on changes of the window width.
  • 0.8

    20 Apr 2005

    • Article creation.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Tyron Madlener
Austria Austria
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
AnswerRe: Please can you help ??memberTyronM8 Jun '07 - 8:01 
...If you explain first what you are actually trying to do yes Wink | ;)
What do you mean with a 'hand made bar'?
GeneralThanks !memberFXMC26 Dec '06 - 2:26 
Thanks , works perfectly for my small app.
GeneralAny books related to this type of programmingmemberdseknat20 Sep '06 - 20:06 
Hi All
Any one please suggest me some books related to this type of programming.

GeneralRe: Any books related to this type of programmingmemberBehind The Scene20 Sep '06 - 20:36 
Check out Apress. They've got many books.
 
ROFLOLMFAO

NewsExample Themed Buttonmembertoertchn28 Feb '06 - 10:14 
I don't used the code but here comes an example how to paint an themed Caption Button using .NET Framework 2:
 
using System.Windows.Forms.VisualStyles;
 
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
   Rectangle btnRect = new Rectangle(10, 10, 20, 20);
   DrawCaptionButton(e.Graphics, btnRect, CaptionStates.Active);
}
 
private void DrawCaptionButton(Graphics g, Rectangle bounds, CaptionStates state)
{
   if (!VisualStyleRenderer.IsSupported) return;
 
   //VisualStyleElement element = VisualStyleElement.Window.MinButton.Normal;
   VisualStyleElement element = VisualStyleElement.CreateElement("WINDOW", 15, (int)state);
 
   VisualStyleRenderer render = new VisualStyleRenderer(element);
 
   render.DrawBackground(g, bounds, bounds);
 
   Rectangle clip = new Rectangle(bounds.Left, bounds.Top, bounds.Width, bounds.Height);
   clip.Inflate(-3, -3);
 
   bounds.Height += bounds.Bottom - bounds.Top;
   render.DrawBackground(g, bounds, clip);
}
 
public enum CaptionStates : int
{
   Active = 1,
   Inactive = 2,
   Disabled = 3
}
 
-- modified at 16:15 Tuesday 28th February, 2006
GeneralRe: Example Themed Buttonmembertayspen18 Mar '06 - 9:40 
Cool, but how do you get it on the forms caption bar?
GeneralRe: Example Themed Buttonmembertoertchn18 Mar '06 - 9:43 
I don't know - never used the topic button.
AnswerRe: Example Themed Buttonmemberp-gregg23 Jul '07 - 1:35 
To enable themed button with XP style, change this:

public void DrawButton(Graphics g, bool pressed) {
if (VisualStyleRenderer.IsSupported)
{
Rectangle btnRect = new Rectangle(wnd_size.Width - (4 * 20) - 4, 12, 14, 14);
 
int status = (pressed) ? 2 : 1;
VisualStyleElement element = VisualStyleElement.CreateElement("WINDOW", 15, status);
VisualStyleRenderer render = new VisualStyleRenderer(element);
render.DrawBackground(g, btnRect, btnRect);
}
else
{
int btn_width = GetSystemMetrics(SM_CXSIZE);
int btn_height = GetSystemMetrics(SM_CYSIZE);
[...]

GeneralRe: Example Themed Buttonmembersameh_serag11 Mar '08 - 5:52 
I just want to add a simple modification:
 
public bool MouseinBtn(Point click)
{
int btn_width = GetSystemMetrics(SM_CXSIZE);
int btn_height = GetSystemMetrics(SM_CYSIZE);
Size btn_size = new Size(btn_width, btn_height);
 
//what if maximize/minimize button(s) are hidden?
int numExistingButtons = ((parent.MaximizeBox || parent.MinimizeBox) ? 3 : 1);
//what if the help button is visible?
if (parent.HelpButton) ++numExistingButtons;
Point pos = new Point(wnd_size.Width - numExistingButtons * btn_width - 12 - (btn_width - 18) - 6, 5);
 
return click.X >= pos.X && click.X <= pos.X + btn_size.Width &&
click.Y >= pos.Y && click.Y <= pos.Y + btn_size.Height;
}
.
.
.
public void DrawButton(Graphics g, bool pressed)
{
int btn_width = GetSystemMetrics(SM_CXSIZE);
int btn_height = GetSystemMetrics(SM_CYSIZE);
 
//what if maximize/minimize button(s) are hidden?
int numExistingButtons = ((parent.MaximizeBox || parent.MinimizeBox) ? 3 : 1);
//what if the help button is visible?
if (parent.HelpButton) ++numExistingButtons;
Point pos = new Point(wnd_size.Width - numExistingButtons * btn_width - 12 - (btn_width - 18) - 6, 5);
 
if (VisualStyleRenderer.IsSupported)
{
// real button size
btn_width -= 4;
btn_height -= 4;
Rectangle btnRect = new Rectangle(pos, new Size(btn_width, btn_height));
int status = 1;
if(pressed)
status = 2;

VisualStyleElement element = VisualStyleElement.CreateElement("WINDOW", 15, status);
VisualStyleRenderer render = new VisualStyleRenderer(element);
render.DrawBackground(g, btnRect, btnRect);
}
else
{
// real button size
btn_width -= 2;
btn_height -= 4;
 
Rectangle btnRect = new Rectangle(pos, new Size(btn_width, btn_height));
if (pressed)
{
ControlPaint.DrawButton(g, btnRect, ButtonState.Pushed);
}
else
ControlPaint.DrawButton(g, btnRect, ButtonState.Normal);
 
g.FillRectangle(new SolidBrush(SystemColors.ControlText), pos.X + (float)0.5625 * btn_width + Convert.ToInt32(pressed), pos.Y + (float)0.6428 * btn_height + Convert.ToInt32(pressed), btn_width * (float)0.1875, btn_height * (float)0.143);
}
}

hope helpful Smile | :)
GeneralWhen I Max. MDIChild it does not draw Buttonmemberfayaz var13 Jan '06 - 23:54 
When i maximize MDIChild Form, It should draw that button on MDIParent Form and receive all the events of active child.
 
Thanks
 
Fayaz
GeneralRe: When I Max. MDIChild it does not draw Buttonmembersameh_serag11 Mar '08 - 5:45 
try this:
 

.
.
.
public MinTrayBtn(Form parent)
{
parent.HandleCreated += new EventHandler(this.OnHandleCreated);
parent.HandleDestroyed += new EventHandler(this.OnHandleDestroyed);
parent.TextChanged += new EventHandler(this.OnTextChanged);
parent.MdiChildActivate += new EventHandler(parent_MdiChildActivate);
this.parent = parent;
}
.
.
.
private void parent_MdiChildActivate(object sender, EventArgs e)
{
DrawButton();
}


QuestionHow to Add in MDIChild Formmemberfayaz var3 Jan '06 - 18:50 
I found this article very help full. It is great. Still i want to add this button in MDIChild Form. It is working with MDIParent Form and single Form applicatio. I am able to draw it on MDIChild Form but events are not triggered. i don't know which m.msg value will catch MDIChild window click event. Please help in this.
 
Thanks
 
Fayaz
AnswerRe: How to Add in MDIChild FormmemberTyronM5 Jan '06 - 8:41 
I'm glad that you can use it Smile | :)
Actually I havent done anything with MDIChilds yet but I guess it should be working when you replace all the WM_NC* Messages with their corresponding non-NC Messages.
 
Hope that helps,
Tyron
Generalvarious buttons for winXP skinsmemberJon Hary22 Oct '05 - 5:04 
I wonder how those guys at XNeat managed to make their product works with different xp skins !??!D'Oh! | :doh:
Generalconvert to VB.NETmemberjugomkd22 Jul '05 - 8:34 
Is it possible to do that for vb.NET programmers please? Thanks in advance ... btw, really great feature and useful as well Wink | ;)
 
Stupid questions dictate stupid answers!
GeneralRe: convert to VB.NETsussAnonymous25 Jul '05 - 14:03 
I haven't any experience in vb.net but maybe someone other could write it in vb.net
GeneralRe: convert to VB.NETmemberjugomkd25 Jul '05 - 22:49 
It would be very nice if someone convert to vb.NET ... thanks for the reply
 
Stupid questions dictate stupid answers!
GeneralRe: convert to VB.NETmember1tg4625 Aug '05 - 4:07 
I have created a VB.NET alternative to this article, and have enabled XP theming, multi-state buttons, and other features have been added. This will be posted in an article with in a week or two (could be longer, but not sure). Right now I am waiting for another article author to let me use some of his code so that the article can also cover transparent menus. If for some reason I am not able to submit the article I will post the code here.
GeneralRe: convert to VB.NETmemberjugomkd26 Aug '05 - 16:48 
Thanks in advance it would be nice of you ... Regards Smile | :)
 
Stupid questions dictate stupid answers!
AnswerRe: convert to VB.NETmember1tg462 Sep '05 - 5:00 
http://thecodeproject.com/vb/net/transmenuandtitlebuttons.asp[^]
 
Hope you enjoy
 
-- modified at 20:45 Friday 9th September, 2005
GeneralRe: convert to VB.NETmemberfayaz var7 Jan '06 - 0:47 
Yes I am converting this into VB.NET. It is working file, but problem is with MDIChild Forms. I am not able to detect the Mouse Click on non-client area of window. Drawing is over.
 
Thanks
 
Fayaz
GeneralRe: convert to VB.NETmembershabonaa6 Jan '06 - 10:12 
i think this site may help converting C# code to VB.Net
http://wwww.developerfusion.com/utilities/convertcsharptovb.aspx
GeneralAdd NotifyIcon Componentmemberemc218 Jul '05 - 6:44 
How and where do I add Notify Icon component?
GeneralRe: Add NotifyIcon ComponentmemberTyron Madlener18 Jul '05 - 8:49 
Depends on the Designer your using, but normally it should be where all the other windows forms (button, textbox, etc.) are.
If that doesn't help you maybe want to have a look at the demo Smile | :)
GeneralWM_NCMOUSELEAVE eventmemberkobalcz7 Jul '05 - 23:32 
Hi,
I found your post on microsoft.public.dotnet.languages.csharp regarding using the TrackMouseEvent() function to hook up for the WM_NCMOUSELEAVE notification. I'm currently strugling with the same problem. Have you got any luck with enabling this event?

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130523.1 | Last Updated 12 Jul 2005
Article Copyright 2005 by Tyron Madlener
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid