Отключить отрисовку фона в JFrame для правильного отображения эффектов Aero (DWM)

У меня проблемы с использованием DWM-функций Windows Vista / 7 в окнах Java. Я хочу, чтобы фон моей рамки был выполнен в стиле Aero. API Windows для этого предоставляется функцией DwmExtendFrameIntoClientArea в библиотеке dwmapi . Мне удалось правильно вызвать процедуру через JNA, и она делает то, что должна (вы можете видеть это, например, при изменении размера кадра, перед следующей перерисовкой вы видите правильные аэроэффекты в еще не окрашенной области, см. прикрепленное изображение).

Но где-то (могу ' t выяснить, где) фон закрашивается поверх эффекта Aero, и эффект теряется.

То, что я уже пробовал:

  • Использование пользовательской ContentPane с непрозрачностью false
  • Установка непрозрачности LayeredPane и RootPane на false
  • Использование Frame вместо JFrame
  • Установить фон цвет JFrame / ContentPane на черный / полностью прозрачный
  • Используйте setLayersOpaque и его собственный вариант, см. первый ответ для получения более подробной информации

Итак далеко мне не удалось удалить этот фон. Это ограничение AWT / Swing? Как мне удалить этот фон или правильно использовать эффект Aero?

Ваша помощь очень признательна.

Снимок экрана

Здесь снимок экрана с кадром без какого-либо содержимого с установкой непрозрачности для RootPane, LayeredPane и ContentPane значения false. Я сделал это быстро при изменении размера. Вы видите, что эффект правильно применен к области, которую Java еще не рисовала.

http://i55.tinypic.com/v614qo.png (Как новый пользователь, я не могу опубликовать изображение напрямую .. .)

Странное поведение

При дальнейшем исследовании я обнаружил следующее странное поведение. Если размер окна составляет 150x150 или меньше, содержимое отображается прозрачно. Это очень неприятно для обычных оконных компонентов. Если вы рисуете прямо на кадре, переопределив метод paint () , все будет отображаться полупрозрачным. Кроме того, система координат кажется немного неправильной, он отображается как нулевая точка JFrame , установленная на фактическую нулевую точку окна. Таким образом, Swing пытается закрасить области, где на самом деле находится граница окна, которая тогда, конечно, не видна.

Смотрите этот снимок экрана: http://d-gfx.kognetwork.ch/java_aero_bug.png

] Пример кода

Это код, который я использую.

Требуется jna.jar и platform.jar . Доступно на домашней странице JNA.

import com.sun.jna.Function;
import com.sun.jna.Native;
import com.sun.jna.NativeLibrary;
import com.sun.jna.Structure;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.platform.win32.WinNT.HRESULT;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.UIManager;

public class AeroFrame extends JFrame {

    public AeroFrame() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JLabel label = new JLabel("Testlabel");
        label.setOpaque(false);

        add(label);

        pack();

        enableAeroEffect();
    }

    private void enableAeroEffect() {
        NativeLibrary dwmapi = NativeLibrary.getInstance("dwmapi");
        HWND aeroFrameHWND = new HWND(Native.getWindowPointer(this));
        MARGINS margins = new MARGINS();
        margins.cxLeftWidth = -1;
        margins.cxRightWidth = -1;
        margins.cyBottomHeight = -1;
        margins.cyTopHeight = -1;
        //DwmExtendFrameIntoClientArea(HWND hWnd, MARGINS *pMarInset)
        //http://msdn.microsoft.com/en-us/library/aa969512%28v=VS.85%29.aspx
        Function extendFrameIntoClientArea = dwmapi.getFunction("DwmExtendFrameIntoClientArea");
        HRESULT result = (HRESULT) extendFrameIntoClientArea.invoke(HRESULT.class,
                new Object[] { aeroFrameHWND, margins});
        if(result.intValue()!=0)
            System.err.println("Call to DwmExtendFrameIntoClientArea failed.");
    }

    /**
     * http://msdn.microsoft.com/en-us/library/bb773244%28v=VS.85%29.aspx
     */
    public class MARGINS extends Structure implements Structure.ByReference {
            public int cxLeftWidth;
            public int cxRightWidth;
            public int cyTopHeight;
            public int cyBottomHeight;
    }

    public static void main(String[] args) {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            JFrame.setDefaultLookAndFeelDecorated(true);

        } catch (Exception e) {
            e.printStackTrace();
        }
        new AeroFrame().setVisible(true);
    }

}

11
задан Daniel Dreibrodt 7 November 2010 в 11:35
поделиться