Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Adding Caption Buttons to the Non-client Area on Vista

0.00/5 (No votes)
21 Sep 2007 1  
A quick and easy-to-use .NET solution for attaching buttons to the non-client area of the window title bar
Screenshot - ActiveButtons.png

Introduction

This article demonstrates a quick and easy-to-use .NET solution for attaching buttons to the non-client area of the window title bar. This uses the ActiveButtons code library, which is able to preserve the composition and transparency effects in Windows Vista.

Background

The Windows Vista operating system fundamentally changes the way the non-client area is rendered, making it almost impossible (if not actually impossible) to paint onto this area without adversely affecting the look and feel. This is because the new Windows Vista graphics engine renders the non-client area outside of the GDI using the new Desktop Windows Manager (DWM).

The DWM is able to render visual effects such as Aero glass by drawing directly to video memory. In doing this, it allows the system to perform complex blending of content from multiple applications without adversely effecting performance.

The DWM does provide an API for customising the way it renders specific Windows Forms through the use of window attributes and Win32 calls. This provides limited control over the rendering of the non-client areas. For example, in a previous article, I discussed using the DWM API to extend the non-client into a Windows Form to increase the glass surface area. To date, however, there doesn't appear to be a solution for rendering a button cleanly onto the non-client area without losing the visual effects.

In some ways, not being able to draw in the non-client area is a good thing. It leads to cleaner more consistent interfaces and adheres to the recommended Microsoft standards for interface design. That said, sometimes there is a need for more flexibility in application design and a valid argument for making use of the non-client area without losing the standard look & feel. The library discussed in this article provides one possible solution. The alternative would be to paint the entire title bar yourself including the system buttons, or disable composition effects in the application and use the traditional Win32 calls to draw within the NC area.

The Solution

The ActiveButtons implementation overcomes the limitations of NC rendering in Vista with a unique approach that is not reliant on the DWM API. The solution supports Windows Vista, Windows XP and Windows 2000 from a single codebase, and allows the attachment of buttons to any .NET Windows Form along-side the standard minimise, maximise and close buttons.

Example: Adding Button to Title Bar

// hook the Windows Form load event
protected override void OnLoad(EventArgs e)
{
    base.OnLoad(e);

    // get an instance of IActiveMenu for the current form
    IActiveMenu menu = ActiveMenu.GetInstance(this);
    // create a new button instance
    ActiveButton button = new ActiveButton();
    // set some properties
    button.BackColor = Color.LightBlue;
    button.Text = "One";
    // attach a click handler
    button.Click += new EventHandler(button_Click);
    // add the button to the menu instance
    menu.Items.Add(button);
}

How It Works

To achieve the desired effect, the library uses some trickery to overlay the buttons onto the windows NC area. This means that the rendering is still preformed within the GDI and the current process, but the DWM still renders the standard title bar complete with any glass and transparency effects where applicable.

To accomplish this, the ActiveMenu instance creates an additional transparent Windows Form behind the scenes, which is then attached to the original window. This can done from within the constructor as follows:

private ActiveMenu(Form form)
{
    ...

    // the following line attaches the menu form
    // as a child window of the original

    this.Show(form);
    
    ...
}

This new Form is then floated over the title bar area allowing .NET controls to be attached in the usual way. As the DWM treats this as another window, it still blends the buttons and renders them perfectly with the glass background in situ. Once this is achieved, it's just a case of positioning and sizing the buttons correctly. To do this, the menu hooks into the parent Form's Resize and Move events, and keeps the child menu correctly positioned.

...

// event handlers are attached in constructor routine

parentForm.SizeChanged += new EventHandler(parent_Refresh);
parentForm.Move += new EventHandler(parent_Refresh);

...

// on change of parent form, the menu is repositioned
protected void parent_Refresh(object sender, EventArgs e)
{
    this.Top = parentForm.Top;
    this.Left = parentForm.Left + 
                parentForm.Width - this.Width -
                (SystemInformation.CaptionButtonSize.Width*3) - 2;
}

The approach is fairly radical, so feedback and bug reports are greatly appreciated. Feel free to experiment with the ActiveButtons.dll library in your own applications.

History

  • Initial release, Sept 2007
  • Additional detail added on how it works, Sept 2007
  • Improved demo application and minor bug fixes, Sept 2007
  • Added ActiveButtonsBasic source code, Sept 2007
  • Added compiled help file, Sept 2007

Further Reading

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