Introduction
CScrollView
comes in handy whenever you need to provide scrolling capability to your view. However, there are several limitations. First, CScrollView
is derived from CView
, so it is designed to work with the document-view architecture. If you attempt to nest a CScrollView
inside a normal CWnd
or a CDialog
, you will get into a big heap of trouble. If your application requires simple and lightweight scrolling support, CScrollView
becomes awkward and costly. Second, the size of the scrolling region is bound to the signed 16-bit limit. Your application may require painting on a large logical area. A map editor or a graphics design application is a good example for such a situation. CScrollWindow
was created to address the above problems.
Background
Basing on the MFC source code of CScrollView
, I made some modifications to achieve my targets. To avoid creating bugs, I tried to make as few changes as possible. However, I know that I am just as imperfect as CScrollWindow
, so bugs may still exist.
Unlike CScrollView
, my class CScrollWindow
is derived from CWnd
so that it can be put inside any other CWnd
. If you want it on a view, nest it inside a CView
or any derived class. In this way, you can still make CScrollWindow
play nicely with the document-view architecture, of cource with more effort than if you use CScrollView
. However, flexibility is what you get in exchange for the effort.
CScrollView
uses functions LDtoDP
and DPtoLP
to convert points from device unit to logical unit and vice versa. These functions accept only 16-bit values. Therefore, you get errors when your total width or height is greater than 32767
. To avoid these errors, I do not use these functions, which means that CScrollWindow
does not support mapping modes. The only supported unit of length is pixel. If you want to support other units of measure or even zooming, you have to implement it on your own, given the background that CScrollWindow
provides to you.
One important point is that CScrollView
uses 16-bit position data provided by WM_HSCROLL
and WM_VSCROLL
. CScrollWindow
instead calls GetScrollInfo
to get 32-bit position data.
Using the Code
Although CScrollWindow
works with any CWnd
and derivatives, including CDialog
, I embed it in a CFrameWnd
in the demo project in this article. You would typically add a member of the type CScrollWindow
or derivatives in your CFrameWnd
.
CScrollWindow m_ScrollWindow;
In the OnCreate
of your CFrameWnd
, create the scroll window and set the scroll sizes.
if (!m_ScrollWindow.Create(NULL, NULL, AFX_WS_DEFAULT_VIEW,
CRect(0, 0, 0, 0), this, AFX_IDW_PANE_FIRST, NULL))
{
TRACE0("Failed to create scroll window\n");
return -1;
}
m_ScrollWindow.SetScrollSizes(CSize(65536, 65536));
Running the Demo
The demo creates a scroll window with a large total size. Scroll around using the scroll bars to verify that you can view any part of the total area.
History
March 23, 2008
- Uploaded the first version
September 12, 2015
- Changed the project name from
ScrollWindowTest
to ScrollWindowSample
- Converted the project format so that it can be built in Visual Studio 2008
- Removed the
SystemInformation
class, thereby simplifying the code
- Modified the drawing code in the demo project
- Revised the tip