0

以下の質問の説明を、他の質問されたが回答されていない質問からコピーしました。これは、私が聞きたい質問とまったく同じであるためです。

半透明の背景と丸みを帯びたエッジ (border-radius) を持つ 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 以降では、通常のウィンドウ シャドウのメニューが必要でした。そのため、次の 2 つのことを行う必要がありました。

  1. Qtがコアの奥深くに追加しているCS_DROPSHADOWメニューから削除します。HWNDWNDCLASS
  2. DWM API を使用してシャドウを追加します。

コツは、キャプチャしてメニュー ウィンドウのハンドルをQEvent::WinIdChange取得し、/を使用してフラグを削除することです。はすべてのメニューで常に同じであるため、これを ( を使用して) 1 回だけ実行しています。これは、アプリの一部がメニュー シャドウを表示する必要があり、他の部分が表示しない場合、問題につながる可能性があります。HWNDGetClassLongSetClassLongCS_DROPSHADOWstatic boolWNDCLASS

をサブクラス化し、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);
}
于 2013-03-02T12:28:23.287 に答える
0

Qt::popup フラグを削除して、影を取り除きます。また、他のバックグラウンド UI には終了コードを追加する必要があります。これらは余分な作業でしたが、私は欲しいものを手に入れました:)

于 2012-12-09T02:46:14.977 に答える