Je rencontre des problèmes lors de l'utilisation de la fonctionnalité DWM de Windows Vista/7 sur les fenêtres Java. Je veux que l'arrière-plan de mon cadre utilise le style Aero. L'API Windows pour ce faire est fournie par la fonction DwmExtendFrameIntoClientArea
dans la bibliothèque dwmapi
. J'ai réussi à appeler la procédure correctement via JNA, et il fait ce qu'il est censé faire (Vous pouvez voir que par exemple lors du redimensionnement du cadre, avant le repeindre suivant vous voyez les effets aérodynamiques appropriés dans la zone pas encore peinte, voir l'image ci-jointe).Désactiver le dessin d'arrière-plan dans JFrame pour afficher correctement les effets Aero (DWM)
Mais quelque part (je ne sais pas où) un fond est peint sur l'effet Aero et l'effet est perdu.
Ce que j'ai déjà essayé:
- En utilisant une coutume
ContentPane
avec l'opacité réglée surfalse
- Réglage de l'opacité du
LayeredPane
et laRootPane
false - L'utilisation d'un
Frame
au lieu d'unJFrame
- Définir la couleur de fond du
JFrame
/ContentPane
au noir/entièrement transparent - Utilisation
setLayersOpaque
et une de ses variantes sur mesure, voir première réponse pour plus de détails
Jusqu'à présent, je ne pouvais pas réussir retirer ce contexte. Est-ce une limitation de AWT/Swing? Comment puis-je supprimer cet arrière-plan ou utiliser correctement l'effet Aero?
Votre aide est grandement appréciée.
Screenshot
Voici une capture d'écran d'un cadre sans contenu, après avoir réglé l'opacité du RootPane, LayeredPane et ContentPane false. Je l'ai fait rapidement en redimensionnant. Vous voyez que l'effet est correctement appliqué à la zone sur laquelle Java n'a pas encore peint.
http://i55.tinypic.com/v614qo.png (En tant que nouvel utilisateur, je ne peux pas poster directement l'image ...)
comportement étrange
Après enquête, je suis tombé sur le comportement étrange suivant. Si la taille de la fenêtre est de 150 x 150 ou moins, le contenu est affiché de manière transparente. Ceci est très glitchy pour les composants de fenêtre normale. Si vous peignez directement sur le cadre en remplaçant la méthode paint()
, tout est dessiné semi-transparent. De plus, le système de coordonnées semble être un peu éteint, il apparaît que le point zéro du JFrame
est réglé sur le point zéro réel de la fenêtre. Ainsi, Swing essaie de peindre les zones où se trouve effectivement la bordure de la fenêtre, qui n'est bien sûr pas visible.
Voir cette capture d'écran: http://d-gfx.kognetwork.ch/java_aero_bug.png
code Exemple
Voici le code que j'utilise.
Nécessite jna.jar
et platform.jar
. Disponible sur la page d'accueil de la 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);
}
}
Qu'advient-il lorsque vous utilisez le look & feel de Windows à la place du métal par défaut? – Jonathan
J'utilise le look & feel de Windows. Mais c'est le même problème avec le Metal L & F et le Windows L & F. Aucune différence. –