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