Click here to Skip to main content
13,355,018 members (58,351 online)
Click here to Skip to main content
Add your own
alternative version


77 bookmarked
Posted 10 Jan 2003


, 7 May 2016
Rate this:
Please Sign up or sign in to vote.
An MFC control for adding middle mouse button scrolling to any CWnd derived window

Sample Image - WindowScroller.jpg


CWindowScroller is a small MFC class that is used to add middle mouse button scrolling functionality (aka. panning) to any CWnd derived window. The control is similar to the one that is found in Internet Explorer and Visual Studio .NET. All that is needed is a single line of code to get the window scroller up and running. All the resources (icon and cursors) that the window scroller uses are created dynamically at run time. They do not have to be added to your resource file.

Using the code

The first (and most obvious) step to using the CWindowScroller class is to add the class files (WindowScroller.h and WindowScroller.cpp ) to your project.

In the .cpp file for the window that you want to add the scroller to, be sure to include the WindowScroller.h file

#include "WindowScroller.h"

Then, using class wizard, add the OnMButtonDown function to your window class. ( Just a small note, the message filter has to be set to "Window" )

Now, in the OnMButtonDown function, all you have to do is create an instance of the CWindowScroller class on the heap.

void CChildView::OnMButtonDown (UINT, CPoint point)
    new CWindowScroller (this, point);

Notes :

  • If you create the CWindowScroller on the stack, it will briefly flash on the screen and then be destroyed when your variable goes out of scope.
  • There is no use saving the pointer for later use, as the CWindowScroller will be destroyed, and the memory deleted as soon as your user is finished using it.

When tjhe CWindowScroller is started it sends a RWM_ONSTARTWINDOWSCROLLER registered windows message to the window that it will scroll. If the handler function returns a non-zero value then the scroller will be blocked.

When the CWindowScroller is destroyed, it posts a RWM_ONDESTROYWINDOWSCROLLER registered windows message to the window that it scrolled. See ON_REGISTERED_MESSAGE in MSDN for more information on handling registered messages.

Member Functions

The class constructor is the only public member function.

CWindowScroller::CWindowScroller (CWnd *pParent,
                                  CPoint Point,
                                  int Pixels,        // = 15
                                  UINT Elapse,       // = 30
                                  int Direction,     // = Both
                                  BOOL bUseThumbPos) // = TRUE


pParent A pointer to the window that needs to be scrolled
Point The point, in parent window client coordinates, that will be the center of the CWindowScroller window
Pixels The distance interval, in pixels, that the mouse pointer has to be away from the center of the CWindowScroller window before the scrolling speed increases.
Elapse The time, in milliseconds, between scrolling messages. This value is passed on to the SetTimer() function
Direction The direction of the scroll. Allowable values are CWindowScroller::Vertical, CWindowScroller::Horizontal or CWindowScroller::Both
bUseThumbPos Sets the message flag to be used with WM_HSCROLL and WM_VSCROLL messages.
TRUE sets the flag to SB_THUMBPOSITION.
FALSE sets the flag to SB_THUMBTRACK.

Scrolling Speed

The scrolling speed is calculated by taking the distance, in pixels, that the mouse pointer is away from the center of the CWindowScroller window and dividing it by the value of the Pixels parameter. This will give the distance that the parent window will be scrolled every Elapse milliseconds.

Preparing your window to use the CWindowScroller

The majority of windows should work with the CWindowScroller without any problems, but some may need a little special attention, either with the CWindowScroller settings or with the way the window handles scrolling messages.

The CWindowScroller currently handles any regular CWnd derived classes by setting the scrollbar position with a call to CWnd::SetScrollPos(), and then sending either a WM_HSCROLL or WM_VSCROLL message to the window. It also has built in code for handling CScrollViews, CTreeViews, and CListViews.

How to add more supported window types to the CWindowScroller

If you get a window that the CWindowScroller does not handle because it uses some non-standard method for scrolling ( such as a list view, which uses the LVM_SCROLL message instead of WM_HSCROLL/WM_VSCROLL ) and you want the CWindowScroller to handle it, then you will have to add some code in the following places in the WindowScroller.cpp file.

First, add a new window type identifier to the WindowTypes enumeration found at the top of the file

enum WindowTypes
    Type_CWnd = 0,
    // Add more types here

Second, add the code to the GetParentWndType() function that can use the pointer passed into the CWindowScroller constructor to identify the window type. Have that code return the identifier that you added to the WindowTypes enumeration.

UINT CWindowScroller::GetParentWndType()
    TCHAR szClassName[256] = {0};
    ::GetClassName(*m_pParentWnd, szClassName, sizeof szClassName);
    if (!_tcscmp(szClassName, _T("SysTreeView32")))
        return Type_CTreeView;

    if (!_tcscmp(szClassName, _T("SysListView32")))
        if ((m_pParentWnd->GetStyle() & 0x3) == LVS_REPORT)
            return Type_CListView_Report;
        if ((m_pParentWnd->GetStyle() & 0x3) == LVS_LIST)
            return Type_CListView_List;
        return Type_CListView_Icon;

    if (m_pParentWnd->IsKindOf(RUNTIME_CLASS(CScrollView)))
        return Type_CScrollView;

    // Add additional window identifier code here

    return Type_CWnd;

The third step is to add the actual scrolling code to the OnTimer() function. Add the code as a case within the switch (m_ParentWndType) block, using the identifier you added to the WindowTypes enumeration and returned from the GetParentWndType() function as the case to be handled.

void CWindowScroller::OnTimer(UINT nIDEvent) 
    < snip >
    if (nIDEvent == 0x1FEB && rc.PtInRect(pt) && (m_HorzScroll || m_VertScroll))
        < snip >
        if (NewPoint != OriginalPoint)
            switch (m_ParentWndType)
            case Type_CListView_Report:
                < snip >

            case Type_CListView_List:
                < snip >

            case Type_CListView_Icon:
                < snip >

            case Type_CTreeView:
                < snip >

            case Type_CScrollView:
                < snip >

            case Type_CWnd:
                < snip >

            // Add additional cases here

                TRACE (_T("CWindowScroller::OnTimer - Unknown window type"));
            } // switch (m_ParentWndType)
        } // if (NewPoint != OriginalPoint)
    } // if (nIDEvent == 0x1FEB && rc.PtInRect(pt) && (m_HorzScroll || m_VertScroll))

The final step is to write up what you did in the forum below, and I will update the article with the new code.

Even if you do all this, there may still be some windows that the CWindowScroller may still not work properly with. One such window that I had a problem with was Chris Maunder's MFC Grid control 2.24. The horizontal scrolling worked great, but the vertical scrolling had a small problem. It turned out that the fixed columns along the left hand side of the control would not scroll along with the rest of the control. The problem (for me, not for Chris) was that the SB_THUMBTRACK and SB_THUMBPOSITION flags were being handled the same, but they have to be handled seperately. So a small change was required in the CGridCtrl::OnVScroll() function to get the CWindowScroller to function properly.

// Handle vert scrollbar notifications
void CGridCtrl::OnVScroll(UINT nSBCode,
                          UINT /*nPos*/,
                          CScrollBar* /*pScrollBar*/)

< snip >
    // pja - 9/1/2003 - changed case SB_THUMBPOSITION:
    // so it properly handles the CWindowScroller
        m_idTopLeftCell.row = -1; = GetFixedRowHeight();

< snip >

If any of you find other windows that the CWindowScroller has problems with, and you manage to find a fix, let me know and I can post the fix here. Thanks


January 10, 2003 Initial release
January 20, 2003 Added code for scrolling list views - Thanks to Jean-Michel LE FOL
January 23, 2003 Fixed middle button click'n hold bug
February 16, 2003 Added mouse button up handlers
February 16, 2003 Cleaned up the demo app's drawing code in order to reduce flicker when using the window scroller
March 8, 2003 Fixed bug that crashed program if window creation fails
March 10, 2003 Total rewrite of scrolling code, now supports tree views and list views in all modes.
Added GetParentWndType function
May 7, 2016 Updated the drawing code. Now uses a layered, transparent, tool window instead of a window region.
Updated code to compile with VS2015 in both 32 and 64 bit modes.
Added the WMR_ONSTARTWINDOWSCROLLER notification message.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

PJ Arends
Canada Canada
No Biography provided

You may also be interested in...

Comments and Discussions

GeneralMy vote of 5 Pin
Forhad Reza15-Nov-16 9:26
memberForhad Reza15-Nov-16 9:26 
GeneralRe: My vote of 5 Pin
PJ Arends16-Nov-16 5:18
professionalPJ Arends16-Nov-16 5:18 
GeneralRe: My vote of 5 Pin
Forhad Reza16-Nov-16 9:39
memberForhad Reza16-Nov-16 9:39 
GeneralGreat work, although it's already implemented in CScrollView... Pin
piotrmb15-Dec-05 4:48
memberpiotrmb15-Dec-05 4:48 
GeneralRe: Great work, although it's already implemented in CScrollView... Pin
PJ Arends15-Dec-05 10:13
memberPJ Arends15-Dec-05 10:13 
GeneralRe: Great work, although it's already implemented in CScrollView... Pin
piotrmb18-Dec-05 4:20
memberpiotrmb18-Dec-05 4:20 
GeneralEcellent work, Pin
Ergin Salih28-Nov-05 3:53
memberErgin Salih28-Nov-05 3:53 
GeneralAdded support for CListBox Pin
PJ Arends12-Jul-03 18:51
memberPJ Arends12-Jul-03 18:51 
GeneralProblems with certain rodents Pin
PJ Arends8-Mar-03 9:24
memberPJ Arends8-Mar-03 9:24 
GeneralRe: Problems with certain rodents Pin
WREY10-Mar-03 12:58
memberWREY10-Mar-03 12:58 
GeneralYou did not disappoint !! Pin
WREY7-Mar-03 15:07
memberWREY7-Mar-03 15:07 
GeneralRe: You did not disappoint !! Pin
PJ Arends7-Mar-03 19:34
memberPJ Arends7-Mar-03 19:34 
GeneralBroken download links Pin
Neville Franks24-Feb-03 11:06
memberNeville Franks24-Feb-03 11:06 
GeneralRe: Broken download links - Fixed Pin
PJ Arends24-Feb-03 16:01
memberPJ Arends24-Feb-03 16:01 
GeneralUsing it in ED Pin
Neville Franks27-Feb-03 17:42
memberNeville Franks27-Feb-03 17:42 
GeneralRe: Using it in ED Pin
PJ Arends27-Feb-03 18:40
memberPJ Arends27-Feb-03 18:40 
GeneralRe: Using it in ED Pin
Neville Franks27-Feb-03 20:20
memberNeville Franks27-Feb-03 20:20 
GeneralCompile error under VC7 Pin
Gerard Nicol28-Jan-03 10:40
memberGerard Nicol28-Jan-03 10:40 
GeneralRe: Compile error under VC7 Pin
PJ Arends28-Jan-03 11:20
memberPJ Arends28-Jan-03 11:20 
GeneralPB: Doesn't work with ListView Pin
Jean-Michel LE FOL20-Jan-03 2:59
memberJean-Michel LE FOL20-Jan-03 2:59 
GeneralRe: PB: Doesn't work with ListView Pin
PJ Arends20-Jan-03 10:27
memberPJ Arends20-Jan-03 10:27 
GeneralRe: PB: Doesn't work with ListView Pin
Dieter Hammer25-Feb-03 22:22
memberDieter Hammer25-Feb-03 22:22 
At first, the control is really great!
With this changes it works for ClistCtrl, horizontal super but vertical it's a little bit lazy ( I use an ownerdrawn CListCtrl in report mode ) sometimes vscroll works, sometimes it doesn't, but never like it does in other windows or even the hscroll in the same ClistCtrl. Do I something wrong?
Thank You
GeneralRe: PB: Doesn't work with ListView Pin
Lasthero26-Feb-03 0:10
memberLasthero26-Feb-03 0:10 
GeneralRe: PB: Doesn't work with ListView Pin
Dieter Hammer26-Feb-03 1:29
memberDieter Hammer26-Feb-03 1:29 
GeneralJust another proposal Pin
Dieter Hammer26-Feb-03 2:21
memberDieter Hammer26-Feb-03 2:21 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.180111.1 | Last Updated 7 May 2016
Article Copyright 2003 by PJ Arends
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid