簡體   English   中英

在非工作區繪制時如何保持控制盒響應

[英]How to keep control box responsive when draw at the non client area

我正在使用以下代碼繪制在窗口非客戶區域延伸的圖像。 該代碼有效,但是控制框(最小化,最大化和關閉按鈕)保持不響應,單擊時無任何反應。 如何在非客戶區域進行繪制,以使我的控制框保持響應狀態?

這是我在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);
}

經過幾次嘗試,我將此代碼編寫為繪制圖像,該圖像在Windows 7下測試的Qt窗口的非客戶區域擴展。

結果截圖:

屏幕截圖

和相關代碼:

在.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];
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM