一个滚动条的问题困扰我很久, 主要是掉进了设备坐标和逻辑坐标的误区, 以及滚动位置取值问题的误区.
测试代码承上做个纪念
Demo程序初始化代码不贴出来了, 过程很简单.
- 创建一个对话框;
- 设置对话框属性, 显示横向滚动条;
- 拖进一个Button,并创建变量ct_btn_add_
- 添加一个横向滚动的消息;
在对话框类里添加了如下变量
CArray<CButton*, CButton*> btns_; // 用来存储创建的Button
int n_btn_id_; // 用于累加Create Button的ID
CButton ct_btn_add_; // 增加Button的按钮,这个是固定的,需要在资源编辑器里托到对话框里
const int BTN_SIZE_; // Button的边长
对话框的初始化, 放在OnInitDialog即可
n_btn_id_ = 5000;
BTN_SIZE_ = 30;
CRect rt_dlg;
GetClientRect(rt_dlg);
CRect rt_btn;
for (int i = 0; i < 10; i++)
{
rt_btn.left = rt_dlg.left + i*BTN_SIZE_;
rt_btn.right = rt_btn.left + BTN_SIZE_;
rt_btn.top = rt_dlg.top;
rt_btn.bottom = rt_btn.top + BTN_SIZE_;
CButton* p_btn = new CButton;
CString cs_btn;
cs_btn.Format(_T("%d"), i+1);
p_btn->Create(cs_btn, 0, rt_btn, this, n_btn_id_++);
p_btn->ShowWindow(SW_SHOW);
btns_.Add(p_btn);
}
CRect rt_add(rt_btn);
rt_add.left = rt_btn.right;
rt_add.right = rt_add.left + BTN_SIZE_;
ct_btn_add_.MoveWindow(rt_add);
SCROLLINFO si;
si.cbSize = sizeof(si);
si.fMask = SIF_PAGE | SIF_RANGE;
si.nMin = 0;
si.nMax = (rt_add.right - rt_dlg.left) - 1;
si.nPage = rt_dlg.Width();
SetScrollInfo(SB_HORZ, &si);
OnHScroll()内容如下
SCROLLINFO si;
si.cbSize = sizeof(si);
si.fMask = SIF_POS | SIF_RANGE | SIF_TRACKPOS | SIF_PAGE;
GetScrollInfo(SB_HORZ, &si);
int xPos = si.nPos;
switch (nSBCode)
{
case SB_LINELEFT:
break;
case SB_LINERIGHT:
break;
case SB_PAGELEFT:
break;
case SB_PAGERIGHT:
break;
case SB_THUMBPOSITION:
{
si.nPos = si.nTrackPos;
break;
}
default:
return;
}
SetScrollInfo(SB_HORZ, &si);
GetScrollInfo(SB_HORZ, &si);
// If the position has changed, scroll the window.
if (si.nPos != xPos)
{
ScrollWindow((xPos - si.nPos), 0);
}
CDialogEx::OnHScroll(nSBCode, nPos, pScrollBar);
增加按钮的Button单击事件OnBnClickedButtonAdd()内容如下
SCROLLINFO si;
si.cbSize = sizeof(si);
si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
GetScrollInfo(SB_HORZ, &si);
int n_btn_count = btns_.GetCount();
CRect rt_dlg;
GetClientRect(rt_dlg);
CRect rt_btn;
int n_test = n_btn_count*BTN_SIZE_;
rt_btn.left = n_test - si.nPos;
rt_btn.right = rt_btn.left + BTN_SIZE_;
rt_btn.top = rt_dlg.top;
rt_btn.bottom = rt_btn.top + BTN_SIZE_;
CButton* p_btn = new CButton;
CString cs_btn;
cs_btn.Format(_T("%d"), n_btn_count+1);
p_btn->Create(cs_btn, 0, rt_btn, this, n_btn_id_++);
p_btn->ShowWindow(SW_SHOW);
btns_.Add(p_btn);
CRect rt_add(rt_btn);
rt_add.left = rt_btn.right;
rt_add.right = rt_add.left + BTN_SIZE_;
ct_btn_add_.MoveWindow(rt_add);
//
n_btn_count = btns_.GetCount();
si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
si.nMin = 0;
si.nMax = n_btn_count*BTN_SIZE_ + BTN_SIZE_ - 1;
si.nPage = rt_dlg.Width();
si.nPos = si.nMax - si.nPage;
SetScrollInfo(SB_HORZ, &si);
ScrollWindow(-BTN_SIZE_, 0);
这样就可以了. 添加按钮后可以实现滚动.
调整对话框大小的功能可以添加在OnSize里, 没什么特别的了.