Imagine you have a dialog, where you can enter text and other data related to the text. While the text should be formatted, the normal data entries should not. So you place a toolbar into your dialog, that has all the formatting buttons you need and find out, that it will dock only at the edges of your dialog. But I (the customer) wants this thing, where it belongs to: right over the format-able text entry.
To achieve the customer's need, there is a little more involved than just placing a button row in the middle of a form.
Creating the toolbar
Create a toolbar as usual and add a
CToolBar member to your dialog, giving it any name that suits you. For a formatting toolbar a name like
m_wndFormatBar sounds great.
Create a static control at that spot, where you want the toolbar to reside. Give this frame an ID (i.e.
IDC_STC_TOOLBARFRAME). Make it slightly bigger then the tools, so you can see the space that becomes occupied by the toolbar. Within class wizard assign a member to this control. Make sure it is assigned to
CStatic and not
CString. Name it whatever you want (like
Now comes the hard part. In the
OnInitDialog method of your dialog, place following code. You may omit the comments.
m_wndFormatBar.SetBarStyle(CBRS_ALIGN_TOP | CBRS_TOOLTIPS | CBRS_FLYBY);
sizeToolbar = m_wndFormatBar.CalcFixedLayout(false,true);
wpl.rcNormalPosition.bottom = wpl.rcNormalPosition.top +
sizeToolbar.cy + 4;
wpl.rcNormalPosition.right = wpl.rcNormalPosition.left +
sizeToolbar.cx + 4;
How this works
m_wndFormatBar.Create(this) tells the toolbar, to which window the commands are to be sent. Loading the images, setting the bar styles and displaying the toolbar is quite obvious. Then you calculate the size of the toolbar, and adjust the size of the static control accordingly with some margin.
After having done heavy numerical considerations we place the static control and put the toolbar in its lap.
m_Stc_ToolbarFrame.RepositionBars tells the toolbar, which window it shall snuggle up to. Then make the static control disappear.
Omitting lines or doing the calculations wrong will be sentenced with weird optical results and strange behavior of your application. Check it out.
While the command routing is very simple, the visual updating of these commands is a little bit tricky.
UpdateCommandUI handlers to your dialog and edit the methods as you would, in every Frame/View application. Do not care, when they do not seem to work. Actually they can't.
Add the line:
at the top of the dialog's cpp file, or put it inside stdafx.h. In your dialog's header file put the line:
afx_msg LRESULT OnKickIdle(WPARAM, LPARAM);
inside the message map. The best place is a line between the
//}}AFX_MSG line and the
DECLARE_MESSAGE_MAP() line. If there is no line, then make one by pressing return. In your dialog's cpp file look for the word
END_MESSAGE_MAP(). Before that line, enter
ON_MESSAGE(WM_KICKIDLE, OnKickIdle). If you forgot to include afxpriv.h the compiler will tell you, that it does not know anything about
WM_KICKIDLE. (By the way, does this message mean that someone is idly kicking?)
Add the body of the
OnKickIdle routine to your dialog class and call herein the
CommandUpdateUI handlers. How? Have a look.
LRESULT CArbitraryToolbarDlg::OnKickIdle(WPARAM, LPARAM)
cmdUI.m_nID = ID_FORMAT_BOLD; cmdUI.DoUpdate(this, FALSE);
cmdUI.m_nID = ID_FORMAT_DURCHSTRICH;
cmdUI.m_nID = ID_FORMAT_KURSIV;
cmdUI.m_nID = ID_FORMAT_UNTERSTRICH;
cmdUI.m_nID = ID_EDIT_CUT;
cmdUI.m_nID = ID_EDIT_COPY;
cmdUI.m_nID = ID_EDIT_PASTE;
Add the command handlers and test it. Drink a cup of coffee.
During this whole process you should compare your source code with mine. What you may adapt to your needs, what may not be altered I can't tell. This is taught only by experience, your experience.
The sample supplied has only the first seven buttons working. This is by design! After all, it is a sample not a full blown application.
The routines for squeezing the
RichEditCtrl will be coming soon with its own class. So stay tuned.
After having read so long, may I ask you a favour? My little brother has been sent to war in the middle east now, would you please pray for him, so he will return safe and sound? Thank you.