HOWTO: How to Place Scroll Bars on an Object Derived from CControlBar (132081)



The information in this article applies to:

  • The Microsoft Foundation Classes (MFC), when used with:
    • Microsoft Visual C++ for Windows, 16-bit edition 1.0
    • Microsoft Visual C++ for Windows, 16-bit edition 1.5
    • Microsoft Visual C++ for Windows, 16-bit edition 1.51
    • Microsoft Visual C++ for Windows, 16-bit edition 1.52
    • Microsoft Visual C++, 32-bit Editions 1.0
    • Microsoft Visual C++, 32-bit Editions 2.0
    • Microsoft Visual C++, 32-bit Editions 2.1
    • Microsoft Visual C++, 32-bit Editions 4.0
    • Microsoft Visual C++, 32-bit Editions 4.1

This article was previously published under Q132081

SUMMARY

When you place scroll bars on an object derived from CControlBar, such as CDialogBar, the window messages must be handled in a special way as described in this article.

MORE INFORMATION

There are three categories of messages for which you can have handlers: window messages, control notification messages, and command messages.

Control notification messages are WM_COMMAND messages sent from controls and other child windows to their parent windows. For example, an edit control can send its parent a WM_COMMAND message containing the EN_CHANGE control notification code. Window messages include the messages with the WM_ prefix, with the exception of WM_COMMAND. WM_VSCROLL is an example of a window message sent by a control to its parent. Command messages include WM_COMMAND messages sent from user-interface objects, such as menus and toolbar buttons.

Control notification messages generated by controls in a CControlBar derived object are routed to the parent view or frame window class of the CControlBar object. However, window messages from controls are routed to the object associated with the parent window of the control -- namely, the CControlBar object itself. Therefore, handlers for controls that send window messages cannot be placed in the frame or view object.

One of the controls that sends a window message is a CScrollBar control. Therefore, when a CScrollBar control is placed on a an object derived from CControlBar, such as CDialogBar, the window messages it generates cannot be handled in the parent view or frame window classes like other messages.

One way to handle window messages from a CScrollBar on a CDialogBar is to derive from CDialogBar and include a handler in the derived class. Another way is to derive from CDialogBar and route the window messages sent to this object to the parent frame or the view window object.

Steps Required to Derive a Class from CDialogBar

  1. Create a dialog template. In the Style box, select Child. In the border box, select None. Clear the Visible check box and the caption. Leave the name IDD_DIALOG1. Create a scroll bar IDC_SCROLLBAR1.
  2. Use Class Wizard to associate the dialog with the generic CWnd class. Name the class CMyDlgBar. You need to do this because Class Wizard does not allow you to associate the dialog with a CDialogBar class.
  3. Change CMyDlgBar so that it is derived from CDialogBar, not CWnd, by changing all references from CWnd in the code to CDialogBar. Don't forget the reference in the message map for CMyDlgBar.
  4. Declare a member variable m_MyDlgBar of type CMyDlgBar as the CMainFrame class.
  5. Override the Create member function in CMyDlgBar, and associate the dialog template with the class:
       BOOL CMyDlgBar :: Create(CWnd* pParentWnd, UINT nStyle)
       {
       // Associate the dialog template with the class:
          return CDialogBar :: Create (pParentWnd,
                                      IDD_DIALOG1,
                                      nStyle,
                                      IDD_DIALOG1);
       }
    						
    NOTE: Create has only two parameters. This is so the Create function can only be used for the dialog bar IDD_DIALOG1.
  6. Call Create for this member in the CMainFrame::OnCreate.
       m_MyDlgBar.Create(this, CBRS_TOP );
    						

How to Handle the Scroll Messages in the Derived Class

There are two ways to handle the scroll messages in the derived class:

  • Handle the processing of messages in the derived class. -or-

  • Redirect the message to the parent view or frame window object and handle the actual processing in the parent window object.
The following sample code shows how to handle the scroll messages using both methods. The debug build of this program prints a TRACE message in the debug window in response to messages from a horizontal scroll bar on the CMyDlgBar IDD_DIALOG1. To run it, build the code, press the F5 function key, click the scroll bar, and look for the TRACE message in the output window.

Sample Code

The following code shows the modifications made to the code generated by ClassWizard for the derived class CMyDlgBar.

  1. The handler for the messages for the scroll bar with ID IDC_SCROLLBAR1 is in the derived class.
       /////////////////////////////////////////////////////////// 
       // mydlgbar.cpp : implementation file
       // 
       ...
       void CMyDlgBar::OnHScroll( UINT nSBCode,
                                  UINT nPos,
                                  CScrollBar* pScrollBar)
       {
        // Add code for processing WM_HSCROLL messages:
        if (pScrollBar != NULL && pScrollBar->GetDlgCtrlID() == IDC_SCROLLBAR1)
    
          {
             TRACE0( "Received message from scroll bar : IDC_SCROLLBAR1\n");
          }
    
          CDialogBar::OnHScroll(nSBCode, nPos, pScrollBar);
       }
    						
  2. In this method, the code in OnHScroll shown above is moved to the OnHScroll of the parent window object and the handler routes the message to the parent Frame or View object.
       /////////////////////////////////////////////////////////// 
       // mydlgbar.cpp : implementation file
       // 
       ...
       void CMyDlgBar::OnHScroll(UINT nSBCode,
                                 UINT nPos,
                                 CScrollBar* pScrollBar)
       {
          // Actual code to handle this message is in the parent
          // frame or view object. Send the message to that object.
       #ifdef _WIN32
          GetOwner()->SendMessage(WM_HSCROLL,
                                  (WPARAM)MAKELONG((WORD)nSBCode,(WORD)nPos),
                                  (LPARAM)pScrollBar->m_hWnd);
       #else
          GetOwner()->SendMessage(WM_HSCROLL,
                                  (WPARAM)mSBCode,
                                  (LPARAM)MAKELONG(nPos, pScrollBar->m_hWnd));
       #endif
          CDialogBar::OnHScroll(nSBCode, nPos, pScrollBar);
       }
    						

Modification Type:MajorLast Reviewed:12/1/2003
Keywords:kbcode kbhowto kbMFCCtrlBar KbUIDesign KB132081