Software to make life easier

CBalloonMsg - an easy-to-use non-modal balloon alternative to AfxMessageBox

March 6th, 2008 by Paul Roberts

While working on a new app I decided it would be nice to use balloon-style tooltips to convey simple messages to the user rather than relying on ye olde ::AfxMessageBox. It would be a less disruptive way of warning the user of minor things like editing mistakes, failing to fill in a field and so on.

cballoonmsg.jpg

I found an existing CodeProject article that seemed to be exactly what I was looking for: Balloon Help as a non-modal replacement for MessageBox(). On closer inspection, I decided against using this because it doesn’t use Windows’ own balloon tooltip. Instead, it draws its own, and at the time of writing I think it needs a small update for Vista. Surely there had to be a simpler solution that uses the real tooltip ctrl? Well I didn’t find one, so I wrote my own and it’s called CBalloonMsg.

Prerequisites

Before going any further please be aware that I coded this for use in theme-aware apps (ie. those with a manifest requesting common ctrls v6) running on Vista or XP (preferably SP2). I haven’t tried using it on Win 2000, but I’m pretty sure it wouldn’t look right. And don’t even think about NT4 and Win9x!

Using the code

This couldn’t be much simpler:

  • Add BalloonMsg.h and BalloonMsg.cpp to your project.
  • Make sure your stdafx.h has WINVER and _WIN32_WINNT set to 0×0501 or better and make sure you’ve got a manifest in your .rc2 (check out the demo!)
  • Finally, use one of the Show or ShowForCtrl static methods to display the balloon message, e.g.
    CBalloonMsg::ShowForCtrl( _T(Test Title”), _T(Test Text”),
    &my_ctrl, hIcon );

The Show/ShowForCtrl methods display the tooltip at the nominated position or over the nominated ctrl. By default, the tooltip stays up for 10 secs then closes automatically. It’ll close earlier if there’s a change in focus or if the mouse moves appreciably. You can change the “stay up” or autopop time easily (more on this later) and you can close or “pop” the balloon at any time using the RequestCloseAll() static method.

How it works (briefly)

When you call one of the Show methods, a separate user interface thread is created. This in turn creates its own small, transparent window around the current mouse position, then sets about processing that window’s message queue. The window acts as the parent for a tooltip ctrl, and calls CToolTipCtrl::RelayEvent to make sure that the tooltip has first bite at all relevant windows messages. The tooltip is given a zero millisecond initial delay, so it appears as soon as it is activated. When the tooltip eventually closes, a call is made to PostQuitMessage which gets rid of the transparent parent window and ends the thread. The thread wrapper self-deletes for completeness.

That’s about it. You’ll find more detailed information on the inner workings in the code’s comments.

Points of interest

You can supply your own icon to the Show calls, OR you can use Windows’ built-in icons by using the special values described in the MSDN doc for TTM_SETTITLE: 1 for info, 2 for warning, 3 for error

You can also change quite a few of the defaults for CMessageBalloon by setting new values for its static members:

s_nInitialDelay Set to zero by default. Dunno why you’d want to change this,
but…
s_nAutoPop Time before balloon self-closes. Defaults to 10 secs.
s_nMaxTipWidth Maximum tip width in pixels. Makes the balloon use linebreaks.
s_nToolBorder The amount by which the mouse can move before the balloon pops

Finally, note the use of the handy function GetGUIThreadInfo which allows us to check the focus window in another thread.

History

First version: 6th March 2008.

You must be logged in to post a comment.

Four Legged Pal