protected:Qt帮助下对这个函数做了介绍: This special event handler can be reimplemented in a subclass to receive native Windows events which are passed in themessage parameter. In your reimplementation of this function, if you want to stop the event being handled by Qt, return true and setresult to the value that the window procedure should return. If you return false, this native event is passed back to Qt, which translates the event into a Qt event and sends it to the widget.(英语不太好久不在这边显摆翻译了)。实现了这个方法,就能捕获windows的他的一些事件啦~ 1.首先,我是想去掉windows自带的标题栏,这样我就可以绘制自己要的最大化,最小化,关闭按钮等等。 直接在窗体构造函数里加入代码
virtual bool winEvent(MSG *message, long *result);
SetWindowLong(this->winId(), GWL_STYLE, GetWindowLong(this->winId(), GWL_STYLE) & ~WS_CAPTION);由于我的电脑是win10的,win10的效果就这这样的!是不是感觉成功大半了!接下来的就交给我们上面提到的那个方法吧。 1.要自己实现WM_NCPAINT函数的处理,来自己绘制自己想要的窗体边框:
<span style="white-space:pre"></span>HWND hwnd = message->hwnd;2.接着实现WM_NCCALCSIZE当窗体移动或者改变大小时来重新规定他的客户区大小:
WPARAM wParam = message->wParam;
WPARAM lParam = message->lParam;
if (message->message == WM_NCPAINT)
{
RECT rc;
GetClientRect(hwnd,&rc);
RECT rcWnd;//窗口坐标
GetWindowRect(hwnd,&rcWnd);
ScreenToClient(hwnd,(LPPOINT)&rcWnd.left);// 将窗口坐标转换为客户坐标
ScreenToClient(hwnd,(LPPOINT)&rcWnd.right);
rc.left -= rcWnd.left; //计算得到窗口内新的客户区域坐标
rc.top -= rcWnd.top;
rc.right += rc.left;
rc.bottom += rc.top;
HDC hdc = GetWindowDC(hwnd);
//现在rc是一个新的窗口内的客户区坐标
ExcludeClipRect(hdc,rc.left,rc.top,rc.right,rc.bottom); //不刷新客户区域
InflateRect(&rc,m_nThickness,m_nThickness); // 将客户区域坐标扩大WIDTH
//在客户区域的外围画一个红色边框
HBRUSH hBr;
int r,g,b;
if (!m_ncActived)
{
m_ncUnActivedColor.getRgb(&r,&g,&b);
}
else
{
m_ncActivedColor.getRgb(&r,&g,&b);
}
hBr = CreateSolidBrush(RGB(r,g,b));
FillRect(hdc,&rc, hBr);
ReleaseDC(hwnd,hdc);
return 1;
}
<span style="white-space:pre"></span>else if (message->message == WM_NCCALCSIZE)3.最后来实现下WM_NCACTIVATE,当窗体非客户区失去焦点和得到焦点对边框进行换色处理
{
NCCALCSIZE_PARAMS* ncParams = (NCCALCSIZE_PARAMS* )lParam;
RECT rect0 = ncParams->rgrc[0];
rect0.left+=m_nThickness;
rect0.top+=m_nThickness;
rect0.right -= m_nThickness;
rect0.bottom -= m_nThickness;
ncParams->rgrc[0] = rect0;
*result =0;
return 1;
}
<span style="white-space:pre"></span>else if (message->message == WM_NCACTIVATE)4.当然最后对另外的事件还是要让Qt自己去处理咯:
{
if (m_ncActived!=(bool)wParam)
{
m_ncActived = wParam;
SendMessage(hwnd,WM_NCPAINT,1,0);
}
*result =1;
return 1;
}
return QWidget::winEvent(message,result);来看看效果吧,窗体在激活状态下(红色区域是客户区):
然后是非激活状体下 窗体的拉伸完全是系统自带的哦,而且能够响应win的自带的事件:
PS:当然这样的窗体还是不完美的还存在一些问题:1、去掉了标题栏,就会失去标题栏的一些事件响应,比如鼠标按住标题栏拖到桌面边缘也能进行自动布局这样也很方便,当然也是有办法可以让他实现的,通过重写WM_NCHITTEST来把客户区一块区域模拟成标题栏(这边就不实现了,代码也很简单的)。2、不同系统的所需边框宽度是不同win7下m_nThickness定义为3就是像素为3的边框,win10下会有误差。3、求大神指教如何把win10顶部的白条去掉!!!!