目次
01. スクロールバークラス
スクロール バーは、CScrollBar クラスのオブジェクトです。これは、Windows アプリケーションにおいて非常に重要なコントロールです。通常、データの観察や位置の決定を支援するためにダイアログ ボックスにアタッチされます。また、データ入力のツールとしても使用できます。スクロール バーには、水平スクロール バーと垂直スクロール バーの 2 種類があります。
前回の記事でも垂直スクロールバーのプログラミング方法について触れましたが、インターネット上のコンテンツコピーの内容をベースにしており、ここでは私が独自に調べた結果、使いやすいように基底クラスをカプセル化しています。このメソッドは、将来サブクラスを通じて基本クラスを継承することによって直接継承されます。いくつかのメソッドを理解する前に、まず構造を理解してください。SCROLLINFO
1.1、SCROLLINFO構造体
typedef struct tagSCROLLINFO {
UINT cbSize;
UINT fMask;
int nMin;
int nMax;
UINT nPage;
int nPos;
int nTrackPos;
} SCROLLINFO, *LPSCROLLINFO;
メンバーの説明:
cbSize: SCROLLINFO 構造体のバイト単位の長さ。パラメータの設定およびクエリ時に入力する必要があります。
fMask: 構造体のどのメンバーが有効であるかを指定します。この値には 5 つのオプションがあり、複数のオプションを「OR」で組み合わせることができます。値は次のとおりです。
パラメータを設定およびクエリするときに入力する必要があります。
SIF_ALL: 構造体全体が有効です。
SIF_DISABLENOSCROLL: この値はパラメーターを設定する場合にのみ使用され、この構造体のメンバーは制御パラメーター設定のニーズに従って選択されます。
SIF_PAGE: nPage メンバーに有効SIF_POS
: nPos メンバーに有効SIF_RANGE に
および nMax メンバー
nMin
:
いくつかの関数を紹介します: SetScrollPos
、SetScrollRange
、SetScrollInfo
、GetScrollInfo
、GetScrollLimit
1.2. スライダーの位置を設定する
int SetScrollPos( int nPos , BOOL bRedraw = TRUE );
パラメータの説明:
①: nPos はスライダーの位置を示します。
②: bRedraw が TRUE の場合、スクロールバーを再描画します。
1.3. 最大値と最小値を設定する
void SetScrollRange(int nMinPos , int nMaxPos , BOOL bRedraw = TRUE);
パラメータの説明:
①: nMinPos は最小値を示します。
②: nMinPos は最大値を示します。
③: bRedraw が TRUE の場合、スクロールバーを再描画します。
1.4. スクロール バーの位置の最小値と最大値、ページ サイズ、スクロール ボタンの位置など、スクロール バーのパラメーターを取得します。
BOOL GetScrolllnfo(int nBar, LPSCROLLINFO lpScrollInfo, UINT nMask = SIF_ALL);
パラメータ説明:
①: nBar: 取得するスクロールバーパラメータの型を指定します。 ②: lpScrollInfo: SCROLLINFO構造体
を指します。 ③: nMask: 構造体のどのメンバを使用するかを指定します。指定されていないメンバは使用されません。
1.5. スクロールバーのパラメータを設定する(同上)
BOOL SetScrollInfo(int nBar, LPSCORLLINFO lpScrollInfo, BOOL bRedraw = TRUE);
パラメータ説明:
①: nBar: 取得するスクロールバーパラメータの型を指定します。
②: lpScrollInfo: SCROLLINFO構造体を指し
ます。 ③: bRedraw: スクロールバーを再描画するかどうか。TRUE の場合は再描画を意味します。
1.6. スクロールブロックの最大位置を取得する
int GetScrollLimit(int nBar);
パラメータ説明:
①: nBar: 取得するスクロールバーパラメータの種類を指定します。
02. 基本クラスの設計
いくつかの関数と SCROLLINFO 構造体の関連知識を理解すれば、基本クラスのカプセル化を見て混乱することはなくなるので、コードに直接アクセスしてください。
手順:
CScrollDialog ダイアログ ボックス: スクロール バーをサポートするウィンドウの基本クラス
使用法: このクラスに基づいてダイアログ ボックスが派生され、OnHScroll、OnVScroll、OnSize、および OnShowWindow の 4 つのイベントのメッセージ ハンドラーが派生クラスに追加されます。
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(); //更新窗口显示
}
これで、スクロール バーの基本クラスのカプセル化は終了です。使用中に問題が発生した場合は、一緒に話し合って進めてください。著作権表示: 転載元、元記事の出典を明記してください。ありがとうございます
!