【问题标题】:How to keep control box responsive when draw at the non client area在非客户区绘制时如何保持控制框响应
【发布时间】:2013-05-31 00:42:45
【问题描述】:

我正在使用以下代码来绘制在我的窗口的非客户区延伸的图像。代码有效,但控制框(最小化、最大化和关闭按钮)保持无响应,单击时没有任何反应。如何在非客户区绘制以保持我的控制框响应?

这是我在 Windows 7 上运行的应用程序的屏幕截图:

还有我的代码:

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    WTA_OPTIONS ops;
    ops.dwFlags = WTNCA_NODRAWCAPTION | WTNCA_NODRAWICON;
    ops.dwMask = WTNCA_NODRAWCAPTION | WTNCA_NODRAWICON;
    SetWindowThemeNonClientAttributes(winId(), ops.dwMask, ops.dwFlags);

    MARGINS margins = {-1};
    DwmExtendFrameIntoClientArea(winId(), &margins);
}

bool MainWindow::winEvent(MSG *pMessage, long *result)
{
    HWND hWnd = pMessage->hwnd;
    UINT message = pMessage->message;
    WPARAM wParam = pMessage->wParam;
    LPARAM lParam = pMessage->lParam;

    DwmDefWindowProc(hWnd, message, wParam, lParam, NULL);

    if(message == WM_PAINT)
    {
        HDC hDC = GetWindowDC(hWnd);
        PaintCustomCaption(hWnd, hDC);
        DeleteDC(hDC);
        return true;
    }

    if(message == WM_NCCALCSIZE) return true;

    if(message == WM_NCHITTEST) return true;

    return QWidget::winEvent(pMessage, result);
}

QPixmap pixmap;

void MainWindow::PaintCustomCaption(HWND hWnd, HDC hdc)
{
    RECT rcClient;
    GetClientRect(hWnd, &rcClient);

    HDC hdcPaint = CreateCompatibleDC(hdc);

    HDC hdcRes = CreateCompatibleDC(hdc);

    if (pixmap.isNull()) pixmap = QPixmap("png.png");

    HBITMAP hBmpRes = pixmap.toWinHBITMAP(QPixmap::PremultipliedAlpha);

    SIZE szBmpRes;
    BITMAP rBitmap;
    GetObject(hBmpRes, sizeof (BITMAP), &rBitmap);
    szBmpRes.cx = rBitmap.bmWidth;
    szBmpRes.cy = rBitmap.bmHeight;

    HBITMAP hOldBmpRes = (HBITMAP)SelectObject(hdcRes, hBmpRes);

    if (hdcPaint)
    {
        int cx = rcClient.right - rcClient.left;
        int cy = rcClient.bottom - rcClient.top;

        BITMAPINFO dib = {0};
        dib.bmiHeader.biSize            = sizeof(BITMAPINFOHEADER);
        dib.bmiHeader.biWidth           = cx;
        dib.bmiHeader.biHeight          = -cy;
        dib.bmiHeader.biPlanes          = 1;
        dib.bmiHeader.biBitCount        = 32;
        dib.bmiHeader.biCompression     = BI_RGB;

        HBITMAP hbm = CreateDIBSection(hdc, &dib, DIB_RGB_COLORS, NULL, NULL, 0);

        if (hbm)
        {
            HBITMAP hbmOld = (HBITMAP)SelectObject(hdcPaint, hbm);
            BitBlt(hdcPaint, 0, 0, cx, cy, hdcRes, 0, 0, SRCCOPY);
            BitBlt(hdc, 0, 0, cx, cy, hdcPaint, 0, 0, SRCCOPY);
            SelectObject(hdcPaint, hbmOld);
            DeleteObject(hbm);
        }
        DeleteDC(hdcPaint);
    }
    SelectObject(hdcRes, (HBITMAP)hOldBmpRes);
    DeleteObject(hBmpRes);
    DeleteDC(hdcRes);
}

【问题讨论】:

    标签: c++ image qt nonclient-area


    【解决方案1】:

    经过几次尝试,我将其编写为代码以绘制在 Qt 窗口的非客户区扩展的图像,并在 Windows 7 下进行了测试。

    结果截图:

    以及相关代码:

    在 .pro 文件中:

    LIBS += -lGdi32
    LIBS += -lUser32
    LIBS += -lDwmApi
    LIBS += -lUxTheme
    

    在头文件处:

    #include <dwmapi.h>
    
    #define LEFTEXTENDWIDTH 8
    #define RIGHTEXTENDWIDTH 8
    #define BOTTOMEXTENDWIDTH 20
    #define TOPEXTENDWIDTH 161
    
    private slots:
        void PaintCustomCaption(HWND hWnd, HDC hdc);
        LRESULT HitTestNCA(HWND hWnd, LPARAM lParam);
    
    protected:
        bool winEvent(MSG *pMessage, long *result);
    
    private:
        QPixmap pixmap;
    

    终于在cpp文件处:

    bool MainWindow::winEvent(MSG *pMessage, long *result)
    {
        HWND hWnd = pMessage->hwnd;
        UINT message = pMessage->message;
        WPARAM wParam = pMessage->wParam;
        LPARAM lParam = pMessage->lParam;
    
        bool retvalue = false;
        LRESULT lRet = 0;
    
        DwmDefWindowProc(hWnd, message, wParam, lParam, &lRet);
    
        if (message == WM_ACTIVATE)
        {
            MARGINS margins;
    
            margins.cxLeftWidth = LEFTEXTENDWIDTH;
            margins.cxRightWidth = RIGHTEXTENDWIDTH;
            margins.cyBottomHeight = BOTTOMEXTENDWIDTH;
            margins.cyTopHeight = TOPEXTENDWIDTH;
    
            WTA_OPTIONS ops;
            ops.dwFlags = WTNCA_NODRAWCAPTION | WTNCA_NODRAWICON;
            ops.dwMask = WTNCA_NODRAWCAPTION | WTNCA_NODRAWICON;
            SetWindowThemeNonClientAttributes(hWnd, ops.dwMask, ops.dwFlags);
    
            DwmExtendFrameIntoClientArea(hWnd, &margins);
    
            lRet = 0;
            retvalue = false;
        }
    
        if(message == WM_PAINT)
        {
            HDC hDC = GetWindowDC(hWnd);
            PaintCustomCaption(hWnd, hDC);
            DeleteDC(hDC);
            lRet = 0;
            retvalue = true;
        }
    
        if(message == WM_NCCALCSIZE)
        {
            lRet = 0;
            retvalue = true;
        }
    
        if(message == WM_NCHITTEST)
        {
            lRet = HitTestNCA(hWnd, lParam);
            DwmDefWindowProc(hWnd, message, wParam, lParam, &lRet);
            retvalue = true;
        }
    
        *result = lRet;
        if(retvalue) return true;
    
        return QWidget::winEvent(pMessage, result);
    }
    
    void MainWindow::PaintCustomCaption(HWND hWnd, HDC hdc)
    {
        RECT rcClient;
        GetClientRect(hWnd, &rcClient);
    
        HDC hdcPaint = CreateCompatibleDC(hdc);
    
        HDC hdcRes = CreateCompatibleDC(hdc);
    
        if (pixmap.isNull()) pixmap = QPixmap("png.png");
    
        HBITMAP hBmpRes = pixmap.toWinHBITMAP(QPixmap::PremultipliedAlpha);
    
        SIZE szBmpRes;
        BITMAP rBitmap;
        GetObject(hBmpRes, sizeof (BITMAP), &rBitmap);
        szBmpRes.cx = rBitmap.bmWidth;
        szBmpRes.cy = rBitmap.bmHeight;
    
        HBITMAP hOldBmpRes = (HBITMAP)SelectObject(hdcRes, hBmpRes);
    
        if (hdcPaint)
        {
            int cx = rcClient.right - rcClient.left;
            int cy = rcClient.bottom - rcClient.top;
    
            BITMAPINFO dib = {0};
            dib.bmiHeader.biSize            = sizeof(BITMAPINFOHEADER);
            dib.bmiHeader.biWidth           = cx;
            dib.bmiHeader.biHeight          = -cy;
            dib.bmiHeader.biPlanes          = 1;
            dib.bmiHeader.biBitCount        = 32;
            dib.bmiHeader.biCompression     = BI_RGB;
    
            HBITMAP hbm = CreateDIBSection(hdc, &dib, DIB_RGB_COLORS, NULL, NULL, 0);
    
            if (hbm)
            {
                HBITMAP hbmOld = (HBITMAP)SelectObject(hdcPaint, hbm);
                BitBlt(hdcPaint, 0, 0, cx, cy, hdcRes, 0, 0, SRCCOPY);
                BitBlt(hdc, 0, 0, cx, cy, hdcPaint, 0, 0, SRCCOPY);
                SelectObject(hdcPaint, hbmOld);
                DeleteObject(hbm);
            }
            DeleteDC(hdcPaint);
        }
        SelectObject(hdcRes, (HBITMAP)hOldBmpRes);
        DeleteObject(hBmpRes);
        DeleteDC(hdcRes);
    }
    
    LRESULT MainWindow::HitTestNCA(HWND hWnd, LPARAM lParam)
    {
        POINT ptMouse = {(int)(short)LOWORD(lParam), (int)(short)HIWORD(lParam)};
    
        RECT rcWindow;
        GetWindowRect(hWnd, &rcWindow);
    
        RECT rcFrame = { 0 };
        AdjustWindowRectEx(&rcFrame, WS_OVERLAPPEDWINDOW & ~WS_CAPTION, FALSE, NULL);
    
        USHORT uRow = 1;
        USHORT uCol = 1;
        bool fOnResizeBorder = false;
    
        if (ptMouse.y >= rcWindow.top && ptMouse.y < rcWindow.top + TOPEXTENDWIDTH)
        {
            fOnResizeBorder = (ptMouse.y < (rcWindow.top - rcFrame.top));
            uRow = 0;
        }
        else if (ptMouse.y < rcWindow.bottom && ptMouse.y >= rcWindow.bottom - BOTTOMEXTENDWIDTH)
        {
            uRow = 2;
        }
    
        if (ptMouse.x >= rcWindow.left && ptMouse.x < rcWindow.left + LEFTEXTENDWIDTH)
        {
            uCol = 0;
        }
        else if (ptMouse.x < rcWindow.right && ptMouse.x >= rcWindow.right - RIGHTEXTENDWIDTH)
        {
            uCol = 2;
        }
    
        LRESULT hitTests[3][3] =
        {
            { HTTOPLEFT,    fOnResizeBorder ? HTTOP : HTCAPTION,    HTTOPRIGHT },
            { HTLEFT,       HTNOWHERE,     HTRIGHT },
            { HTBOTTOMLEFT, HTBOTTOM, HTBOTTOMRIGHT },
        };
    
        return hitTests[uRow][uCol];
    }
    

    【讨论】:

      猜你喜欢
      • 2011-07-12
      • 2021-12-15
      • 2010-09-11
      • 2012-06-02
      • 1970-01-01
      • 2014-12-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多