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

Autopanning All Windows, Views and Controls

0.00/5 (No votes)
19 Nov 1999 1  
Autopan within your own application
Sample Image 1 Sample Image 2

What Does Autopan Do?

Autopan is used for panning windows by simply pressing the middle mouse button and dragging the mouse to the desired direction. You probably know this method from other applications (left picture).

Another possibility of using Autopan is choosing a value in ListBoxes, ComboBoxes or with SpinButtons (right picture).

What Particular Features Does It Have?

  • Support of MFC-Views
    • CEditView, CFormView, CListView (all modes), CRichEditView, CScrollView, CTreeView
  • Support of Windows Controls
    • ComboBox (different look&feel), Edit, ListBox, ListCtrl (all modes), SpinButton (different look&feel), TreeCtrl
  • Continuous subpixel scrolling (adapted form Lutz Kretzschmar)
    • Smooth scrolling even with very slow speed
  • Accelerated panning
    • Faster acceleration when more than 42 pixel away from origin
  • Simple usage
    • Predefined Macros, Automated detection of control/view type
  • Customizable behavior
    • Style Flags and Parameter classes

How Do I Integrate It in My Own Code?

If you want to use it in your application, simply add the source files to your project and include the resources from the template. Every time you want to start panning, create the origin window:

Using in a MFC CView

void CAutoPanView::OnMButtonDown(UINT nFlags, CPoint point)
{
    // Try to create the window (neither ctrl nor shift may be pressed)
    CWheelWnd_OnMButtonDown;

    // If panning was not started, continue as usual...
    CScrollView::OnMButtonDown(nFlags, point);
}

If you want to simulate the 3rd mouse button by pressing the left and the right same time, you can use CWheelWnd_OnLButtonDown and CWheelWnd_OnRButtonDown in the same way as CWheelWnd_OnMButtonDown.

Using in a MFC CDialog

void CAutopanDialog::OnMButtonDown(UINT nFlags, CPoint point)
{
    // Try to create the window (neither ctrl nor shift may be pressed)
    // and find desired control
    CWheelWnd_OnMButtonDown_Dlg;

    // If panning was not started, continue as usual...
    CDialog::OnMButtonDown(nFlags, point);
}

BOOL CAutopanDialog::PreTranslateMessage(MSG* pMsg)
{
    // The WM_MBUTTONDOWN handler
    CWheelWnd_PreTranslateMessage;

    // Processing as usual
    return CDialog::PreTranslateMessage(pMsg);
}

Using in a MFC PropertyPage

void CAutopanPage::OnMButtonDown(UINT nFlags, CPoint point)
{
    // Try to create the window (neither ctrl nor shift may be pressed)
    // and find desired control - this time we have to find a
    // child-window
    CWheelWnd_OnMButtonDown_PropPg;

    // If panning was not started, continue as usual...
    CPropertyPage::OnMButtonDown(nFlags, point);
}

BOOL CAutopanPage::PreTranslateMessage(MSG* pMsg)
{
    // The WM_MBUTTONDOWN handler
    CWheelWnd_PreTranslateMessage;

    // Processing as usual
    return CPropertyPage::PreTranslateMessage(pMsg);
}

Yes, that's all!

How Does It Work?

As soon as the Origin-Window is created, the CAutoPanParameters for scrolling the current window is identified by the classname except the usage of a specific class is demanded.

Every 10 millisecs, the distance from the origin is calculated, if the distance is more than 42 pixel, the virtual distance will be increased for a faster acceleration (optional). Also the direction-flags will be handled now.

Now the new distances are added to the long-time-sums (for smooth scrolling) and the CAutoPanParameters class is used to determine how many pixels are necessary for scrolling one step. Based on these values, the number of steps to scroll is calculated.

If we need to scroll, the CAutoPanParameters class is called to do the scrolling and the long-time-sums are corrected as well as the right cursor is set.

The CAutoPanParameters class now calculates how many units it will scroll the window and passes these values to the DoScrollWindow member, which now does the scrolling.

Best you now have a look on the code (perhaps with the debugger), then you will see how it really works.

And How Do I the Customize the Behavior?

You can customize the behavior either by providing Style Flags or by using your own Parameter Class. In either case, you have to call MfxTrackAutoPan() to create the origin window and start panning:

MfxTrackAutoPan(
    CWnd*                pParentWnd, 
    WORD                 wStyle = MFX_WHEELWNDSTYLE_DEFAULT, 
    CAutoPanParameters*  pAutoPanParameters = NULL
    );

pParentWnd               Pointer to the window to be scrolled
wStyle                   optional <a href="#flags">Style Flags</a>
pAutoPanParameters       optional <a href="#class">Parameter Class</a>

Style Flags

MFX_WHEELWNDSTYLE_ONEDIRECTION
No diagonal scrolling.

MFX_WHEELWNDSTYLE_UPDOWNONLY
Allow vertical scrolling only.

MFX_WHEELWNDSTYLE_LEFTRIGHTONLY
Allow horizontal scrolling only.

MFX_WHEELWNDSTYLE_NOSUBPIXELSCROLLING
No smooth subpixel-scrolling.

MFX_WHEELWNDSTYLE_SCROLLBYMESSAGE
Use WM_HSCROLL/WM_VSCROLL messages with SB_THUMBPOSITION to scroll
the window. (CAutoPanParametersMessage)

MFX_WHEELWNDSTYLE_SCROLLBYMESSAGEEX
Use multiple WM_HSCROLL/WM_VSCROLL messages with SB_LINERIGHT/SB_LINELEFT/
SB_LINEUP/SB_LINEDOWN to scroll the window. (CAutoPanParametersLineMessages)

MFX_WHEELWNDSTYLE_SCROLLBYMESSAGEREG
Use a registered message (rjf_OriginWindowUpdate) with the distance provided
as LPARAM. (CAutoPanParametersRegMessage)

MFX_WHEELWNDSTYLE_SCROLLBYMESSAGETRK
Use WM_HSCROLL/WM_VSCROLL messages with SB_THUMBTRACK to scroll
the window. (CAutoPanParametersMessageThumbTrack)

Parameter Class

The CAutoPanParameters class is a plugin-class which you can use to customize nearly everything:

class CAutoPanParameters
{
    // szClassName: classname for supported class; NULL to use for all
    // nWindowResID: resourceID for background bitmap
    CAutoPanParameters(LPCTSTR szClassName = NULL, UINT nWindowResID = 0);
    virtual ~CAutoPanParameters();

    // Which background bitmap shall we show?
    virtual UINT GetWindowResID(CWnd* /*pParentWnd*/) 
                                const {return m_nWindowResID;};
    virtual void GetBitmapDimensions(CSize& size, CWnd* pParentWnd) const;
    virtual void CreateWindowRegion(CRgn& rgn, CWnd* /*pParentWnd*/) const;

    // Can we use this class to pan which window?
    virtual CWnd* PanThisWindow(CWnd* pParentWnd) const;

    // We are scrolling! So which cursor to show?
    virtual int GetCursorResID(int nScrollX, int nScrollY, 
                               bool bNoHorzScroll, bool bNoVertScroll) const;

    // Implementation of scrolling:
    // This one is called if we have to scroll at least one step. The default
    // implementation assumes scrollbars.
    virtual bool DoScroll(CWnd* pParentWnd, int nScrollStepsX, 
                          int nScrollStepsY) const;
    // And here we know the Origin and Destination, so really Do scroll 
    // the window to the new position. 
    // It is only needed for the default "DoScroll"
    virtual bool DoScrollWindow(CWnd* pParentWnd, int nScrollToX, 
                           int nOriginX, int nScrollToY, int nOriginY) const;

    // Scroll one step if you have to scroll ? pixels
    virtual int GetPixelsInAStepX  (CWnd* /*pParentWnd*/, 
                                         int /*nScrollX*/) const {return 1;};
    virtual int GetPixelsInAStepY  (CWnd* /*pParentWnd*/, 
                                         int /*nScrollY*/) const {return 1;};
    // Scroll by ? substeps if scrolling one step
    virtual int GetSubstepsInAStepX(CWnd* /*pParentWnd*/, 
                                         int /*nScrollX*/) const {return 1;};
    virtual int GetSubstepsInAStepY(CWnd* /*pParentWnd*/, 
                                         int /*nScrollY*/) const {return 1;};

    // Can scroll this window?
    virtual bool NoVertScroll(CWnd* pParentWnd) const;
    virtual bool NoHorzScroll(CWnd* pParentWnd) const;
}

In mfxWhlPan.cpp and mfxWhlPan.inc, there are many sample implementations for panning all kinds of views and controls, so this is probably a good point to start with, if you plan to realize your own behavior.

If you have any comments, annotations or questions, feel free to leave a note in the comments section below.

Credits

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.

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