In this post, you will see a solution for giving the Ribbon an orb and the quick access toolbar.
Introduction
When trying to figure out how to give the Ribbon an orb and the quick access toolbar, I found myself in trouble. I hope this example works for something you may need.
Background
Take a look to some Office app with a ribbon (Word, Excel, PowerPoint). There are some things that you might notice at first sight:
- The orb is drawn half on the client area, half on the title bar.
- The quick access tools are drawn (and sensed) on the title bar.
- The title of the window is centered between the available space and the start of the caption buttons (minimize, maximize, close).
Using the Code
Although it seems like the orb and the tools are drawn on the non-client area, they are not. This trick is done with one of the features of Vista's Desktop Window Manager (DWM).
How? Well, a regular window has a client area and a non-client area:
But, a form with the trick done has no client area at all:
So, why does the form look like it has a client area? A very well known trick: DwmExtendFrameIntoClientArea
.
Turns out that when extending the frame into the client area, caption buttons (minimize, maximize, close) are drawn by default. To give life to these caption buttons, the DwmDefWindowProc
function is called.
protected override void WndProc(ref Message m)
{
...
int dwmHandled = Dwm.DwmDefWindowProc(m.HWnd, m.Msg,
m.WParam, m.LParam, out result);
if (dwmHandled == 1)
{
m.Result = result;
return;
}
...
Now, we have to provide basic frame features like window moving and resizing. This is solved by handling the WM_NCHITTEST
message on the WndProc
. The return value for this message can specify which part of the frame the mouse is currently hitting. By a measurement of areas, the code returns the correct result:
Caption
North
South
East
West
NorthWest
NorthEast
SouthEast
SouthWest
Drawing the ToolStrip
To add a ToolStrip
to the window, I just placed it as usual:
and modified the render process so the ToolStrip
gets no background:
public class NonClientAreaRenderer
: ToolStripProfessionalRenderer
{
protected override void OnRenderToolStripBackground(ToolStripRenderEventArgs e)
{
if (e.ToolStrip.IsDropDown)
{
base.OnRenderToolStripBackground(e);
}
else
{
e.Graphics.Clear(Color.Transparent);
}
}
...
And, there you go. A nice toolbar just on the non-client area, but you know, it's not the non-client area. :)
History
- 17th January, 2009 - Original post
- 6th February, 2009 - Focus bug fixed