我在Java窗口中使用Windows Vista/7的DWM功能時遇到問題。我想讓我的框架的背景使用Aero風格。這樣做的Windows API由dwmapi
庫中的函數DwmExtendFrameIntoClientArea
提供。我已經設法通過JNA正確調用該程序,並且它完成了它應該做的事情(例如,您可以看到,例如,在調整幀的大小時,在下一次重繪之前,您可以在尚未繪製的區域中看到適當的空氣效果,見附圖)。在JFrame中禁用背景圖以正確顯示Aero(DWM)效果
但是在某處(我無法弄清楚)Aero效果的背景是如何繪製的,效果會丟失。
我已經嘗試過:
- 使用自定義
ContentPane
不透明度設置爲false
- 設置
LayeredPane
的不透明度和RootPane
假 - 使用
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);
}
}
會發生什麼事,當你使用Windows的外觀和感覺,而不是默認的金屬? – Jonathan 2010-10-20 15:58:50
我正在使用Windows外觀。但是Metal L&F和Windows L&F都存在同樣的問題。沒有不同。 – 2010-10-21 10:26:02