没有shaodw的Qt菜单?
我从其他被问但未回答的问题中复制了下面的问题描述,因为这与我想问的问题完全相同 我有一个半透明背景和圆形边缘(边界半径)的QMenu。不幸的是,Windows 7为此菜单绘制了一个阴影,该阴影不适合圆角。它是为普通矩形菜单绘制的阴影 是否有一种方法可以完全禁用QMenu的绘图放置阴影,或者有一种方法可以使阴影适合圆角边缘 下面是一个出现这种情况的极简示例:没有shaodw的Qt菜单?,qt,menu,Qt,Menu,我从其他被问但未回答的问题中复制了下面的问题描述,因为这与我想问的问题完全相同 我有一个半透明背景和圆形边缘(边界半径)的QMenu。不幸的是,Windows 7为此菜单绘制了一个阴影,该阴影不适合圆角。它是为普通矩形菜单绘制的阴影 是否有一种方法可以完全禁用QMenu的绘图放置阴影,或者有一种方法可以使阴影适合圆角边缘 下面是一个出现这种情况的极简示例: QPushButton b("press me"); QMenu m; m.addAction("hello"); m.addAction(
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的饼状菜单的菜单,或者是这样的菜单:
我尝试了弹出窗口小部件,但它得到了上面描述的阴影工件。
谁能帮上忙 我只是删除了Qt::popup标志以去除阴影。
我必须给任何其他后台用户界面添加关闭代码。这些都是额外的工作,但我得到了我想要的:)在WindowsVista和更高版本上,我想要一个带有普通窗口阴影的菜单。所以我必须做两件事:
HWND
的WNDCLASS
中删除CS\u DROPSHADOW
QEvent::WinIdChange
以获取菜单窗口的HWND
句柄,然后使用GetClassLong
/SetClassLong
删除CS\u DROPSHADOW
标志。我只做了一次(通过使用静态bool
),因为WNDCLASS
对于所有菜单都是相同的。如果应用程序的一部分想要显示菜单阴影,而另一部分不想显示,这可能会导致问题
我已经对QMenu
进行了子类化,并且在创建菜单时总是使用覆盖的类
Menu * my_menu = new Menu(tr("&File"));
mainMenu->addMenu(my_menu);
以下是全部代码,请欣赏:
菜单
#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
\ifndef菜单
#定义菜单
#包括
类菜单:公共QMenu
{
Q_对象
公众:
显式菜单(QWidget*parent=0);
显式菜单(常量字符串和标题);
受保护的:
虚拟布尔事件(QEvent*事件);
信号:
公众时段:
};
#endif//菜单
menu.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);
}
#包括“menu.h”
#pragma注释(lib,“dwmapi.lib”)
#包括“dwmapi.h”
菜单::菜单(QWidget*父项):
QMenu(父项)
{
}
菜单::菜单(常量字符串和标题):
QMenu(标题)
{
}
bool菜单::事件(QEvent*事件)
{
静态布尔类_修正=假;
如果(事件->类型()==QEvent::WinIdChange)
{
HWND HWND=reinterpret_cast(winId());
如果(类_修正==假)
{
第u类修正=真;
DWORD class_风格=::GetClassLong(hwnd,GCL_风格);
class_style&=~CS_DROPSHADOW;
::SetClassLong(hwnd,GCL_样式,class_样式);
}
DWMNCRENDERINGPOLICY val=DWMNCRP_已启用;
::DwmSetWindowAttribute(hwnd、DWMWA_NCRENDERING_POLICY和val、sizeof(DWMNCRENDERINGPOLICY));
//这将关闭阴影
//边距m={0};
//这将打开阴影
边距m={-1};
HRESULT hr=::dwmextendframeintoclienterea(hwnd,&m);
如果(成功(hr))
{
//多做事
}
}
返回QWidget::事件(event);
}
我认为,在这种情况下,您需要选择非本机外观,而不是按默认值使用Qt的本机外观。Qt试图模仿操作系统的小部件。为了显示菜单,Qt使用一个专用窗口(它不只是在底层小部件上绘制菜单)。Windows操作系统决定向Qt无法控制的窗口添加阴影。我唯一的想法是为QMenu尝试不同的窗口标志。否则,不要使用本机QMenu并绘制自己的QMenu。但是事情变得复杂了…谢谢你的回复!说如果我想画我自己的,你能给我更多的提示吗??非常感谢!创建一个显示菜单项的自定义菜单小部件。实现鼠标悬停效果以突出显示当前菜单项。要管理和显示项目,您可以创建一个自定义的MenuItem小部件,或者只对项目使用QStringList,这取决于您希望的灵活性级别以及您希望在这方面投入多少精力。然而,根据你的技能水平,不要期望在几小时或几天内得到合理的结果。。。但是一旦你有了这个,你可以根据你的需要扩展你的菜单。圆角,圆角阴影,动画等等,我强烈建议你重新思考,如果你真的想这样做只是为了实现圆角。我告诉过你你能做些什么来实现这一点,但在我看来,这不值得付出努力。也许其他人知道如何调整QMenu
以禁用本机阴影效果。也许你忽略了一个窗口标志。我刚刚尝试了其他窗口标志,是的,我消除了阴影,但我失去了弹出窗口标志提供的功能:单击菜单区域以外的屏幕区域将关闭菜单。这是一种模仿这些的方法吗?我是否必须向所有其他bg小部件添加关闭代码??至于我自己画菜单,主要问题是我要在哪里画画?如果我在应该拥有这些菜单的小部件上绘制,菜单将不会超出该小部件的框架。所以我必须打开一个全屏透明的小部件,把我的菜单画成它的内容?