Custom Window Border



  • Hello,

    I currently try to create a QMainWindow with an custom window border on Windows. My current code is:

    bool MainWindow::nativeEvent(const QByteArray &eventType,
        void *msg, long *result) {
        auto win_msg = static_cast<MSG*>(msg);
        auto message = win_msg->message;
        auto wParam = win_msg->wParam;
        auto lParam = win_msg->lParam;
    
        if (message == WM_CREATE)
            int i = 0;
    
        if (message == WM_CREATE || message == WM_ACTIVATE
            || message == WM_NCCALCSIZE || message == WM_NCHITTEST) {
            auto forward = true;
            auto win_result = (LRESULT)0;
            auto hwnd = (HWND)winId();
            auto dwm_enabled = (BOOL)FALSE;
            auto hr = DwmIsCompositionEnabled(&dwm_enabled);
            if (SUCCEEDED(hr)) {
                forward = !DwmDefWindowProc(hwnd, message,
                    wParam, lParam, &win_result);
    
                switch (message) {
                case WM_CREATE: {
                    RECT rcClient;
                    GetWindowRect(hwnd, &rcClient);
    
                    // Inform application of the frame change.
                    SetWindowPos(hwnd, NULL,
                        rcClient.left, rcClient.top,
                        rcClient.right - rcClient.left,
                        rcClient.bottom - rcClient.top,
                        SWP_FRAMECHANGED);
    
                    forward = true;
                    win_result = 0;
                    break;
                }
                case WM_ACTIVATE: {
                    MARGINS margins;
    
                    margins.cxLeftWidth = 0;
                    margins.cxRightWidth = 0;
                    margins.cyBottomHeight = 0;
                    margins.cyTopHeight = 0;
    
                    hr = DwmExtendFrameIntoClientArea(hwnd, &margins);
    
                    if (!SUCCEEDED(hr))
                    {
                        // Handle error.
                    }
    
                    forward = true;
                    win_result = 0;
                    break;
                }
                case WM_NCCALCSIZE: {
                    if (wParam == TRUE) {
                        NCCALCSIZE_PARAMS *params =
                            reinterpret_cast<NCCALCSIZE_PARAMS*>(lParam);
                        params->rgrc[0].left = params->rgrc[0].left + 5;
                        params->rgrc[0].top = params->rgrc[0].top + 0;
                        params->rgrc[0].right = params->rgrc[0].right - 5;
                        params->rgrc[0].bottom = params->rgrc[0].bottom - 5;
                        forward = false;
                        win_result = 0;
                    }
                    break;
                }
                case WM_NCHITTEST: {
                    if (win_result == 0) {
                        auto mouse_pos = POINT{ LOWORD(lParam), HIWORD(lParam) };
                        RECT window_rect;
                        GetWindowRect(hwnd, &window_rect);
                        RECT frame_rect = { 0 };
                        AdjustWindowRectEx(&frame_rect,
                            WS_OVERLAPPEDWINDOW & ~WS_CAPTION, FALSE, NULL);
                        auto row = (USHORT)1;
                        auto col = (USHORT)1;
                        auto resize_border = false;
                        if (mouse_pos.y >= window_rect.top
                            && mouse_pos.y < window_rect.top + 30) {
                            resize_border =
                                (mouse_pos.y < (window_rect.top - frame_rect.top));
                            row = 0;
                        }
                        else
                            if (mouse_pos.y < window_rect.bottom
                                && mouse_pos.y >= window_rect.bottom)
                                row = 2;
                        if (mouse_pos.x >= window_rect.left
                            && mouse_pos.x < window_rect.left)
                            col = 0;
                        else
                            if (mouse_pos.x < window_rect.right
                                && mouse_pos.x >= window_rect.right)
                                col = 2;
    
                        LRESULT result_map[3][3] = {
                            { HTTOPLEFT, resize_border ? HTTOP : HTCAPTION, HTTOPRIGHT },
                            { HTLEFT, HTNOWHERE, HTRIGHT },
                            { HTBOTTOMLEFT, HTBOTTOM, HTBOTTOMRIGHT },
                        };
    
                        win_result = result_map[row][col];
                        if (win_result != HTNOWHERE)
                            forward = false;
                    }
                    break;
                }
                }
            }
    
            if (!forward) {
                *result = win_result;
                return true;
            }
        }
    
        return QWidget::nativeEvent(eventType, msg, result);
    }
    
    void MainWindow::paintEvent(QPaintEvent *event) {
        QPainter p(this);
        p.setPen(Qt::NoPen);
    
        p.setBrush(QBrush(QColor("#bbdefb")));
        p.drawRect(0, 0, geometry().width(), geometry().height());
    
        p.setBrush(QBrush(QColor("#2196f3")));
        p.drawRect(0, 0, geometry().width(), 30);
    
        QMainWindow::paintEvent(event);
    }
    

    The problem is, them main winow then looks like this:
    0_1488728775996_mainwindow.png

    So it seems, that the sizes of the drawing area are not calculated correctly given the customizations I made.
    Does anybody know a solution to this?

    Regards


  • Moderators

    Hi, and welcome. The image upload function on our forum is broken, the uploaded images might be visible to you, but they aren't to anyone else. See this thread for a workaround.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.