现在的位置: 首页 > 综合 > 正文

MFC Windows程序设计总结(六)—— 实现可拖动的按钮

2014年09月02日 ⁄ 综合 ⁄ 共 1922字 ⁄ 字号 评论关闭

本篇笔记实现一个可在父窗口中自由拖动的按钮(CButton),并且不允许拖出父窗口(这样就拖不回来了)。

新建类CMovableButton,继承CButton。为CMovableButton添加成员变量bMoving_,并添加WM_LBUTTONDOWN、WM_LBUTTONUP消息处理函数。

void CMovableButton::OnLButtonDown(UINT nFlags, CPoint point)
{
	bMoving_ = true; 
	CButton::OnLButtonDown(nFlags, point);
}

void CMovableButton::OnLButtonUp(UINT nFlags, CPoint point)
{
	bMoving_ = false;
	CButton::OnLButtonUp(nFlags, point);
}

bMoving_在构造函数中初始化为false,用于标记是否正在移动按钮。在OnLButtonDown()中置为true,在OnLButtonUp()中置为false。

为CMovableButton添加WM_MOUSEMOVE消息处理函数,在OnMouseMove()中判断如果bMoving_为true,则想办法移动自己。方法有两种,一种是发消息,另一种是直接调用SetWindowPos(MoveWindow)修改窗口位置。具体看代码:

void CMovableButton::OnMouseMove(UINT nFlags, CPoint point)
{
	if (bMoving_)
	{

#if 1  //Method 1
		ReleaseCapture();

		//Sets dragging of full windows either on or off. 
		//The uiParam parameter specifies TRUE for on, or FALSE for off.
		//::SystemParametersInfo(SPI_SETDRAGFULLWINDOWS, TRUE, NULL, 0);  
		//SendMessage(WM_SYSCOMMAND, /*0xF012*/SC_MOVE|HTCAPTION, 0);

		PostMessage(WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(point.x, point.y));

#else  //Method 2
		ClientToScreen(&point);
		GetParent()->ScreenToClient(&point);

		CRect rcButton;
		GetClientRect(&rcButton);
		point.Offset(-rcButton.Width()/2, -rcButton.Height()/2);

		SetWindowPos(NULL, point.x, point.y, 0, 0, SWP_NOZORDER|SWP_NOSIZE);
		//Invalidate();

#endif
	}

	CButton::OnMouseMove(nFlags, point);
}

这样按钮就可以自由拖动了,还需要限制按钮的拖动范围,否则一旦拖出父窗口外面就拖不回来了。为CMovableButton添加WM_WINDOWPOSCHANGING消息处理函数,作如下处理:

// 防止子窗口移出父窗口
void CMovableButton::OnWindowPosChanging(WINDOWPOS* lpwndpos)
{
	CRect rcParent;
	GetParent()->GetClientRect(&rcParent);
	
	CRect rcButton;
	GetClientRect(&rcButton);
	
	if (lpwndpos->x < rcParent.left)
		lpwndpos->x = rcParent.left;

	if (lpwndpos->y < rcParent.top)
		lpwndpos->y = rcParent.top;

	if (lpwndpos->x + rcButton.Width() > rcParent.right)
		lpwndpos->x = rcParent.right - rcButton.Width();

	if (lpwndpos->y + rcButton.Height() > rcParent.bottom)
		lpwndpos->y = rcParent.bottom - rcButton.Height();
}

这样CMovableButton就完成了,试了一下,可以满足我的需求。这种实现思路同样适用于其他种类的无标题栏的子窗口拖动。

完整测试代码:http://download.csdn.net/detail/zhuyf87/6859133

抱歉!评论已关闭.