在Windows Vista和更高版本中,我想要一個具有普通窗口陰影的菜單。因此,我不得不做兩件事情:
- 從菜單
HWND
的WNDCLASS
使用Qt被添加在覈心深處,刪除CS_DROPSHADOW
。
- 使用DWM API添加陰影。
關鍵是要抓住QEvent::WinIdChange
得到HWND
句柄菜單窗口,然後使用GetClassLong
/SetClassLong
刪除CS_DROPSHADOW
標誌。我只做了一次(使用static bool
),因爲WNDCLASS
對於所有菜單總是相同的。如果你的應用程序的一部分想要顯示菜單陰影而其他則不顯示,則這可能會導致問題。
我有子類的QMenu
和創建菜單
Menu * my_menu = new Menu(tr("&File"));
mainMenu->addMenu(my_menu);
這裏是整個代碼時,我總是用我的被覆蓋的類,可享受:
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);
}
我認爲這種情況下,你想選擇一個非本地外觀和感覺,在本機外觀和感覺,默認情況下使用Qt。 Qt試圖類似於操作系統的小部件。爲了顯示一個菜單,Qt使用了一個專用窗口(它不會簡單地在底層窗口部件上繪製菜單)。 Windows操作系統決定爲這個窗口添加一個陰影,而Qt沒有任何控制權。我唯一的想法是爲QMenu嘗試不同的窗口標誌。否則,請不要使用本機QMenu並繪製自己的。但是這變得複雜... – leemes
感謝您的回覆!說如果我想畫我自己的,你能給我更多的提示嗎?非常感謝! – miguel
創建一個顯示菜單條目的自定義菜單部件。實現鼠標懸停效果以突出顯示當前菜單項。要管理和顯示這些項目,您可以創建一個自定義的MenuItem小部件或僅爲項目使用QStringList,這取決於您想要的靈活性級別以及您想要投入多少努力。但是,根據您的技能水平,不要期望在少於幾個小時或幾天內就能獲得合理的結果......但是,一旦擁有此功能,您可以根據需要擴展菜單。圓角,圓角投影,動畫,... – leemes