|
スライダコントロールの基本2
前回の続きでスライダコントロールの操作部分です。
スライダを操作したときに、現在の値とエディットボックスを更新する処理を追加しましょう。スライダを操作すると、水平スライダの場合、親ダイアログクラスのCWnd::OnHScroll()関数、垂直スライダの場合CWnd::OnVScroll()関数が呼び出されます。
では、この関数をオーバーライドします。ダイアログクラスのプロパティからメッセージアイコンをクリックし、WM_HSCROLLを選択し、CWnd::OnHScroll()関数をオーバーライドします。同様にWM_VSCROLLを選択し、CWnd::OnVScroll()関数をオーバーライドします。

関数の内容は次のようにしました。実は水平も垂直も処理は全く同じなので、それぞれ自作のOnScroll()関数を呼び出しています。水平と垂直で別々の処理にしたい場合は、OnHScroll()、OnVScroll()関数に直接記述したほうがよいでしょう。
// 水平スライダ
void CSliderDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
OnScroll(nSBCode, nPos, pScrollBar);
CDialog::OnHScroll(nSBCode, nPos, pScrollBar);
}
// 垂直スライダ
void CSliderDlg::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
OnScroll(nSBCode, nPos, pScrollBar);
CDialog::OnVScroll(nSBCode, nPos, pScrollBar);
}
|
OnScroll()関数の方に本体を記述します。
// スライダ操作
void CSliderDlg::OnScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
int index = -1;
int pageSize;
int min, max;
int err = 0;
// スライダ特定
if (*pScrollBar == m_xcSlider[0]) index = 0;
if (*pScrollBar == m_xcSlider[1]) index = 1;
if (*pScrollBar == m_xcSlider[2]) index = 2;
if (index == -1) err = 1;
if (!err)
{
switch (nSBCode)
{
// つまみをドラッグ
case SB_THUMBPOSITION:
case SB_THUMBTRACK:
m_xvSlider[index] = nPos;
break;
// つまみ左側、上側をクリック
case SB_PAGELEFT:
//case SB_PAGEUP:
pageSize = m_xcSlider[index].GetPageSize();
m_xcSlider[index].GetRange(min, max);
m_xvSlider[index] = (m_xvSlider[index] -pageSize > min)
? m_xvSlider[index] -pageSize : min;
break;
// つまみ右側、下側をクリック
case SB_PAGERIGHT:
//case SB_PAGEDOWN:
pageSize = m_xcSlider[index].GetPageSize();
m_xcSlider[index].GetRange(min, max);
m_xvSlider[index] = (m_xvSlider[index] +pageSize < max)
? m_xvSlider[index] +pageSize : max;
break;
default:
break;
}
// エディットボックス更新
m_xvEdit[index].Format(_T("%d"), m_xvSlider[index]);
UpdateData(FALSE);
}
return;
}
|
まずは、どのスライダが操作されたのかを特定しないといけません。OnHScroll()、OnVScroll()の第3引数はコントロールのポインタが渡されます。これを見れば、どのスライダが操作されて関数が呼ばれたのかがわかります。
渡されるデータ型がCSliderCtrl *ではなくCScrollBar *なのは、この関数はスクロールバーでも使われるからです。しかし、スライダの場合はCScrollBar *型にキャストされているだけなので、CSliderCtrl *型として扱って問題ありません。
(*pScrollBar == m_xcSlider[0])で、CScrollBar型とCSliderCtrl型を比較していますが、これはCWnd::operator==(const CWnd& wnd)を呼び出しています。両方ともCWndの派生クラスなので、==演算子で同じインスタンスなのかどうかを判定できるのです。
スライダのつまみをドラッグした場合、第一引数のnSBCodeにSB_THUMBPOSITIONまたはSB_THUMBTRACKが渡されます。この場合、第二引数のnPosに現在の値が入っています。
また、スライダのつまみでない部分をクリックした場合、ある幅の分だけつまみが動きます。この幅をページサイズと呼びます。この場合、nSBCodeにSB_PAGELEFTなどが入ってきます。ページサイズの分だけ現在の値が動くので、どれぐらい動いたのかを自分で計算します。
CSliderCtrl::GetPageSize()関数で、ページサイズが取得できます。また、CSliderCtrl::GetRange()関数で、最小値、最大値が取得できます。
| int CSliderCtrl::GetPageSize( ) const; |
| 説明: |
スライダのページサイズを取得 |
| 引数: |
なし |
| 戻り値: |
スライダのページサイズ |
| void CSliderCtrl::GetRange(int& nMin, int& nMax) const; |
| 説明: |
スライダの最小値、最大値を取得 |
| 引数: |
nMin:最大値を受け取る変数への参照
nMax:最小値を受け取る変数への参照 |
| 戻り値: |
なし |
通常はページサイズを足し引きすればいいのですが、最大値、最小値を超えないようにしないといけません。
最後にエディットボックスの値も更新し、UpdateData(FALSE)関数で表示を更新します。
では、ビルドして実行してみましょう。スライダのつまみをドラッグすると、現在の値が更新されます。また、つまみ以外の部分をクリックすると、つまみが移動し、現在の値が更新されます。

|