Qt实现Windows平台上的拖动标题栏贴边最大化等效果
// 构造函数中要给Widget设置风格 WS_OVERLAPPEDWINDOW
this->setWindowFlags(Qt::FramelessWindowHint);
HWND hwnd = reinterpret_cast<HWND>(this->winId());
DWORD style = GetWindowLong(hwnd, GWL_STYLE);
SetWindowLongPtr(hwnd, GWL_STYLE, style | WS_OVERLAPPEDWINDOW);
bool XX::nativeEvent(const QByteArray &eventType, void *message, long *result)
{
#ifdef Q_OS_WIN32
if (eventType != "windows_generic_MSG")
return false;
MSG* msg = static_cast<MSG*>(message);
QWidget* widget = QWidget::find(reinterpret_cast<WId>(msg->hwnd));
if (!widget)
return false;
switch (msg->message) {
case WM_NCCALCSIZE: {
*result = 0;
return true;
}
//正确判断窗口的边缘, 窗口的标题,以及窗口的客户区
case WM_NCHITTEST: {
int x = GET_X_LPARAM(msg->lParam);
int y = GET_Y_LPARAM(msg->lParam);
QPoint pt = mapFromGlobal(QPoint(x, y));
*result = calculateBorder(pt);
if (*result == HTCLIENT) {
QWidget* tempWidget = this->childAt(pt.x(), pt.y());
if (tempWidget == m_titleBar->customWidget()) {
*result = HTCAPTION;
}
}
return true;
}
case WM_GETMINMAXINFO: {
if (::IsZoomed(msg->hwnd)) {
RECT frame = { 0, 0, 0, 0 };
AdjustWindowRectEx(&frame, WS_OVERLAPPEDWINDOW, FALSE, 0);
frame.left = abs(frame.left);
frame.top = abs(frame.bottom);
widget->setContentsMargins(frame.left, frame.top, frame.right, frame.bottom);
}
else {
widget->setContentsMargins(0, 0, 0, 0);
}
*result = ::DefWindowProc(msg->hwnd, msg->message, msg->wParam, msg->lParam);
return true;
}
break;
default:
break;
}
#endif
return QWidget::nativeEvent(eventType, message, result);
}
#endif
继承QWidget,重写nativeEvent事件