控制两个CListView同步滚动

本文介绍了一种使用CListView实现双列表同步滚动的方法,通过自定义滚动逻辑,解决了滑块移动时不同步的问题。

在图像编程中,经常要查看矩阵数组中的元素值,大量的数据在调试窗口中查看是特别麻烦的,于是我想着,能不能编写一个表格一样的东西,在需要的时候让它直接弹出来显示。

我的思路是这样的,在一个对话框上放置一个CListView,设置成列表风格,然后把数据插入到列表中,这样还不用自己写滚动条。(如何在对话框上放置CListView可以参考sanbiangongzi.bokee.com/1733920.html)。但是在编程中发现,CListView的列表风格没有行方向的表头,当然可以自己插入一列数据作为表头,但是这样的话,在水平滚动条向右滑动的过程中,行方向的表头就会移出对话框,总感觉这样不是很方便。于是我在对话框的左边又放置了一个CListView做行方向的表头,这样就牵扯到一个问题,如何控制两个CListView同步滚动。

在网上找了很久,再加上自己摸索,我的方法是这样的:

假设CMatrixLeftHeader和CMatrixView继承自CListView,分别用来显示行方向的表头和矩阵数据。在CMatrixView中设置CMatrixLeftHeader的指针,用CMatrixView的滚动条来控制二者同步滚动。重写CMatrixView的OnVScroll方法,在其滚动条动作触发的同时向CMatrixLeftHeader发送滚动消息。

新的问题又出现了,如果CMatrixLeftHeader的滚动条要显示的话(不设置 LVS_NOSCROLL),按行滚动和翻页都可以成功,但滑块移动却不行(网上说是因为CListView的假窗口的原因),如果禁用CMatrixLeftHeader的滚动条(设置 LVS_NOSCROLL),就只有按行滚动可以成功,其他都不行。

::SendMessage(m_hWnd,WM_VSCROLL,MAKEWPARAM(SB_LINEDOWN,0),NULL);//可以成功下滚1行
::SendMessage(m_hWnd,WM_VSCROLL,MAKEWPARAM(SB_PAGEDOWN,0),NULL);//可以成功下滚1页
::SendMessage(m_hWnd,WM_VSCROLL,MAKEWPARAM(SB_THUMBTRACK,nPos),NULL);    //不成功
::SendMessage(m_hWnd,WM_VSCROLL,MAKEWPARAM(SB_THUMBPOSITION,nPos),NULL); //不成功

我的做法是,用按行滚动来获得翻页以及滑块移动时的效果。在CMatrixView里设置一成员变量m_nCurrFirstRow记录当前处在视图第一行的行号,用SCROLLINFO类型的变量可以获得当前列表的最小最大行号(nMin,nMax),包括每页的行数(nPage),这样需要滚动到什么地方就让它逐行滚动到那里。

void CMatrixView::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
	// TODO: Add your message handler code here and/or call default
	switch (nSBCode)
    {
    case SB_LINEDOWN:
		ListLineDown(m_pLeftHeader->m_hWnd);
        break;

    case SB_LINEUP:
		ListLineUp(m_pLeftHeader->m_hWnd);
        break;

    case SB_PAGEDOWN:
		ListPageDown(m_pLeftHeader->m_hWnd);
        break;

    case SB_PAGEUP:
		ListPageUp(m_pLeftHeader->m_hWnd);
        break;

    case SB_THUMBPOSITION:
        ListThumbPosition(m_pLeftHeader->m_hWnd,nPos);
        break;

    case SB_THUMBTRACK:
        ListThumbTrack(m_pLeftHeader->m_hWnd,nPos);
        break;

    default:
        break;
    } 
   	
	CListView::OnVScroll(nSBCode, nPos, pScrollBar);
}

同步控制函数如下:

void CMatrixView::ListLineDown(HWND hWnd)
{
	SCROLLINFO info;
    GetScrollInfo(SB_VERT,&info,SIF_ALL);

	if(m_nCurrFirstRow<=info.nMax-info.nPage)
	{
		::SendMessage(hWnd,WM_VSCROLL,SB_LINEDOWN,0);		
		m_nCurrFirstRow++;
	}
}

void CMatrixView::ListLineUp(HWND hWnd)
{
	SCROLLINFO info;
    GetScrollInfo(SB_VERT,&info,SIF_ALL);

	if(m_nCurrFirstRow>0)
	{
		::SendMessage(hWnd,WM_VSCROLL,SB_LINEUP,0);
		m_nCurrFirstRow--;
	}
}

void CMatrixView::ListPageDown(HWND hWnd)
{
	SCROLLINFO info;
    GetScrollInfo(SB_VERT,&info,SIF_ALL);

	int n=min(info.nPage, info.nMax-info.nPage-m_nCurrFirstRow+1);
	for(int i=0;i<n;i++)
	{
		::SendMessage(hWnd,WM_VSCROLL,SB_LINEDOWN,0);
		m_nCurrFirstRow++;
	}
}

void CMatrixView::ListPageUp(HWND hWnd)
{
	SCROLLINFO info;
    GetScrollInfo(SB_VERT,&info,SIF_ALL);

	int n=min(info.nPage, m_nCurrFirstRow);
	for(int i=0;i<n;i++)
	{
		::SendMessage(hWnd,WM_VSCROLL,SB_LINEUP,0);
		m_nCurrFirstRow--;
	}
}

void CMatrixView::ListThumbPosition(HWND hWnd,UINT nPos)
{
	SCROLLINFO info;
    GetScrollInfo(SB_VERT,&info,SIF_ALL);
	
	if(nPos>m_nCurrFirstRow)
	{
		int n=nPos-m_nCurrFirstRow;
		for(int i=0;i<n;i++)
		{
			::SendMessage(hWnd,WM_VSCROLL,SB_LINEDOWN,0);
			m_nCurrFirstRow++;
		}
	}
	else
	{
		int n=m_nCurrFirstRow-nPos;
		for(int i=0;i<n;i++)
		{
			::SendMessage(hWnd,WM_VSCROLL,SB_LINEUP,0);
			m_nCurrFirstRow--;
		}
	}	
}

void CMatrixView::ListThumbTrack(HWND hWnd,UINT nPos)
{
	SCROLLINFO info;
    GetScrollInfo(SB_VERT,&info,SIF_ALL);
	
	if(nPos>m_nCurrFirstRow)
	{
		int n=nPos-m_nCurrFirstRow;
		for(int i=0;i<n;i++)
		{
			::SendMessage(hWnd,WM_VSCROLL,SB_LINEDOWN,0);
			m_nCurrFirstRow++;
		}
	}
	else
	{
		int n=m_nCurrFirstRow-nPos;
		for(int i=0;i<n;i++)
		{
			::SendMessage(hWnd,WM_VSCROLL,SB_LINEUP,0);
			m_nCurrFirstRow--;
		}
	}	
}
当对话框的窗口拉大到超过列表最大行数的时候,CMatrixView的滚动条会回滚,这里我们同样要控制CMatrixLeftHeader回滚,相关函数如下:
void CMatrixView::ListScrollPageChange(HWND hWnd)
{
	SCROLLINFO info;
    GetScrollInfo(SB_VERT,&info,SIF_ALL);
	
	int n=m_nCurrFirstRow+info.nPage-info.nMax-1;	
	for(int i=0;i<n;i++)
	{
		::SendMessage(hWnd,WM_VSCROLL,SB_LINEUP,0);	
		m_nCurrFirstRow--;
	}
}

可以看到,整个控制过程只要算清楚滚动的行数即可。至此,两个CListView就可以实现同步滚动了。效果如以下网址中所示:

http://my.youkuaiyun.com/my/album/detail/1154049

http://my.youkuaiyun.com/my/album/detail/1154050



非常好用的CListCtrl加强版。 从CListCtrl继承,完全兼容CListCtrl. 它有以下特性: • The background of the sorted column can be displayed in a different color (like the detailed view of Windows XP Explorer). • The header of the sorted column can display an arrow that indicates the sort direction (like the detailed view of Windows XP Explorer). • You can give the user the opportunity to hide or redisplay selected columns by just clicking on the header control with the right mouse button (see picture below). • You can hide or redisplay a selected column entirely. • In contrast to the original list view control, the first column can have the LVCFMT_CENTER or LVCFMT_RIGHT style, too. For this feature, the list view control must have the LVS_OWNERDRAWFIXED style. • The label attributes state icon, small icon, and selection can always be shown in the leftmost column, independent of the order of the columns. For this feature, the listview control must have the LVS_OWNERDRAWFIXED style. • You can supply tooltips not only for the whole item, but also for the small icon, the state icon, and each subitem label. • The extended styles LVS_EX_CHECKBOXES, LVS_EX_ONECLICKACTIVATE, LVS_EX_SUBITEMIMAGES, LVS_EX_TWOCLICKACTIVATE, and LVS_EX_UNDERLINEHOT will be supported even if the list view control has the LVS_OWNERDRAWFIXED style. • If the LVS_EX_CHECKBOXES style has been applied and a selected item will be checked/unchecked, all other selected items will be checked/unchecked, too. • If the LVS_EX_LABELTIP style has been applied, not only the partially hidden text of the item label will be unfolded but also the partially hidden text of each subitem label. Note: The LVS_EX_LABELTIP style will be supported under all operating systems. • Tooltips and expanded labels can be displayed simultaneously. • The current state of the list view control (column widths, column order, hidden columns, and sort column and direction) can be saved and restored.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值