C++ 在非客户区绘图时如何保持控制盒响应

C++ 在非客户区绘图时如何保持控制盒响应,c++,image,qt,nonclient-area,C++,Image,Qt,Nonclient Area,我正在使用下面的代码绘制一个图像,该图像在我的窗口的非客户端区域扩展。代码可以工作,但控制框(最小化、最大化和关闭按钮)保持无响应,单击时不会发生任何事情。如何在非客户区绘图,使我的控制箱保持响应 下面是我在Windows 7上运行的应用程序的屏幕截图: 我的代码是: MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi

我正在使用下面的代码绘制一个图像,该图像在我的窗口的非客户端区域扩展。代码可以工作,但控制框(最小化、最大化和关闭按钮)保持无响应,单击时不会发生任何事情。如何在非客户区绘图,使我的控制箱保持响应

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

在几次尝试之后,我编写了这段代码来绘制一个图像,该图像在Qt窗口的非客户端区域扩展,在Windows7下测试

结果截图:

及有关守则:

在.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;
#包括
#定义LEFTEXTENDWIDTH 8
#定义RIGHTEXTENDWIDTH 8
#定义底部延伸宽度20
#定义TOPEXTENDWIDTH 161
专用插槽:
无效标题(HWND HWND,HDC HDC);
LRESULT HitTestNCA(HWND HWND,LPARAM LPARAM);
受保护的:
bool winEvent(MSG*pMessage,long*result);
私人:
QPixmap;
最后,在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];
}
bool主窗口::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);
如果(消息==WM\U激活)
{
利润率;
margins.cxLeftWidth=LEFTEXTENDWIDTH;
margins.cxRightWidth=RIGHTEXTENDWIDTH;
margins.cyBottomHeight=底部延伸宽度;
margins.height=TOPEXTENDWIDTH;
WTA_选项操作;
ops.dwFlags=WTNCA_NODRAWCAPTION | WTNCA_NODRAWICON;
ops.dwMask=WTNCA_NODRAWCAPTION | WTNCA_NODRAWICON;
设置WindowTheMeNonClientAttributes(hWnd、ops.dwMask、ops.dwFlags);
DwmExtendFrameIntoClientArea(硬件和边缘);
lRet=0;
retvalue=false;
}
如果(消息==WM\U PAINT)
{
HDC HDC=GetWindowDC(hWnd);
自定义标题(hWnd、hDC);
DeleteDC(hDC);
lRet=0;
retvalue=true;
}
如果(消息==WM\u NCCALCSIZE)
{
lRet=0;
retvalue=true;
}
如果(消息==WM_NCHITTEST)
{
lRet=HitTestNCA(hWnd,lParam);
DwmDefWindowProc(hWnd、message、wParam、lParam和lRet);
retvalue=true;
}
*结果=lRet;
if(retvalue)返回true;
返回QWidget::winEvent(pMessage,result);
}
void主窗口::PaintCustomCaption(HWND HWND,HDC HDC)
{
RECT-rcClient;
GetClientRect(hWnd和rcClient);
HDC hdcPaint=CreateCompatibleDC(HDC);
HDC hdcRes=创建兼容的数据中心(HDC);
如果(pixmap.isNull())pixmap=QPixmap(“png.png”);
HBITMAP hBmpRes=pixmap.towinhbmap(QPixmap::premultipledalpha);
大小szBmpRes;
位图rBitmap;
GetObject(hBmpRes、sizeof(位图)和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(BitMapInfo头文件);
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_颜色,NULL,NULL,0);
如果(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);
选择对象(hdcPaint、hbmOld);
删除对象(hbm);
}
DeleteDC(hdcPaint);
}
选择对象(hdcRes,(HBITMAP)hOldBmpRes);
删除对象(hBmpRes);
DeleteDC(hdcRes);
}
LRESULT主窗口::HitTestNCA(HWND HWND,LPARAM LPARAM)
{
点ptMouse={(int)(short)LOWORD(lParam),(int)(short)HIWORD(lParam)};
矩形窗口;
GetWindowRect(hWnd和rcWindow);
RECT rcFrame={0};
AdjustWindowRectEx(&rcFrame,WS\u重叠窗口和~WS\u标题,FALSE,NULL);
USHORT-uRow=1;
USHORT-uCol=1;
bool-fOnResizeBorder=false;
if(ptMouse.y>=rcWindow.top&&ptMouse.y=rcWindow.bottom-BOTTOMEXTENDWIDTH)
{
uRow=2;
}
if(ptMouse.x>=rcWindow.left&&ptMouse.x=rcWindow.right-rightedwidth)
{
uCol=2;
}
LRESULT hitTests[3][3]=
{
{httoplight,fOnResizeBorder?HTTOP:HTCAPTION,httoplight},
{HTLEFT,HTNOWHERE,HTRIGHT},
{HTBOTTOMLEFT,HTBOTTOM,HTBOTTOMRIGHT},
};
返回测试[uRow][uCol];
}

几次尝试后,我将此代码写入代码,以绘制一个图像,该图像在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;
#包括
#定义LEFTEXTENDWIDTH 8
#定义RIGHTEXTENDWIDTH 8
#定义底部延伸宽度20
#定义TOPEXTENDWIDTH 161
专用插槽:
无效标题(HWND HWND,HDC HDC);
LRESULT HitTestNCA(HWND HWND,LPARAM LPARAM);
受保护的:
bool winEvent(MSG*pMessage,long*result);
私人:
QPixmap;
最后,在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];
}
bool主窗口::winEvent(MSG*pMessage,long*result)
{
HWND HWND=pMessage->HWND;
UINT message=pMessage->messa