|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Want a new Job?
Chapters
Services
Feature Zones
|
Note: This is an unedited contribution. If this article is inappropriate,
needs attention or copies someone else's work without reference then please
Report This Article
IntroductionI was inspired to create XBalloonMsg when I saw great article by Paul Roberts, CBalloonMsg. I like balloon messages because visually they seem to be more lightweight and less obtrusive than standard message box:
This is ideal way to draw user's attention to a control or area of the screen. I decided to learn more about balloon tooltips which are used to show balloon messages, and find out how to integrate them in my projects. XBalloonMsg Features and BehaviorsHere are features I wanted in XBalloonMsg:
The programmatic interface to XBalloonMsg is very simple: just two functions, one of which you only need if you want to dismiss message balloon for some particular reason:
Show() FunctionHere are details forShow() function:
Implementation NotesI started by trying to get balloon message to display:m_hWndBalloon = ::CreateWindowEx(0, TOOLTIPS_CLASS, 0, WS_POPUP | WS_VISIBLE | TTS_ALWAYSTIP | TTS_NOPREFIX | TTS_BALLOON | TTS_CLOSE | TTS_NOFADE | TTS_NOANIMATE, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hParent, 0, 0, 0);This worked, except that close button (
Now that I have balloon message displayed,
how to get rid of it? Clicking close button of course works,
but what if user clicks on another window? I have taken care of
this in other projects by using However, things are still not working quite right. Some keys (arrow keys, function keys) are just ignored. What's worse, the Esc key causes the balloon tip to disappear, but also closes the dialog! The solution to these problems was to install a keyboard hook using the SetWindowsHookEx() function. This allowed me to catch the keystrokes that a user would expect to dismiss the balloon tip.
XBalloonMsgShow(), which takes same parameters
as CXBalloonMsg::Show() (see above).
The download includes Visual Basic projects for both VS6 and VS2005,
that show how to use DLL with VB:
XBalloonMsgShow()'s
nIcon parameter:
Depending on whether your application is running on XP or Vista, you can select the appropriate help icon. Here is code from C++ demo app that checks for Vista: BOOL IsVista()
{
BOOL rc = FALSE;
OSVERSIONINFO osvi = { 0 };
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (GetVersionEx(&osvi))
{
if ((osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) &&
(osvi.dwMajorVersion >= 6))
{
rc = TRUE;
}
}
return rc;
}
This is how DLL's Private Sub ShowMessage(nIcon As Long)
Dim ptCursor As POINTAPI
Dim hWndOver As Long
Dim l As Long
Call GetCursorPos(ptCursor) ' Get cursor position
hWndOver = WindowFromPoint(ptCursor.X, ptCursor.Y) ' Get window cursor is over
l = XBalloonMsgShow("My Title", "This is My Message", _
hWndOver, GetParent(hWndOver), 0, nIcon, 1, 0, 0, 1)
End Sub
For VB2005, the last parameter (bSubclassParent) must be
Private Sub ShowMessage(nIcon As Integer)
Dim ptCursor As POINTAPI
Dim hWndOver As Integer
Dim l As Integer
Call GetCursorPos(ptCursor) ' Get cursor position
hWndOver = WindowFromPoint(ptCursor.X, ptCursor.Y) ' Get window cursor is over
l = XBalloonMsgShow("My Title", "This is My Message", _
hWndOver, GetParent(hWndOver), 0, nIcon, 1, 0, 0, 0)
End Sub
C++ Demo AppHere is what demo app looks like:
If you do not want to use balloon messages (or cannot because registry setting disables them), regular tooltip will be displayed:
LPSTR_TEXTCALLBACK) are not used:
‘What's This’ HelpIn the above screenshot, notice
On Vista you will see similar message balloon:
This technique allows you to have What's This help for any control without having to create a help file. Here is code that displays What's This help balloon: //============================================================================= BOOL CXBalloonMsgTestDlg::OnHelpInfo(HELPINFO* pHelpInfo) //============================================================================= { CString s = _T(""); // the string resource id is the same as control id if (s.LoadString(pHelpInfo->iCtrlId)) { CXBalloonMsg::Show(_T("What's This? Help"), s, ::GetDlgItem(m_hWnd, pHelpInfo->iCtrlId), m_hWnd, AfxGetInstanceHandle(), (UINT)m_hHelp); } else if (pHelpInfo->iCtrlId != -1) // ignore clicking on dialog box { s.Format(_T("There is no help for control #%d.\r\n") _T("Please click on another control."), pHelpInfo->iCtrlId); CXBalloonMsg::Show(_T("Help Unavailable"), s, ::GetDlgItem(m_hWnd, pHelpInfo->iCtrlId), m_hWnd, AfxGetInstanceHandle(), TTI_INFO); } return TRUE; } One final note about What's This help: it is customary to use Shift+F1 to invoke What's This help. However, in MFC by default the F1 key (unshifted) will activate What's This help. The following code will restore the Windows standard behaviors for F1 and Shift+F1. //============================================================================= BOOL CXBalloonMsgTestDlg::PreTranslateMessage(MSG* pMsg) //============================================================================= { BOOL rc = TRUE; // Trap the famous undocumented F1 key message. Windows normally // responds to this message by sending the WM_HELP message (referred // to as WM_HELPINFO in MFC), which we use to enter What's This // (Shift+F1) help mode. This override makes unshifted F1 call // the normal Help function, and makes shifted F1 invoke the // What's This help. if (pMsg->message == 0x004D) { if (GetKeyState(VK_SHIFT) & 0x8000) SendMessage(WM_SYSCOMMAND, SC_CONTEXTHELP); else OnHelp(); } else { rc = CDialog::PreTranslateMessage(pMsg); } return rc; } //============================================================================= void CXBalloonMsgTestDlg::OnHelp() //============================================================================= { // Here you can implement full-blown F1 help }
Balloon Tip Registry KeyOn most systems, balloon tips are enabled by default. However, there is registry key that may be set that will disable balloon tips from displaying. If balloon tips are disabled, this has unfortunate effect of preventing any tooltip created withTTS_BALLOON style from displaying - it does not
automatically fall back to displaying a regular tooltip.
To handle this situation, XBalloonMsg checks
Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\EnableBalloonTipsand if it is set to 0, TTS_BALLOON style
will not be used. This allows regular tooltips to be displayed:
How to useStep 1 - Add FilesTo integrateCXBalloonMsg into your app,
you first need to add following files to your project:
The .cpp file should be set to Not using precompiled header in Visual Studio. Otherwise, you will get error
fatal error C1010: unexpected end of file while looking for precompiled header directive
XBalloonMsg.h should be included in whatever module you intend to use
XBalloonMsg in. Also, if you want to implement What's This
help, you should add one or both of the help icon files included with the demo.
Step 2 - Call CXBalloonMsg::Show()TheCXBalloonMsg::Show() function
displays message balloon, and may be called using
embedded strings like this:
CXBalloonMsg::Show(_T("Edit1 Info "), _T("This is an info string for Edit1."), m_ctrlEdit1.m_hWnd, m_hWnd, AfxGetInstanceHandle(), TTI_INFO);or using string resource IDs like this: CXBalloonMsg::Show(MAKEINTRESOURCE(IDS_EDIT2_INFO_TITLE),
MAKEINTRESOURCE(IDS_EDIT2_INFO_MSG),
m_ctrlEdit2.m_hWnd,
m_hWnd,
AfxGetInstanceHandle(),
TTI_INFO);
Internally there is just one function used for both calls.
The function determines whether
the calling parameter is resource id or string,
by inspection of high-order word of pointer:
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||