Windows Vista 以降では、通常のウィンドウ シャドウのメニューが必要でした。そのため、次の 2 つのことを行う必要がありました。
- Qtがコアの奥深くに追加している
CS_DROPSHADOW
メニューから削除します。HWND
WNDCLASS
- DWM API を使用してシャドウを追加します。
コツは、キャプチャしてメニュー ウィンドウのハンドルをQEvent::WinIdChange
取得し、/を使用してフラグを削除することです。はすべてのメニューで常に同じであるため、これを ( を使用して) 1 回だけ実行しています。これは、アプリの一部がメニュー シャドウを表示する必要があり、他の部分が表示しない場合、問題につながる可能性があります。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
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);
}