实现无边框窗体的拖动及窗体大小变化

无边框窗体如何实现用鼠标拖动窗体边缘实现窗体大小变动呢?通过以下几个步骤即可实现:
1.实现WM_NCHITTEST消息,实现四条边框的模拟
2.实现WM_NCLBUTTONDOWN,发送窗体拖曳变化的消息
 

具体阐述如下:

1. 实现WM_NCHITTEST消息,实现四条边框的模拟,参考代码如下:

LRESULT CNoBorderWndChangeSizeDlg::OnNcHitTest(CPoint point)  
{  
	// TODO: 在此添加消息处理程序代码和/或调用默认值  
	   
	CRect rect;  
	GetWindowRect(&rect);  
	CRect rect1 = rect;  
	rect1.DeflateRect(10, 10, -10, -10);  
	rect1.NormalizeRect();  
	
	if (point.x <= rect.left+3)  
	    return HTLEFT;  
	else if (point.x >= rect.right-3)  
	    return HTRIGHT;  
	else if (point.y <= rect.top+3)  
	    return HTTOP;  
	else if (point.y >= rect.bottom-3)  
	    return HTBOTTOM;  
	else if (point.x <= rect.left+10 && point.y <= rect.top+10)  
	    return HTTOPLEFT;  
	else if (point.x >= rect.right-10 && point.y <= rect.top+10)  
	    return HTTOPRIGHT;  
	else if (point.x <= rect.left+10 && point.y >= rect.bottom-10)  
	    return HTBOTTOMLEFT;  
	else if (point.x >= rect.right-10 && point.y >= rect.bottom-10)  
	    return HTBOTTOMRIGHT;  
	else if (!rect.IsRectEmpty())  
	{  
	    LRESULT uRet = CWnd::OnNcHitTest(point);  
	    uRet = (uRet == HTCLIENT) ? HTCAPTION : uRet;  
	    return uRet;  
	}  
	else  
	{  
	    return CWnd::OnNcHitTest(point);  
	} 
	 
	return 0;  
} 

2. 实现WM_NCLBUTTONDOWN,发送窗体拖曳变化的消息

void CNoBorderWndChangeSizeDlg::OnNcLButtonDown(UINT nHitTest, CPoint point)  
{  
    // TODO: 在此添加消息处理程序代码和/或调用默认值 
     
    if (nHitTest == HTTOP)  
    {         
        SendMessage( WM_SYSCOMMAND, SC_SIZE | WMSZ_TOP, MAKELPARAM(point.x, point.y));  
    }  
    else if (nHitTest == HTBOTTOM)  
        SendMessage( WM_SYSCOMMAND, SC_SIZE | WMSZ_BOTTOM, MAKELPARAM(point.x, point.y));  
    else if (nHitTest == HTLEFT)  
        SendMessage( WM_SYSCOMMAND, SC_SIZE | WMSZ_LEFT, MAKELPARAM(point.x, point.y));  
    else if (nHitTest == HTRIGHT)  
        SendMessage( WM_SYSCOMMAND, SC_SIZE | WMSZ_RIGHT, MAKELPARAM(point.x, point.y));  
    else if (nHitTest == HTTOPLEFT)  
        SendMessage( WM_SYSCOMMAND, SC_SIZE | WMSZ_TOPLEFT, MAKELPARAM(point.x, point.y));  
    else if (nHitTest == HTTOPRIGHT)  
        SendMessage( WM_SYSCOMMAND, SC_SIZE | WMSZ_TOPRIGHT, MAKELPARAM(point.x, point.y));  
    else if (nHitTest == HTBOTTOMLEFT)  
        SendMessage( WM_SYSCOMMAND, SC_SIZE | WMSZ_BOTTOMLEFT, MAKELPARAM(point.x, point.y));  
    else if (nHitTest == HTBOTTOMRIGHT)  
        SendMessage(WM_SYSCOMMAND, SC_SIZE | WMSZ_BOTTOMRIGHT, MAKELPARAM(point.x, point.y));  
    else if (nHitTest==HTCAPTION)  
        SendMessage(WM_SYSCOMMAND, SC_MOVE | 4, MAKELPARAM(point.x, point.y));  
} 

通常,使用上述的代码即可实现要求。
我们进行一下扩展。在窗体大小发生变化时,有两种表现形式:一种是出现虚线框,一种没有。这个选择依赖于操作系统,你可以右击桌面/属性/外观/效果中通过选择或取消“拖动时显示窗口内容”来表现这两种形式。那么如何在程序中实现而不依赖于当前机器的设置呢(这里的意思是不依赖手动选择“拖动时显示窗口内容”项),我们可以在OnNcLButtonDown函数中通过加入如下的代码实现:

if(nHitTest == HTTOP)  
{         
    SystemParametersInfo(SPI_SETDRAGFULLWINDOWS, TRUE, NULL, 0);  
    SendMessage(WM_SYSCOMMAND, SC_SIZE | WMSZ_TOP, MAKELPARAM(point.x, point.y));  
    SystemParametersInfo(SPI_SETDRAGFULLWINDOWS, FALSE, NULL, 0);  
}  

这段代码意思是在拖动上边缘动作之前,设置“拖动时显示窗口内容”,当该动作结束后,恢复原来的设置。当然,更好的做法是你首先获取机器当前的选项是什么,函数依旧是SystemParametersInfo,只是选项变化,具体查看MSDN即可。
 

实现无边框窗体的拖动及窗体大小变化

上一篇:WPF UI布局(Layout)


下一篇:跟我学Windows Azure 创建Windows Azure试用账号