Download source files - 48 Kb
Introduction
This article and the demo app is to teach how to create toolbars with spinners and/or sliders on them. However, you can use the classes for each one of them as they are with very little midifications as per your own requirements in your application.
The idea and implementation is fairly easy when you come to do it yourself from scratch, however, but please note that you don't miss the main or the most important piece of code. They are the following 2 lines of code that come in the message handler function OnCreate(...)
of any one of the classes, as illustrated below:
...
if (!LoadToolBar (IDR_SPINNER_BAR))
return -1;
...
The above lines make sure that the dummy toolbar is loaded after it was created in the CMainFrame
class' OnCreate(...)
function.
Bibiti, Babiti, Booo :o) Or let's explain in few easy steps how things are done here:
Because the Slider Toolbar is just for demonstration and does not do much while the Spinner Toolbar does a very lot, I will first start on the class CSpinToolBar
:
- In the resource editor of VC++, Create a dummy toolbar with 16 dummy buttons.
- In the
CMainFrame
class, create the toolbar. In my case I have added a member function and then called it within the create of mainframe which is like this: BOOL CMainFrame::CreateSpinnerBar()
{
if (!m_wndSpinBar.CreateEx(this, TBSTYLE_FLAT , WS_CHILD |
WS_VISIBLE | CBRS_BOTTOM
| CBRS_GRIPPER | CBRS_TOOLTIPS
| CBRS_FLYBY | CBRS_SIZE_FIXED))
return FALSE;
m_wndSpinBar.LoadToolBar (IDR_SPINNER_BAR);
m_wndSpinBar.SetWindowText(
_T("RGB Spinners: From 0 to 255 _&_ Slider 0 to 255"));
m_wndSpinBar.EnableDocking (CBRS_ALIGN_TOP | CBRS_ALIGN_BOTTOM);
DockControlBar(&m_wndSpinBar);
return TRUE;
}
- Derive a class from the mighty
CToolBar
and name it any thing you like. I called it CSpinToolBar to be simple.
- Add
WM_CREATE
, WM_HSCROLL
(for the Slider) & WM_VSCROLL
(for the Spinners) to the above derived class and fill the last two ones with codes as shown under: void CSpinToolBar::OnHScroll(UINT nSBCode, UINT nPos,
CScrollBar* pScrollBar)
{
CSliderCtrl* m_wndSlider = (CSliderCtrl*) pScrollBar;
m_wndSpin_sld.SetPos(m_wndSlider->GetPos());
HCURSOR hCursor = AfxGetApp()->LoadCursor(IDC_CURSOR_SLIDER);
::SetCursor(hCursor);
CToolBar::OnHScroll(nSBCode, nPos, pScrollBar);
}
void CSpinToolBar::OnVScroll(UINT nSBCode, UINT nPos,
CScrollBar* pScrollBar)
{
CSpinButtonCtrl* m_wndSpin_r = (CSpinButtonCtrl*) pScrollBar;
CSpinButtonCtrl* m_wndSpin_g = (CSpinButtonCtrl*) pScrollBar;
CSpinButtonCtrl* m_wndSpin_b = (CSpinButtonCtrl*) pScrollBar;
HCURSOR hCursor = AfxGetApp()->LoadCursor(IDC_CURSOR_SPINNER);
::SetCursor(hCursor);
CToolBar::OnVScroll(nSBCode, nPos, pScrollBar);
}
And In the WM_CREATE
handler function - OnCreate(...)
, create whatever controls you want to add to the toolbar. In may case, I have 3 sets of Spinner & Edit buddy controls that would control the RGB values of the displayed text string on the view. The code is long to be pasted here, so please just have a look at them from within the project files and the example below.
Example: This is how we obtain the button index to modify it as per our need.
CRect rect;
SetButtonInfo (0, ID_EDIT_R, TBBS_SEPARATOR , cxChar * 8);
GetItemRect (0, &rect);
rect.bottom = rect.top + (cyChar + 6);
- Add a member function called
SetPositions()
to it as well. This is where we will put the SetRange(...)
, SetBuddy(...)
& the SetPos(...)
functions of the spinners to intialize them. Then call this function at the end of the OnCreate(...)
but before the return 0
line of code, like this:
SetPositions();
return 0;
- This is the last but never the least step in finilizing the spinner toolbar functionality and its effectiveness on the document's data. Add
ON_EN_CHANGE
message maps and handlres to the edit controls to catch their updation by the spinners of the spinner toolbar. This is the best place to put any data modifying code into and I have done it in the view class to keep things simple. You can add them anywhere else as your application requires. Because they map to the ID of the editors, they will be processed for sure. I have done it like this: ON_EN_CHANGE(ID_EDIT_R, OnUpdateRed)
ON_EN_CHANGE(ID_EDIT_G, OnUpdateGreen)
ON_EN_CHANGE(ID_EDIT_B, OnUpdateBlue)
Example: This is how we do it. A sample of the blue color edit control update handler.
void CSpinnerTBView::OnUpdateBlue()
{
CMainFrame* pFrame = (CMainFrame*) AfxGetApp()->m_pMainWnd;
ASSERT_VALID(pFrame);
CSpinnerTBDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
pFrame->m_wndSpinBar.m_nBlue =
pFrame->m_wndSpinBar.m_wndSpin_b.GetPos();
pDoc->m_nBlue = pFrame->m_wndSpinBar.m_nBlue;
pDoc->m_clrTextClr = RGB(pDoc->m_nRed, pDoc->m_nGreen, pDoc->m_nBlue);
pDoc->UpdateAllViews(0);
pDoc->SetModifiedFlag();
}
- And, And, Hmm, OOops, That's IT!, nice job.
And oh yes, as I mentioned earlier that the slider toolbar does not do much, so I won't say anything about it here, but if you need further help on it, please do not hesitate to e-mail me your question. I's be glad to assist.
Sample
Please download and in case you are interested in the WM_USER messages, take a look inside the stdafx.h file and you will find the lines:
#define WM_USER_UPDATE_COLOR WM_USER+0x100
#define WM_USER_UPDATE_SPINNER_RED WM_USER+0x101
#define WM_USER_UPDATE_SPINNER_GREEN WM_USER+0x102
#define WM_USER_UPDATE_SPINNER_BLUE WM_USER+0x103
#define WM_USER_UPDATE_GRADIENT WM_USER+0x104
#define WM_USER_UPDATE_GRADIENT_STATUS WM_USER+0x105
which are used for updating the staus bar panels with the latest user interactions with any of the toolbars. Just as an extra visual feed back to the user.They are mapped in the mainframe class.
Questions are most welcome. Post them here or my e-mail as you desire.
Finally, HAVE FUN. I do that while programming!
Masoud Samimi
marcello43@hotmail.com
http//:www.geocities.com/samimi73