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



  • 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.