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