Click here to Skip to main content
15,867,568 members
Articles / Programming Languages / C#

Corner Bowl Popup Help Control

Rate me:
Please Sign up or sign in to vote.
4.92/5 (46 votes)
16 Nov 2010Ms-PL5 min read 102.3K   1.8K   91   55
Provides a simple icon users can easily identify as a help provider. Once a user moves their mouse over the icon, a visually pleasing popup window displays context sensitive help that remains visible until they choose to close the view.

sample.jpg

Introduction

The other day, I received an email response to a sales follow up I'd sent to a potential customer which stated he was not going to buy my software, Corner Bowl Log Manager, because he was unable to get it to work. I gathered my thoughts, then called him up because surely if he couldn't get the software to work, others were in the same predicament. In summary, the user interface was not intuitive. To make matters worse, he did not know he could simply press F1 to access the associated help. This was unexpected. As I recall, the F1 help command was introduced by Microsoft as a usability standard back when Windows 95 was released, which all Windows developers should now religiously implement. Well, maybe, we all do, but even some IT professionals, such as those that use my software, do not know about the power of the F1 key. As I search for words to write this article, I even see Help printed on the F1 key. So what to do? Simple, add a question mark icon next to the controls of confusion, and popup a multi-line tooltip that explains in detail how to use the dialog to configure the software. This article offers a C# alternative to the built-in tooltip control, which is both visually pleasing and highly customizable.

Requirements

Provide a simple icon users can easily identify as a help provider. Once a user moves their mouse over the icon, a visually pleasing popup window must display context sensitive help that remains visible until they choose to close the view.

Design

This control consists of a fixed size UserControl that handles MouseOver events. When you move the mouse over the control, a popup window is displayed. This popup window uses properties contained within the UserControl to determine the size, content, and UI styles to apply. Knowing that the built-in tooltips were dated, I searched for a UI solution. I found the toolbar tooltips in Microsoft Office Word 2007 offered a good solution that would fulfill my requirements. The Word tooltips popup a window which has round corners, a border, a gradient background, a title, a message, a horizontal line, an F1 information message, and portrays a transparent based shadow (see Figure 1).

Figure 1 (Microsoft Word 2007 Tooltip)

Word_Tooltip_Sample.jpg

Since I had never created a window with transparent attributes, I searched this site to find a transparent window sample. red_moon's A ToolTip with Title, Multiline Contents, and Image provided a sample which taught me the necessary steps to implement transparency. In summary, to display round corners or a transparent shadow, the WS_EX_LAYERED style must be applied to the window. This is accomplished by overriding the CreateParams property. Once overridden, paint messages are no longer fired. Instead, within the constructor, the code must draw to a memory mapped bitmap which is selected into a memory device context for drawing via the UpdateLayeredWindows user32 API. Lastly, the window is displayed by calling the ShowWindow user32 API. For more information, see Layer Windows on MSDN.

C#
protected override CreateParams CreateParams
{
    get
    {
        CreateParams cp = base.CreateParams;
        cp.ExStyle |= WS_EX_LAYERED;
        return cp;
    }
}

private void SelectBitmap(Bitmap bmp)
{
    IntPtr hDC = GetDC(IntPtr.Zero);
    try
    {
        IntPtr hMemDC = CreateCompatibleDC(hDC);
        try
        {
            IntPtr hBmp = bmp.GetHbitmap(Color.FromArgb(0));
            try
            {
                IntPtr previousBmp = SelectObject(hMemDC, hBmp);
                try
                {
                    Point ptDst = new Point(Left, Top);
                    Size size = new Size(bmp.Width, bmp.Height);
                    Point ptSrc = new Point(0, 0);

                    BLENDFUNCTION blend = new BLENDFUNCTION();
                    blend.BlendOp = AC_SRC_OVER;
                    blend.BlendFlags = 0;
                    blend.SourceConstantAlpha = 255;
                    blend.AlphaFormat = AC_SRC_ALPHA;

                    UpdateLayeredWindow(
                        Handle,
                        hDC,
                        ref ptDst,
                        ref size,
                        hMemDC,
                        ref ptSrc,
                        0,
                        ref blend,
                        ULW_ALPHA);
                }
                finally
                {
                    SelectObject(hDC, previousBmp);
                }
            }
            finally
            {
                DeleteObject(hBmp);
            }
        }
        finally
        {
            DeleteDC(hMemDC);
        }
    }
    finally
    {
        ReleaseDC(IntPtr.Zero, hDC);
    }
}

Implementation

I created a new control, assigned a background image, and set the minimum and maximum size to 16x16. I added Title and Message properties which provide a means to assign the necessary help information at either design time or runtime. To prevent the control from receiving focus, I overrode the TabStop property and set the value to false. I also added properties for all UI aspects of the control, enabling the look to be quickly customized.

To get all fonts and colors used by Word, I took a screenshot of the Word tooltip and pasted it into Paint. Using the color picker tool, I figured out which colors they used. Finally, I took screenshots of each potentially matching font and pasted the bitmap into Paint, comparing widths, heights, and styles until I found what I think is the correct font.

Next, I added MouseEnter and MouseLeave event handlers which show and hide the popup window accordingly. Please note, I did not include a timer that automatically closes the popup window. Instead, to dismiss the popup window, the user simply moves their mouse off the control. This format provides everyone with as much time as necessary to read and understand the help without having to worry the tooltip is going to disappear on them.

Aside from the few nuances described earlier, the Form code is fairly simple. Once the bitmap is created, it's simple bit math to get the correct positions and sizes of the internal drawing components. The exception to this is the shadow code. I looked at many different solutions, but ultimately went with red_moon's concept.

Testing

Once the control was complete, I created a test application which used a timer to show and hide the popup window infinitely while I watched the memory in Task Manager. I used a large message that would display a huge bitmap so I was able to more quickly identify any issues.

Sample Application

Once I was satisfied the code was not leaking, I created a sample application for this article (Figure 2). I added a properties grid which quickly surfaced many properties I needed to hide. I overrode those properties, and set the Browsable attribute to false, which has the effect of hiding each tagged property within Visual Studio's design mode.

Figure 2 (Sample Application)

Sample_Application.jpg

What's Missing

Many of the tooltip controls that are available offer a fading option; however, Corner Bowl Log Manager is targeted at Windows Server and is typically used through Remote Desktop. For those of you with experience managing servers through Remote Desktop, you already know that although fading looks great on your desktop, it performs very poorly over a network link. This control does not include a fading option although it would be very easy for you to add.

Source Control

The source code contained within this article has been posted to CodePlex and therefore contains source control information. Although this article contains a working version of this control, the source code tip must be downloaded from CodePlex at: http://cbpopuphelpcontrol.codeplex.com.

Conclusion

The code contained within this article is quite simple, and I hope self-explanatory. Hopefully my work here will be appreciated by other C# developers that need simple inline context-sensitive help without the requirement of loading a .CHM or other help files.

License

This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)


Written By
CEO
United States United States
I am a self taught developer that has been developing both backend and frontend Windows applications since the early 1990s. I started out working for Intel as a C/C++ developer in their network management software division located here in Utah. After 3 years I left the large corporate environment to work with a startup company called emWare which developed device management software. While at emWare I worked on low level multi-threaded client/server code written in C/C++ and Java as well as many frontend MFC and later C# applications. In 2006 I started my own software company called Corner Bowl Software which provided enterprise class systems management software. In 2012 I was approached by another software company to purchase Corner Bowl Software; which I sold. I have since started a new company called Upper Setting that provides several client/server application framework SDKs and software consulting services.

Comments and Discussions

 
GeneralMy vote of 5 Pin
ScruffyDuck27-Mar-13 1:50
ScruffyDuck27-Mar-13 1:50 
GeneralRe: My vote of 5 Pin
Michael Janulaitis1-Sep-15 7:17
Michael Janulaitis1-Sep-15 7:17 
GeneralMy vote of 5 Pin
jieky peng14-Nov-11 17:03
jieky peng14-Nov-11 17:03 
GeneralRe: My vote of 5 Pin
Michael Janulaitis1-Sep-15 7:16
Michael Janulaitis1-Sep-15 7:16 
GeneralI like the design but in all fairness... Pin
afinnell21-Dec-10 8:28
afinnell21-Dec-10 8:28 
Generalnice one Pin
Pranay Rana18-Dec-10 9:57
professionalPranay Rana18-Dec-10 9:57 
GeneralRe: nice one Pin
Michael Janulaitis1-Sep-15 7:16
Michael Janulaitis1-Sep-15 7:16 
GeneralMy vote of 5 Pin
ScruffyDuck17-Dec-10 20:16
ScruffyDuck17-Dec-10 20:16 
GeneralRe: My vote of 5 Pin
Michael Janulaitis22-Dec-10 3:50
Michael Janulaitis22-Dec-10 3:50 
GeneralMy vote of 5 Pin
v# guy16-Dec-10 23:58
v# guy16-Dec-10 23:58 
GeneralRe: My vote of 5 Pin
Michael Janulaitis22-Dec-10 3:49
Michael Janulaitis22-Dec-10 3:49 
GeneralMy vote of 5 Pin
RaviRanjanKr16-Dec-10 2:59
professionalRaviRanjanKr16-Dec-10 2:59 
GeneralRe: My vote of 5 Pin
Michael Janulaitis16-Dec-10 5:39
Michael Janulaitis16-Dec-10 5:39 
GeneralExcellent app! 5 Pin
DrABELL15-Dec-10 18:29
DrABELL15-Dec-10 18:29 
GeneralMy vote of 5 Pin
Member 68182722-Nov-10 14:13
Member 68182722-Nov-10 14:13 
GeneralRe: My vote of 5 Pin
Michael Janulaitis1-Dec-10 6:16
Michael Janulaitis1-Dec-10 6:16 
GeneralThanx Pin
Poul_L18-Nov-10 3:43
Poul_L18-Nov-10 3:43 
GeneralRe: Thanx Pin
Michael Janulaitis18-Nov-10 5:04
Michael Janulaitis18-Nov-10 5:04 
GeneralRe: Thanx Pin
Poul_L18-Nov-10 5:58
Poul_L18-Nov-10 5:58 
GeneralRe: Thanx Pin
Michael Janulaitis19-Nov-10 1:22
Michael Janulaitis19-Nov-10 1:22 
GeneralRe: Thanx Pin
Poul_L21-Nov-10 1:56
Poul_L21-Nov-10 1:56 
GeneralVery Nice Pin
Doncp18-Nov-10 1:34
Doncp18-Nov-10 1:34 
You got my 5.

Don
GeneralRe: Very Nice Pin
Michael Janulaitis18-Nov-10 5:00
Michael Janulaitis18-Nov-10 5:00 
Generalthanx for the update but [modified] Pin
Poul_L17-Nov-10 3:36
Poul_L17-Nov-10 3:36 
GeneralRe: thanx for the update but Pin
Michael Janulaitis17-Nov-10 10:03
Michael Janulaitis17-Nov-10 10:03 

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

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.