Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Toolbars with Spinners & Sliders

0.00/5 (No votes)
26 Oct 2000 1  
How to create toolbars with spinners and/or sliders
  • Download source files - 48 Kb

    Sample Image - spnsld.gif

    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:

    ...
       
    //##################################################//
    
    // Load the dummy buttons toolbar. VERY IMPORTANT!!
    
    //
    
       
    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:

    1. In the resource editor of VC++, Create a dummy toolbar with 16 dummy buttons.
    2. 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()
      {
      
      	//##########################################//
      
      	// Creation
      
      
      	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;
      }
      
    3. Derive a class from the mighty CToolBar and name it any thing you like. I called it CSpinToolBar to be simple.
    4. 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) 
      	{
          
          // This line maps the slider control to the scroll bar parameter
      
          CSliderCtrl* m_wndSlider = (CSliderCtrl*) pScrollBar;
          
          m_wndSpin_sld.SetPos(m_wndSlider->GetPos());
      
          // Here we can load our own designed cursor while sliding. 
      
          // NICEEE, Ha :-)
      
          HCURSOR hCursor = AfxGetApp()->LoadCursor(IDC_CURSOR_SLIDER); 
          ::SetCursor(hCursor);
      	
          CToolBar::OnHScroll(nSBCode, nPos, pScrollBar);
      }
      
      void CSpinToolBar::OnVScroll(UINT nSBCode, UINT nPos, 
                                                       CScrollBar* pScrollBar) 
      {
      
          // This lines map the each spinner control to the 
      
          // scroll bar parameter	
      
          CSpinButtonCtrl* m_wndSpin_r = (CSpinButtonCtrl*) pScrollBar;
          CSpinButtonCtrl* m_wndSpin_g = (CSpinButtonCtrl*) pScrollBar;
          CSpinButtonCtrl* m_wndSpin_b = (CSpinButtonCtrl*) pScrollBar;
      
          // Here we can load our own designed cursor while spinning around. 
      
          // NICEEE, Ha :-)
      
          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 object for the rectangle body of each control, their 
      
      // physical existence. 
      
      CRect rect;
      
      // This one sets the desired button by index to what you like it 
      
      // to become. The function SetButtonInfo (int nIndex, UINT nID, 
      
      // UINT nStyle, int iImage) prototype.
      
      SetButtonInfo (0, ID_EDIT_R, TBBS_SEPARATOR , cxChar * 8);
      
      // This one actually gets the rectangle area of the button in question
      
      GetItemRect (0, &rect);
      
      // Here we set the rect area of the obtained button from above code
      
      rect.bottom = rect.top + (cyChar + 6);
      
    5. 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:
      // Set the edit box default numbers
      
      SetPositions();
      
      return 0;
      
    6. 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() 
      {
      
        // Get a pointer to our Main Frame
      
        CMainFrame* pFrame = (CMainFrame*) AfxGetApp()->m_pMainWnd;
        ASSERT_VALID(pFrame);
      
        // Document pointer
      
        CSpinnerTBDoc* pDoc = GetDocument();
        ASSERT_VALID(pDoc);
      
        // Set the spin toolbar's member variable m_nBlue value 
      
        // to the spinner's value
      
        pFrame->m_wndSpinBar.m_nBlue = 
                                    pFrame->m_wndSpinBar.m_wndSpin_b.GetPos();
      	
        // Set the document's member variable m_nBlue 
      
        // value to the toolbar value
      
        pDoc->m_nBlue = pFrame->m_wndSpinBar.m_nBlue;
      	
        // Set the text COLORREF value
      
        pDoc->m_clrTextClr = RGB(pDoc->m_nRed, pDoc->m_nGreen, pDoc->m_nBlue);
      
        // force Update to the view and set the modifying flag to true
      
        pDoc->UpdateAllViews(0);
        pDoc->SetModifiedFlag();
      	
      
      }
      
    7. 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:

    // Custom user messages
    
    #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

  • License

    This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

    A list of licenses authors might use can be found here