Click here to Skip to main content
15,867,308 members
Articles / Desktop Programming / MFC
Article

CBalloonMsg - An Easy-to-use Non-modal Balloon Alternative to AfxMessageBox

Rate me:
Please Sign up or sign in to vote.
4.71/5 (29 votes)
1 Apr 2008CPOL5 min read 121.7K   3.6K   109   52
Makes it easy to use a balloon tooltip to convey hints/messages non-modally
Image 1

Introduction

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.

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 control? 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 (i.e. those with a manifest requesting common controls v6) running on Vista or XP (preferably SP2). I haven't tried using it on Windows 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 0x0501 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.

    C++
    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 control. By default, the tooltip stays up for 10 seconds 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 control, and calls CToolTipCtrl::RelayEvent to make sure that the tooltip has first bit 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

SafeShowMsg and BalloonsEnabled

By default, Windows allows the use of balloon tooltips. There is however a registry tweak available that prevents balloons from being displayed. It seems this is most often used to kill those often redundant and distracting tray balloons that Windows likes to present from time to time.

The tweak involves setting zero for the DWORD value EnableBalloonTips in HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced (thanks to DerMeister for reporting this!)

To get around this, the latest version of the class now includes two additional methods: BalloonsEnabled and SafeShowMsg.

BalloonsEnabled() returns TRUE if the user hasn't suppressed balloon tooltips. Following on from that, SafeShowMsg() uses balloons to display a message if they're enabled, and reverts to AfxMessageBox if the user has switched them off. The demo shows this function in action - take a look at CTTTestDlg::DoDataExchange.

Icons

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_nTimerStepDefaults to 30 milliseconds. Determines frequency of checks for balloon termination states (see History for Version 2 changes)
s_nAutoPop Time before balloon self-closes in milliseconds. Defaults to 10 seconds. Set to 0 to let the balloon stay up until closed through focus changes, user action etc.
s_nMaxTipWidthMaximum tip width in pixels. Makes the balloon use linebreaks.
s_nToolBorderThe amount by which the mouse can move before the balloon pops

GetGUIThreadInfo

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

Special Version Adapted for VC6 by Damir Valiulin

The third download at the top of the article is for a VC6 version of the demo project. It contains some minor differences from the original code, as follows:

  • Minor changes to be able to compile under VC6
  • Check for Win32 (no balloon tip there) and for registry disabling hack
  • Changes to function calls for simplification (got rid of calls with string IDs)

Many thanks to Damir for this!

History

Version 1: 6th March, 2008


Version 2: 16th March, 2008

Changed to using a tracking tooltip to counter anomalies in positioning of the balloon and its pointer when the dialog was near the edge of the screen. The use of TTF_TRACK necessitated other changes:

  • Repositioning of the balloon is now achieved via the TTM_TRACKPOSITION message rather than through the use of SetWindowPos.
  • TTM_TRACKACTIVATE is now used to activate the tooltip, rather than the MFC method Activate().
  • A timer is also created and set to fire every 30 milliseconds or so (this is configurable via s_nTimerStep above). The timer gives us a chance to spot changes in the state of windows owned by the primary thread that should bring about closure of the balloon. It also lets us (re)implement the automatic closure interval (autopop) that is used when s_nAutoPop is non-zero.

Version 3: 23rd March, 2008

  • Added SafeShowMsg and BalloonsEnabled to detect when the user has suppressed balloons via a reg tweak and fall back to AfxMessageBox.
  • Added overloads to take HWND for target control as well as CWnd*.

Version 4: 30th March, 2008

  • Added a VC6 version, kindly adapted by Damir Valiulin.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United Kingdom United Kingdom
Started programming on a Commodore Vic 20(!), and later entered employment programming for the Mac back in the days of System 6. Soon the pull of the Dark Side became too strong and I switched to Windows (Win 3.1) and have been coding for Windows ever since.

I'm now lead programmer for a small software house in Glasgow, Scotland. Our main products include PTFB Pro, ColorCache, and LogMeister.

Comments and Discussions

 
QuestionSafer closing Pin
BongoVR13-Mar-19 4:51
BongoVR13-Mar-19 4:51 
Suggestionif tooltips are not shown, try using a manifest Pin
RedFraggle24-Jul-18 2:13
RedFraggle24-Jul-18 2:13 
Questionidentical compare Pin
asrx12-Dec-14 2:56
asrx12-Dec-14 2:56 
SuggestioneBalloonMsgIcon hIcon parameter in 64 bits Pin
David Pritchard26-Mar-14 23:18
David Pritchard26-Mar-14 23:18 
QuestionCompatibility w "normal" tooltips? Pin
ols600015-Sep-08 13:12
ols600015-Sep-08 13:12 
GeneralForcing tooltips to close Pin
roel_12-Aug-08 0:42
roel_12-Aug-08 0:42 
QuestionHow to see Balloon Message point to icon on the system tray? Pin
leminh048830-May-08 17:08
leminh048830-May-08 17:08 
SuggestionSmall fix for Unicode Pin
David Pritchard22-May-08 1:18
David Pritchard22-May-08 1:18 
GeneralRe: Small fix for Unicode Pin
Paul Roberts26-May-08 22:32
Paul Roberts26-May-08 22:32 
GeneralRe: Small fix for Unicode Pin
asrx12-Dec-14 0:58
asrx12-Dec-14 0:58 
GeneralIn DLL project,can not see the tootip Pin
Szmgolden14-Apr-08 16:36
Szmgolden14-Apr-08 16:36 
GeneralRe: In DLL project,can not see the tootip Pin
Paul Roberts16-Apr-08 10:36
Paul Roberts16-Apr-08 10:36 
GeneralBalloon disappears shortly after coming up Pin
RedFraggle10-Apr-08 5:38
RedFraggle10-Apr-08 5:38 
GeneralRe: Balloon disappears shortly after coming up Pin
Paul Roberts10-Apr-08 23:09
Paul Roberts10-Apr-08 23:09 
GeneralRe: Balloon disappears shortly after coming up Pin
RedFraggle11-Apr-08 14:22
RedFraggle11-Apr-08 14:22 
GeneralExcellent! Pin
Damir Valiulin20-Mar-08 12:36
Damir Valiulin20-Mar-08 12:36 
GeneralRe: Excellent! Pin
Paul Roberts21-Mar-08 9:14
Paul Roberts21-Mar-08 9:14 
GeneralRe: Excellent! Pin
Damir Valiulin24-Mar-08 4:53
Damir Valiulin24-Mar-08 4:53 
It seems like the "email reply" system is broken on this site because I didn't get your message. So maybe just send me e-mail and then I'll send you the files. My address is XXXXXXXXX
GeneralRe: Excellent! Pin
Paul Roberts24-Mar-08 9:41
Paul Roberts24-Mar-08 9:41 
GeneralSome ideas Pin
bolivar12319-Mar-08 4:32
bolivar12319-Mar-08 4:32 
GeneralRe: Some ideas Pin
Paul Roberts20-Mar-08 1:31
Paul Roberts20-Mar-08 1:31 
GeneralSome questions Pin
Hans Dietrich18-Mar-08 17:34
mentorHans Dietrich18-Mar-08 17:34 
GeneralRe: Some questions Pin
Paul Roberts19-Mar-08 0:13
Paul Roberts19-Mar-08 0:13 
GeneralPossible reason for tooltip not showing Pin
DerMeister16-Mar-08 14:59
DerMeister16-Mar-08 14:59 
GeneralRe: Possible reason for tooltip not showing Pin
Paul Roberts17-Mar-08 10:32
Paul Roberts17-Mar-08 10:32 

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.