DwmExtendFrameIntoClientAreadwmapiContentPanefalseLayeredPaneRootPaneFrameJFrameJFrameContentPanesetLayersOpaquepaint()JFramejna.jar
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);
}
}
最佳答案:
好问题。
最明显的答案是
WindowUtils.setWindowOpaque(this, false);
这给了你想要的视觉效果,但不幸的是,你无法点击窗口!
我尝试的第二件事是重写paint()方法以执行与
Window.paint()
标志设置为false时相同的操作。什么都没做。然后我试着用倒影。反射设置为“真”的结果与使用“真”的结果相同。
最后,我尝试将此添加到
Method m = null;
try {
m = Window.class.getDeclaredMethod("setLayersOpaque", Component.class, Boolean.TYPE);
m.setAccessible(true);
m.invoke(null, this, false);
} catch ( Exception e ) {
//TODO: handle errors correctly
} finally {
if ( m != null ) {
m.setAccessible(false);
}
}
这奏效了!窗口仍然对鼠标事件做出正确响应,但未绘制背景。这幅画有点浮华,但应该让你上路。
显然它很脆弱,因为它依赖于反射。如果我是你,我会看一下
opaque
的作用,并尝试以一种不依赖反射的方式复制它。编辑:在检查
Window.opaque
方法时,它实际上似乎归结为禁用透明组件上的双缓冲。从您的WindowUtils
方法调用此方法,您就可以开始了://original source: Sun, java/awt/Window.java, setLayersOpaque(Component, boolean)
private static void setLayersTransparent(JFrame frame) {
JRootPane root = frame.getRootPane();
root.setOpaque(false);
root.setDoubleBuffered(false);
Container c = root.getContentPane();
if (c instanceof JComponent) {
JComponent content = (JComponent) c;
content.setOpaque(false);
content.setDoubleBuffered(false);
}
frame.setBackground(new Color(0, 0, 0, 0));
}