由来:
现在大量的软件采用简洁的风格,即移除系统的标题栏及边框并自己实现标题栏以达到定制的目的,由于我们写要用Qt写一个类似IM的软件,故有此需求。
方法:
去除系统边框比较简单,setFlags(Qt::Window | Qt::FramelessWindowHint);即可,但下一步要实现窗体的拖拽和缩放。
1,最简单的方法:
这种方法比较简单直观,即点击鼠标的时候记录下鼠标位置,然后在鼠标移动的时候对窗体进行移动。示例代码如下:
MouseArea { //为窗口添加鼠标事件
property int xMouse //存储鼠标x坐标
property int yMouse //存储鼠标y坐标
anchors.fill: parent
acceptedButtons: Qt.LeftButton //只处理鼠标左键
drag.filterChildren: true
onPressed: { //接收鼠标按下事件
xMouse = mouse.x
yMouse = mouse.y
}
onPositionChanged: { //鼠标按下后改变位置
loginScreen.x = loginScreen.x + (mouse.x - xMouse)
loginScreen.y = loginScreen.y + (mouse.y - yMouse)
}
}
以上方法简单直观,但当窗体比较复杂的时候将发生窗体移动比较迟钝,甚至,当从上标题快速拖拽窗体时,鼠标移出窗体,而窗体不再移动的问题。
网上的一个案例,大家可以参考http://blog.sina.com.cn/s/blog_a6fb6cc90101au8r.html
2,改进方案:
观察系统默认的带标题栏的窗体,发现,拖动窗体时,窗体并不移动,而是由一个矩形框随着鼠标移动,当松开鼠标后窗体才进行一次性地移动。
于是,有了一个可行的方案(因为后面有更优的方案,但是如果后面的方案不行,这个方案可能成为最后的方案),当拖拽的时候绘制一个移动的和原窗体等大小的矩形进行移动,最后再一次性地移动(相信系统的拖拽也是采用类似的方案)。具体实施略,可以自行测试。
3,继续改进方案,应该是一个较优方案:
具体原理我也是参照这个博客http://blog.sina.com.cn/s/blog_6288219501015dwa.html,讲得比较详细,虽然是mfc程序,但毕竟也是windows程序,原理相同。
摘抄一段:
当窗口确定鼠标位置时,Windows向窗口发送WM_NCHITTEST消息,可以处理该消息,使得只要鼠标在窗口内,Windows便认为鼠标在标题条上。这需要重载CWnd类处理WM_NCHITTEST消息的OnNcHitTest函数,在函数中调用父类的该函数,如果返回HTCLIENT,说明鼠标在窗口客户区内,使重载函数返回HTCAPTION,使Windows误认为鼠标处于标题条上。
UINT MyWndDlg::OnNcHitTest(CPoint point)
{
// 取得鼠标所在的窗口区域
UINT nHitTest = CDialog::OnNcHitTest(point);
// 如果鼠标在窗口客户区,则返回标题条代号给Windows