I know that a neat WTL balloon tip class already exists on CodeProject.com, but this control was actually inspired from my old CountDown sample and a Delphi component by Jonathan Hosking (I'm a former Pascal programmer, so it was fun to look at some Delphi code).
The control was created because I required something more of my balloons. This control uses a dialog template to render the balloon, allowing you to put a multitude of texts and shiny buttons inside it.
Being a dialog means that it works best in a modal state. But you can have modeless balloons floating around too.
The dialog needs a buddy. That's a window it can position itself relative to. You can choose on which side it should prefer to attach itself, but if there is not enough real estate, the dialog will move to another side of the buddy window.
The sample contains some Office 97 buttons as well. They are not perfect, but I included them anyway so you could perhaps build your own pesky Office Assistant look-alike into your WTL app.
A few quirks
Implementing this was not without a few quirks.The little arrow-head turned out to be most troublesome. Normally you would paint the entire balloon frame in one go, however if i.e. the arrow-head should be painted to the left, then the entire dialog content had to be shifted to the right. To avoid this maneuver, I applied the arrow-head as a separate window, which is attached on-top of the dialog at runtime.
Another problem is of course that you might want to resize your dialog
depending on the size of text and other controls. You can still resize
the dialog in a WM_INITDIALOG
handler - probably even
using the WTL Dialog Resize classes.
How to use it
Simply create a dialog class as usual.The dialog should be a popup dialog, with all borders and captions removed.
Add the Tool Window style so it does not appear in the task list.
Then derive from CBalloonDialog...
class CMyTipDlg :
public CDialogImpl<CMyTipDlg>,
public CBalloonDialog<CMyTipDlg>
{
public:
enum { IDD = IDD_MYTIPDLG };
...
In your dialog message map, add a few chains...
BEGIN_MSG_MAP(CMyTipDlg)
CHAIN_MSG_MAP( CBalloonDialog<CMyTipDlg> )
...
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
ALT_MSG_MAP(1)
CHAIN_MSG_MAP_ALT( CBalloonDialog<CMyTipDlg>, 1 )
END_MSG_MAP()
Finally, to show the dialog, simply use the DoModal()
method.
But first you must attach your buddy window...
CMyTipDlg dlg;
dlg.SetBuddy(GetDlgItem(IDC_EDIT1));
UINT nRes = dlg.DoModal();
If you do not assign the buddy window, the balloon dialog
will appear as a MessageBox-like dialog - without the arrow
and centered on the owner window.
The CBalloonDialog class needs to handle a few important
messages, such as the WM_INITDIALOG
.
Place the CHAIN_MSG_MAP
macro at the top of your
message map or make sure to set bHandled
to FALSE
if you
handle these messages locally as well.
Source Code Dependencies
Microsoft Visual C++ 6.0Microsoft WTL 3.1 Library
Download Files
Source Code (40 Kb) |