The Missing .NET #1: Cue Banners in Windows Forms (EM_SETCUEBANNER, Text Prompt)

The .NET framework is huge, but not so huge that it does everything for everyone; there are things that they in Redmond miss or don’t do for whatever reason but is still generally applicable to many developers. So, dear reader, I present to you a new, hopefully weekly, series of posts on stuff I find missing in .NET, typically where even the Google fails to find the answer.

One of the subtle UI improvements we’ve seen over the past few windows versions, and on the web, is the cue banner, or text prompt. They are hardly groundbreaking — putting them in your app probably won’t win you awards, but they do serve to make your applications that much more polished and usable.

They are used increasingly more often now that Vista has come out, which solved a few problems that I’ll address later. You can see them used in the popular browsers IE 7 and Firefox in the search boxes, denoting the search engine of choice for the user in a subtle grey tone. Click inside those textboxes, however, and the text disappears. That’s all a cue banner is, that grey text, informing the user what exactly she is supposed to use the text control for.

Cue banners work great in places where a formatted string is required, say an email address or a URL or a phone number. Instead of cluttering up the window with tons of labels, explaining examples or ranges of valid values, you can put those in a cue banner. It makes the UI a tad more elegant and self-explanatory.

Firefox and IE 7 Search boxes displaying a cue banner of the default search engine.These aren’t exactly missing on the web though. Search for ‘cue banner’ in your favourite search engine and you’ll find all kinds of examples, but none of them cover everything, or in a way that seems satisfactory to me. An example of an inherited textbox for Winforms can be found at this Channel 9 post. Daniel Moth has a version that works for the .NET Compact Framework as well as the main framework and decided to eschew the OS support and do it completely in managed code. He’s braver than I; I’d prefer to have MS do all that work and then use it.


The Code

Download the code I’ve covered in this article.

OK, so now we know what a cue banner is, how do we include them in our apps?

The first thing to remember is that this is all done in Win32 which requires P/Invoke. All we’re doing is sending a Win32 message on the window handle of the control. That’s pretty straightforward boilerplate code that you can find on The one thing you may have to search for is the value of the msg parameter, EM_SETCUEBANNER, but I got you covered.

private const int EM_SETCUEBANNER = 0x1501;
private const int EM_GETCUEBANNER = 0x1502;

[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern Int32 SendMessage(IntPtr hWnd, int msg,
int wParam, [MarshalAs(UnmanagedType.LPWStr)] string lParam);

You can certainly do what buddy did on Channel 9: inherit from TextBox, add the required property, call the P/Invoke method and call it a day but then you’d be missing something important. Cue banners can be placed on edit controls, not just textboxes. The unfortunate thing about WinForms is that it’s essentially a facade over Win32. It does a very good job, make no mistake, but if you push it in the wrong place you end up exposing what’s underneath. And what’s underneath is Win32 which identifies all controls with its corresponding HWND. As a consequence, Windows Forms has a pretty flat hierarchy (cf. with WPF which was designed when OO was the prevailing wisdom; a very deep hierarch). Therefore, if you want to display a cue banner in a ComboBox or a RichTextBox, which the OS allows, then you’d have to subclass ComboBox and RichTextBox. Well, that’s just not scalable or portable. You’d always have to import your own controls and use those in your projects. I’ve found that most custom controls suck when used in the designer, so who wants to use them?

Besides, all the info that’s required to make cue banners work is already there in the control! So let’s use it instead. It’s not ideal, but I prefer to keep it all in a static class. We only need to use the Handle property which Control owns and we should also parameterize the actual cue banner text so we write the following method to set cue banners:

public static void SetCueText(Control control, string text)
   SendMessage(control.Handle, EM_SETCUEBANNER, 0, text);

Easy or what? So now drop a text box on a form. Call SetCueText in the form constructor for the text box and you’re set. Now drop a ComboBox and do the same for it. Hit F5 and prepare to bask in the glo… Hey! Why isn’t the cue banner set in the ComboBox? This is where other articles completely fall down on this stuff. You see, the ComboBox is actually made up of three controls: a text box and a list box and a button; think of it as a really old and ubiquitous UserControl. ComboBox.Handle is the handle for the combined control, not the text control, so we’ll need a way to get its handle. For that, we need more P/Invoke:

private static extern bool GetComboBoxInfo(IntPtr hwnd, ref COMBOBOXINFO pcbi);

private struct COMBOBOXINFO
   public int cbSize;
   public RECT rcItem;
   public RECT rcButton;
   public IntPtr stateButton;
   public IntPtr hwndCombo;
   public IntPtr hwndItem;
   public IntPtr hwndList;

private struct RECT
   public int left;
   public int top;
   public int right;
   public int bottom;

OK, now we’re ready to add some more logic to the SetCueText method above:

public static void SetCueText(Control control, string text)
   if (control is ComboBox)
      COMBOBOXINFO info = GetComboBoxInfo(control);
      SendMessage(info.hwndItem, EM_SETCUEBANNER, 0, text);
        SendMessage(control.Handle, EM_SETCUEBANNER, 0, text);

private static COMBOBOXINFO GetComboBoxInfo(Control control)
   //a combobox is made up of three controls, a button, a list and textbox;
    //we want the textbox
    info.cbSize = Marshal.SizeOf(info);
    GetComboBoxInfo(control.Handle, ref info);
   return info;

Hit F5 on your test app again, and voila: cue banner on ComboBox!


This only works on Windows XP and Vista.

On Windows XP, this conflicts with the East Asian Language packs, so if you have them installed, cue banners won’t work. Vista fixes this.

On Windows Vista, they’ve added a use for wParam parameter in the SendMessage() call. If you set it to TRUE, then the cue banner text will remain when the control gets focus.

I’ve found no use for the corresponding GetCueText, but if you want it, make sure you use a StringBuilder as the last parameter in SendMessage(), which requires another declaration of SendMessage.

Important: If you’ve done everything above and you still don’t see the wonderful cue banner text, check to see that before you call Application.Run(), you call Application.EnableVisualStyles(). That has to be called else cue banner won’t show up no matter what OS your are using.


A few exercises for the reader:

  • SetCueText() is an ideal candidate for an extension method, if you’re allowed to use .NET 3.5. It’ll make the code just a little more readable. I’ll let you figure out how to do that.
  • There is a way you can have this on the designer. Just provide a component that implements IExtenderProvider to be dropped on the design surface.