KnowledgeBase Archive

An Archive of Early Microsoft KnowledgeBase Articles

View on GitHub

Q132081: HOWTO: How to Place Scroll Bars on an Object Derived from CContr

Article: Q132081
Product(s): Microsoft C Compiler
Version(s): winnt:1.0,2.0,2.1,4.0,4.1
Operating System(s): 
Keyword(s): kbcode kbMFC KbUIDesign kbVC100 kbVC150 kbVC200 kbVC400 kbVC410 kbGrpDSMFCATL kbMFCCtrl
Last Modified: 29-JUL-2001

-------------------------------------------------------------------------------
The information in this article applies to:

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

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);
     }

Additional query words: kbinf 1.00 1.50 2.00 2.10 2.50 2.51 2.52 3.00 3.10 4.00 4.10

======================================================================
Keywords          : kbcode kbMFC KbUIDesign kbVC100 kbVC150 kbVC200 kbVC400 kbVC410 kbGrpDSMFCATL kbMFCCtrlBar 
Technology        : kbAudDeveloper kbMFC
Version           : winnt:1.0,2.0,2.1,4.0,4.1
Issue type        : kbhowto

=============================================================================

THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Copyright Microsoft Corporation 1986-2002.