[MFC] Encapsulation of the base class of the dialog scroll bar class

01. Scroll bar class

The scroll bar is an object of the CScrollBar class. It is a very important control in Windows applications. It is usually attached to the dialog box to help observe data or determine the position. It can also be used as a tool for data input. There are two types of scroll bars, horizontal and vertical.

The previous article also talked about the programming method of the vertical scroll bar, but it is based on the content of the content copy on the Internet. Here, after my own research, a base class is encapsulated, so that it is convenient to use this method directly by inheriting the base class through subclasses in the future. Before understanding some methods, first understand a structure:SCROLLINFO

1.1, SCROLLINFO structure

typedef struct tagSCROLLINFO {
    
     
    UINT cbSize; 
    UINT fMask; 
    int  nMin; 
    int  nMax; 
    UINT nPage; 
    int  nPos; 
    int  nTrackPos; 
}   SCROLLINFO, *LPSCROLLINFO; 

Member description:
cbSize: The length in bytes of the SCROLLINFO structure, which must be filled in when setting and querying parameters.
fMask: Specifies which members in the structure are valid. There are 5 options for this value, and multiple options can be combined with "OR". The value is in

It must be filled in when setting and querying parameters.
SIF_ALL: The entire structure is valid
SIF_DISABLENOSCROLL: This value is only used when setting parameters, and the members of this structure are selected according to the needs of control parameter settings.
SIF_PAGE: valid for nPage members SIF_POS
: valid for nPos members SIF_RANGE : valid for nMin
and nMax members The position of the scroll box when dragging, this parameter can only be queried, not set.




Introduce several functions: SetScrollPos, SetScrollRange, SetScrollInfo, GetScrollInfo,GetScrollLimit

1.2. Set the position of the slider

int SetScrollPos( int nPos , BOOL bRedraw = TRUE );

Parameter description:
①: nPos indicates the position of the slider.
②: Redraw the scroll bar when bRedraw is TRUE.

1.3. Set the maximum and minimum values

void SetScrollRange(int nMinPos , int nMaxPos , BOOL bRedraw = TRUE);

Parameter description:
①: nMinPos indicates the minimum value
②: nMinPos indicates the maximum value.
③: Redraw the scroll bar when bRedraw is TRUE.

1.4. Obtain the parameters of the scroll bar, including the minimum and maximum values ​​of the scroll bar position, the page size, and the position of the scroll button

BOOL GetScrolllnfo(int nBar, LPSCROLLINFO lpScrollInfo, UINT nMask = SIF_ALL);

Parameter description:
①: nBar: Specify the type of the scroll bar parameter to be retrieved
②: lpScrollInfo: Point to the SCROLLINFO structure
③: nMask: Specify which members of the structure to use, and those not specified will not be used

1.5. Set the parameters of the scroll bar (same as above)

BOOL SetScrollInfo(int nBar, LPSCORLLINFO lpScrollInfo, BOOL bRedraw = TRUE);

Parameter description:
①: nBar: Specifies the type of the scroll bar parameter to be retrieved
②: lpScrollInfo: Points to the SCROLLINFO structure
③: bRedraw: Whether to redraw the scroll bar, if it is TRUE, it means redraw

1.6. Obtain the maximum position of the scroll block

int GetScrollLimit(int nBar);

Parameter description:
①: nBar: Specifies the type of the scroll bar parameter to be obtained

02. Base class design

After we understand some of the functions and the relevant knowledge of the SCROLLINFO structure, you will not be confused when you look at my base class encapsulation, so go directly to the code!

Instructions:

CScrollDialog dialog box: the window base class that supports scroll bars
Usage: Based on this class, the dialog box is derived, and the message handlers for the four events of OnHScroll, OnVScroll, OnSize, and OnShowWindow are added to the derived class

2.1、ScrollDialog.h

#pragma once

class CScrollDialog : public CDialog
{
    
    
	DECLARE_DYNAMIC(CScrollDialog)

public:
		CScrollDialog(UINT nIDTemplate, CWnd* pParent = NULL); //构造函数
		virtual ~CScrollDialog();
		
		void UpDateWindows(); //更新窗口大小

private:
		int m_nInitWidth;  //初始化宽度
		int m_nInitHeight; //初始化高度
		int m_nCurWidth;   //当前宽度
		int m_nCurHeight;  //当前高度

		int m_nOldPosX;
		int m_nOldPosY;

		BOOL m_bSized;

protected:
		virtual void DoDataExchange(CDataExchange* pDX);  //DDX/DDV 支持

		/* DECLARE_MESSAGE_MAP */

public:
		afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
		afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
		afx_msg void OnSize(UINT nType, int cx, int cy);
		afx_msg void OnShowWindow(BOOL bShow, UINT nStatus);	
};

2.2、ScrollDialog.cpp

#include "stdafx.h"
#include "ScrollDialog.h"

IMPLEMENT_DYNAMIC(CScrollDialog, CDialog)

CScrollDialog::CScrollDialog(UINT nIDTemplate, CWnd* pParent /*=NULL*/)
			: CDialog(nIDTemplate, pParent)
{
    
    
	m_nInitWidth = 0;
	m_nInitHeight = 0;
	m_nCurWidth = 0;
	m_nCurHeight= 0;
	m_nOldPosX = 0;
	m_nOldPosY = 0;
	m_bSized = FALSE;
}

CScrollDialog::~CScrollDialog()
{
    
    
}

void CScrollDialog::DoDataExchange(CDataExchange* pDX)
{
    
    
	CDialog::DoDataExchange(pDX);
}

void CScrollDialog::OnScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
    
    
	int minpos = 0;
	int maxpos = 0;
	GetScrollRange(SB_HORZ, &minpos, &maxpos);
	maxpos = GetScrollLimit(SB_HORZ);
	
	//得到当前水平滚动条的位置
	int curpos = GetScrollPos(SB_HORZ);

	//确定新的滚动条位置
	switch (nSBCode)
	{
    
    
	case SB_LEFT:
		curpos = minpos;
		break;
	case SB_RIGHT:
		curpos = maxpos;
		break;
	case SB_ENDSCROLL:
		break;
	case SB_LINELEFT:
		if(curpos > minpos)
			curpos--;
		break;
	case SB_LINERIGHT:
		if(curpos < maxpos)
			curpos++;
		break;
	case SB_PAGELEFT:
	{
    
    
		//获得页长度
		SCROLLINFO info;
		GetScrollInfo(SB_HORZ, &info, SIF_ALL);

		if(curpos > minpos)
			curpos = max(minpos, curpos - (int)info.nPage); //减去滑块的长度再做判断	
	}
	break;
	case  SB_PAGERIGHT:
	{
    
    
		SCROLLINFO info;
		GetScrollInfo(SB_HORZ, &info, SIF_ALL);

		if(curpos < maxpos)
			curpos = min(maxpos, curpos + (int)info.nPage);
	}
	break;
	case SB_THUMBPOSITION: //滚动到绝对位置(nPos为该位置)
		curpos = nPos;  //拖动操作结束时的滚动框的位置
		break;
	case SB_THUMBTRACK:  //将滚动框拖动到指定位置nPos
		curpos = nPos; 
		break;
	}
	
	//设置新的位置
	SetScrollPos(SB_HORZ, curpos);
	SCrollWindow(m_nOldPosX - curpos, 0);

	m_nOldPosX = curpos;
	UpdateWindow();

	CDialog::OnHScroll(nSBCode, nPos, pScrollBar);
}

void CScrollDialog::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
    
    
	int minpos = 0;
	int maxpos = 0;
	GetScrollRange(SB_VERT, &minpos, &maxpos);
	maxpos = GetScrollLimit(SB_VERT);

	int curpos = GetScrollPos(SB_VERT);

	switch (nSBCode)
	{
    
    
	case SB_TOP:
		curpos = minpos;
		break;
	case SB_BOTTOM:
		curpos = maxpos;
		break;
	case SB_ENDSCROLL:
		break;
	case SB_LINEUP
		if(curpos > minpos)
			curpos--;
		break;
	case SB_LINEDOWN:
		if(curpos < maxpos)
			curpos++;
		break;
	case SB_PAGEUP:
	{
    
    
		SCROLLINFO info;
		GetScrollInfo(SB_VERT, &info, SIF_ALL);

		if(curpos > minpos)
			curpos = max(minpos, curpos - (int)info.nPage);
	}
	break;
	case SB_PAGEDOWN:
	{
    
    
		SCROLLINFO info;
		GetScrollInfo(SB_VERT, &info, SIF_ALL);

		if(curpos > minpos)
			curpos = max(minpos, curpos + (int)info.nPage);
	}
	break;
	case SB_THUMBPOSITION: //滚动到绝对位置(nPos为该位置)
		curpos = nPos;  //拖动操作结束时的滚动框的位置
		break;
	case SB_THUMBTRACK:  //将滚动框拖动到指定位置nPos
		curpos = nPos; 
		break;
	}	
	
	//设置新的位置
	SetScrollPos(SB_VERT, curpos);
	SCrollWindow(0,m_nOldPosY - curpos);

	m_nOldPosY = curpos;
	UpdateWindow();

	CDialog::OnVScroll(nSBCode, nPos, pScrollBar);
}

void CScrollDialog::OnSize(UINT nType, int cx, int cy)
{
    
    
	CDialog::OnSize(nType,cx,cy);

	if(!m_bSized)
	{
    
    //获取窗口初始大小(一般为创建时资源文件中定义的尺寸)
		m_nInitWidth = cx;
		m_nInitHeight = cy;
		m_bSized = TRUE;
	}
	//更新当前窗口大小
	m_nCurWidth = cx;
	m_nCurHeight = cy;

	UpdateWindow();
}

void CScrollDialog::OnShowWindow(BOOL bShow, UINT nStatus)
{
    
    
	CDialog::OnShowWindow(bShow,nStatus);

	if(bShow)
	{
    
    //显示窗口时动态显示滚动条并设置滚动条范围或者隐藏滚动条
		UpDataWindow();
	}
}

void CScrollDialog::UpDateWindow()
{
    
    
	SCROLLINFO si = {
    
     0 };
	si.cbSize = sizeof(si);
	si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;

	GetScrollInfo(SB_HORZ, &si);
	si.nMin = 0;
	si.nMax = m_nInitWidth;
	if(si.nPos > si.nMax)
	{
    
    
		si.nPos = si.nMax;
	}
	si.nPage = m_nCurWidth;
	if(si.nPage >= (UINT)si.nMax)
	{
    
    //刚好一页,不要滚动条
		ShowScrollBar(SB_HORZ, SW_HIDE);
	}
	else {
    
    
		ShowScrollBar(SB_HORZ, SW_SHOW);
		SetScrollInfo(SB_HORZ, &si);
		ScrollWindow(m_nOldPosX - si.nPos, 0);
		m_nOldPosX = si.nPos;
	}

	GetScrollInfo(SB_VERT, &si);
	si.nMin = 0;
	si.nMax = m_nInitHeight;
	if(si.nPos > si.nMax)
	{
    
    
		si.nPos = si.nMax;
	}
	si.nPage = m_NCurHeight;
	if(sinPage >= (UINT)si.nMax)
	{
    
    //刚好一页,隐藏滚动条
		ShowScrollBar(SB_VERT, SW_HIDE);
	}
	else {
    
    
		ShowScrollBar(SB_VERT, SW_SHOW);
		SetScrollInfo(SB_VERT, &si);
		ScrollWindow(0, m_nOldPosY - si.nPos);
		m_nOldPosY = si.nPos;
	}
	UpdateWindow();  //更新窗口显示
}

This is the end of the base class encapsulation of the scroll bar. If you have any problems during use, please discuss and make progress together.
Copyright Notice: Please indicate the source of the reprint, original article, thank you!

Guess you like

Origin blog.csdn.net/m0_43458204/article/details/119969880