0

我从其他已问但未回答的问题中复制了下面的问题描述,因为这与我想问的问题完全相同。

我有一个带有半透明背景和圆形边缘(边框半径)的 QMenu。不幸的是,Windows 7 为这个菜单绘制了一个阴影,它不适合圆角。它是为普通矩形菜单绘制的阴影。

有没有一种方法可以完全禁用 QMenu 的绘制阴影,或者有一种方法可以使阴影适合圆形边缘?

这是它发生的简约示例:

QPushButton b("press me");
QMenu m;
m.addAction("hello"); m.addAction("world");
m.setWindowFlags(m.windowFlags() | Qt::FramelessWindowHint);
m.setAttribute(Qt::WA_TranslucentBackground);
m.setStyleSheet("background:rgba(255,0,0,50%); border-radius:5px;");
b.setMenu(&m);
b.show();

现在我必须手动关闭 Windows 控制面板中的菜单阴影才能消除该阴影。实际上我想要存档的是像qt的饼菜单这样的菜单,或者像这样的菜单:http: //upload.wikimedia.org/wikipedia/commons/8/85/Blender_2.36_Screenshot.jpg 我尝试了弹出窗口小部件,但它得到了上面描述的影子神器。任何人都可以帮助解决这个问题吗?

4

2 回答 2

1

在 Windows Vista 和更高版本上,我想要一个带有正常窗口阴影的菜单。所以我必须做两件事:

  1. CS_DROPSHADOW从菜单HWND中删除WNDCLASSQt 在核心深处添加的内容。
  2. 使用 DWM API 添加阴影。

诀窍是捕获QEvent::WinIdChange以获取HWND菜单窗口的句柄,然后使用GetClassLong/SetClassLong删除CS_DROPSHADOW标志。我只这样做一次(通过使用 a static bool),因为WNDCLASS所有菜单的 总是相同的。如果您的应用程序的一部分想要显示菜单阴影而其他部分不想要,这可能会导致问题。

我已经子类化了QMenu,并且在创建菜单时我总是使用我的覆盖类

Menu * my_menu = new Menu(tr("&File"));
mainMenu->addMenu(my_menu);

这是整个代码,享受:

菜单.h

#ifndef MENU_H
#define MENU_H

#include <QMenu>

class Menu : public QMenu
{
    Q_OBJECT
public:
    explicit Menu(QWidget *parent = 0);
    explicit Menu(const QString & title);

protected:
    virtual bool event(QEvent *event);

signals:

public slots:

};

#endif // MENU_H

菜单.cpp

#include "menu.h"

#pragma comment( lib, "dwmapi.lib" )
#include "dwmapi.h"

Menu::Menu(QWidget *parent) :
    QMenu(parent)
{

}

Menu::Menu(const QString &title) :
    QMenu(title)
{

}



bool Menu::event(QEvent *event)
{
    static bool class_amended = false;
    if (event->type() == QEvent::WinIdChange)
    {
        HWND hwnd = reinterpret_cast<HWND>(winId());
        if (class_amended == false)
        {
            class_amended = true;
            DWORD class_style = ::GetClassLong(hwnd, GCL_STYLE);
            class_style &= ~CS_DROPSHADOW;
            ::SetClassLong(hwnd, GCL_STYLE, class_style);
        }
        DWMNCRENDERINGPOLICY val = DWMNCRP_ENABLED;
        ::DwmSetWindowAttribute(hwnd, DWMWA_NCRENDERING_POLICY, &val, sizeof(DWMNCRENDERINGPOLICY));

        // This will turn OFF the shadow
        // MARGINS m = {0};
        // This will turn ON the shadow
        MARGINS m = {-1};
        HRESULT hr = ::DwmExtendFrameIntoClientArea(hwnd, &m);
        if( SUCCEEDED(hr) )
        {
            //do more things
        }
    }
    return QWidget::event(event);
}
于 2013-03-02T12:28:23.287 回答
0

我只是删除 Qt::popup 标志来摆脱阴影。而且我必须将关闭代码添加到任何其他后台 UI。这些是更多的额外工作,但我得到了我想要的:)

于 2012-12-09T02:46:14.977 回答