MFC滚动条自动对齐:一个grid选中一行另一个grid也选中相同行并且内容和滚动条自动对齐

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ClamReason/article/details/80326333

核心思想是利用gridCtrl的滚动条消息响应。

当我需要让一个gridCtrl的滚动条连同其gridCtrl的内容一起自动滚动到另一个新的合适的位置的时候,我给这个gridCtrl发一个消息SendMessage()

核心代码如下:

m_gridRight.SetScrollPos(SB_VERT, iPos, TRUE);//滚动条滚动
 //内容滚动
m_gridRight.SendMessage(WM_VSCROLL,MAKELONG(SB_THUMBTRACK, iPos),NULL);
m_gridRight.SetCurSel(iSelRowLeft);//设置行选中状态
MFC滚动条技术介绍:

对于滚动条,windows内部封装了WM_VSCROLL和WM_HSCROLL两个标准消息。windows中的消息分为三种:
标准消息:所有以WM_开头的消息,除了WM_Command消息外,都是标准消息,这类消息能够被CWnd类及其派生类直接调用。
命令消息:但但就是WM_Command这种消息。
通告消息:由控件响应的消息,例如BN_Click消息。
我们看下WM_VScroll消息的声明:
afx_msg void OnVScroll( UINT nSBCode, UINT nPos, CScrollBar* pScrollBar );
与所有消息一样,WM_VSSCROLL和WM_HSCROLL也带有wParam和lParam参数,其中lParam参数只用于作为子窗口而创建的滚动条。
在这个函数的声明中第一个参数就是win32里的wParam消息。wParam的高位字在SB_THUMBTRACK时,表示滚动条当前位置,SB_THUMBPOSITION时,表示用户释放鼠标后滚动条最终位置。
参数:nSBCode
指定指示用户滚动请求的滚动条代码。 此参数可以是下列值之一:
基于的SB_BOTTOM 滚动。
SB_ENDSCROLL 结束滚动。
SB_LINEDOWN 向下滚动一行。
SB_LINEUP 滚动一行。
SB_PAGEDOWN 向下滚动一页。
SB_PAGEUP 滚动一页。
为绝对位置的SB_THUMBPOSITION 滚动。 提供当前位置。nPos
SB_THUMBTRACK 拖动到指定位置的滚动框。 提供当前位置。nPos。
为top的SB_TOP 滚动。
我们看下第二个参数nPos,它仅仅是对滚动条代码是 SB_THUMBPOSITION 或 SB_THUMBTRACK进行响应

“如果在被滚动的窗口中含有^符,ScrollWindow将自动隐藏起^符,以防它被擦掉;当滚动结束后再恢复^符。^符的位置相应的被调整过来。 
未被ScrollWindow覆盖的区域不再重画,但该区域会与窗口更新区域组合。应用程序最终收到WM_PAINT的消息,通知它结合区域必须被重画。为了在滚动操作的同时重画未覆盖区域,则应在调用ScrollWindow函数后马上调用UpdateWindow函数。 
如果参数lpRect为NULL,则窗口中的任何子窗口的位置由参数XAmount和Yamount的数值决定偏移;窗体无效(未着色)的区域也偏移。IpRect为NULL时ScrollWindow执行地更快。 
如果参数lpRect不为NULL,则窗口中的子窗口的位置不改变,窗口中无效(未着色)的区域也不偏移。为了防止lpRect不为NULL时更新的问题,需要在调用ScrollWindow前调用UpdateWindow函数重绘窗口。”
在实际编程的时候,你可以调用UpdateWindow函数,因为这个函数的影响不大。ScrollWindow函数的主要作用就是随着滚动条滚动窗口,如果在滚动的区域有信息,则将保存下来,防止因为窗口的移动而覆盖掉。

要实现的效果:


核心代码的实现函数:

1 消息映射增加SelChanged
BEGIN_MESSAGE_MAP(C***Dlg, CChangeDialog)
ON_REGISTERED_MESSAGE(BCGM_GRID_SEL_CHANGED, OnGridSelChanged)
END_MESSAGE_MAP()


OnGridSelChanged 内部根据情况判断当前是要左对齐还是右对齐,下面的代码是左对齐(左侧选中了一行,右侧自动向左对齐也跟着动起来动起来)

// 根据一个grid的选中行,让另一个grid也选中相同行
void C***Dlg::DressToTheLeft(int& _preLeftLine, int& _preRightLine)
{
	auto iSelRowLeft = _preLeftLine = _preRightLine = m_gridLeft.GetCurSel()->GetRowId();
	if (m_gridRight.GetRowCount()-1 < iSelRowLeft)
	{
		return;
	}
	int iPos = m_gridLeft.GetScrollPos(SB_VERT);
	//另一侧滚动条也设置到左侧同样的位置
	m_gridRight.SetScrollPos(SB_VERT, iPos, TRUE);//滚动条滚动
 //内容滚动
	m_gridRight.SendMessage(WM_VSCROLL,MAKELONG(SB_THUMBTRACK, iPos),NULL);
	m_gridRight.SetCurSel(iSelRowLeft);//设置行选中状态
}



猜你喜欢

转载自blog.csdn.net/ClamReason/article/details/80326333