SWT Transparentes Fenster

Thomas Darimont

Erfahrenes Mitglied
Hallo!

Code:
  /**
   * 
   */
  package de.tutorials;
  
  import org.eclipse.swt.SWT;
  import org.eclipse.swt.events.SelectionAdapter;
  import org.eclipse.swt.events.SelectionEvent;
  import org.eclipse.swt.layout.RowLayout;
  import org.eclipse.swt.widgets.Button;
  import org.eclipse.swt.widgets.Display;
  import org.eclipse.swt.widgets.Shell;
  
  /**
   * @author Tom
   * 
   */
  public class SWTTransparencyExample {
  	/**
  	 * @param args
  	 */
  	public static void main(String[] args) {
  		Display display = new Display();
  		final Shell shell = new Shell(display,SWT.NO_BACKGROUND);
  		shell.setText("SWTTransparencyExample");
  		shell.setSize(320, 240);
  		shell.setLayout(new RowLayout());
  
  		Button btn = new Button(shell,SWT.NO_BACKGROUND);
  		btn.setText("Close");
  		btn.addSelectionListener(new SelectionAdapter(){
  			public void widgetSelected(SelectionEvent e) {
  				shell.dispose();
			}
  		});
  		
  		shell.open();
  
  		while (!shell.isDisposed()) {
  			if (!display.readAndDispatch()) {
  				display.sleep();
  			}
  		}
  
  	}
  }

Gruß Tom
 
Nett :-)
leider:

Wenn Ich das Fenster verschiebe, dann bleibt der alte Hintergrund bestehen und wird mitverschoben.
Wenn das Fenster hinter einem anderen verschwindet und dann neu gezeichnet werden muss, wird der Inhalt in der transparenten Shell korrekt dargestellt. Teile, die nicht überdeckt werden, behalten den Inhalt.

Wie kann man erreichen, dass der Hintergrund neu geschrieben wird?
 
Hallo!

Ich weis noch nicht, wie man das nur mit SWT Mitteln hinbekommt, jedoch hab ich mir dazu etwas über JNI gebastelt:

Code:
  /**
   * 
   */
  package de.tutorials;
  
  import org.eclipse.swt.SWT;
  import org.eclipse.swt.events.SelectionAdapter;
  import org.eclipse.swt.events.SelectionEvent;
  import org.eclipse.swt.layout.RowLayout;
  import org.eclipse.swt.widgets.Display;
  import org.eclipse.swt.widgets.Scale;
  import org.eclipse.swt.widgets.Shell;
  
  /**
   * @author Tom
   * 
   */
  public class SWTTransparencyExample {
  
  	static{
  		System.loadLibrary("windowTransparencyExample");
  	}
  	
  	/**
  	 * @param args
  	 */
  	public static void main(String[] args) {
  		Display display = new Display();
  		Shell shell = new Shell(display);
  		shell.setText("SWTTransparencyExample");
  		shell.setSize(320, 240);
  		shell.setLayout(new RowLayout());
  
  		initModule(shell.handle);
  
  		final Scale scale = new Scale(shell, SWT.HORIZONTAL);
  		scale.setMinimum(0);
  		scale.setMaximum(255);
  		scale.addSelectionListener(new SelectionAdapter() {
  			public void widgetSelected(SelectionEvent e) {
 				setWindowTransparency(scale.getSelection());
  			}
  		});
  		
  		setWindowTransparency(255);
  
  		shell.open();
  
  		while (!shell.isDisposed()) {
  			if (!display.readAndDispatch()) {
  				display.sleep();
  			}
  		}
  		
  		destroyModule(shell.handle);
  
  	}
  
  	private native static void initModule(int handle);
  	private native static void destroyModule(int moduleHandle);
  	private static native void setWindowTransparency(int transparency);
  }

Das Header File
Code:
  /* DO NOT EDIT THIS FILE - it is machine generated */
  #include <jni.h>
  /* Header for class de_tutorials_SWTTransparencyExample */
  
  #ifndef _Included_de_tutorials_SWTTransparencyExample
  #define _Included_de_tutorials_SWTTransparencyExample
  #ifdef __cplusplus
  extern "C" {
  #endif
  /*
   * Class:	 de_tutorials_SWTTransparencyExample
   * Method:	initModule
   * Signature: (I)V
   */
  JNIEXPORT void JNICALL Java_de_tutorials_SWTTransparencyExample_initModule
    (JNIEnv *, jclass, jint);
  
  /*
   * Class:	 de_tutorials_SWTTransparencyExample
   * Method:	destroyModule
   * Signature: (I)V
   */
  JNIEXPORT void JNICALL Java_de_tutorials_SWTTransparencyExample_destroyModule
    (JNIEnv *, jclass, jint);
  
  /*
   * Class:	 de_tutorials_SWTTransparencyExample
   * Method:	setWindowTransparency
   * Signature: (I)V
   */
  JNIEXPORT void JNICALL Java_de_tutorials_SWTTransparencyExample_setWindowTransparency
    (JNIEnv *, jclass, jint);
  
  #ifdef __cplusplus
  }
  #endif
  #endif

Die Implementierung:
Code:
  // windowTransparencyExample.cpp : Definiert den Einstiegspunkt für die DLL-Anwendung.
  //
  
  #include "stdafx.h"
  #include "de_tutorials_SWTTransparencyExample.h"
  #include "windows.h"
  #include "Winuser.h"
  #include <iostream>
  
  using namespace std;
  
  HWND hWnd;
  HMODULE hDLL;
  typedef DWORD (WINAPI *PSLWA)(HWND, DWORD, BYTE, DWORD);
  PSLWA pSetLayeredWindowAttributes;
  
  /*
   * Class:	 de_tutorials_SWTTransparencyExample
   * Method:	setWindowTransparency
   * Signature: (I)V
   */
  JNIEXPORT void JNICALL Java_de_tutorials_SWTTransparencyExample_setWindowTransparency
  (JNIEnv *env, jclass clazz, jint transparencyValue){
  
  	cout << "setWindowTransparency: " << transparencyValue << endl;
  	if (pSetLayeredWindowAttributes != NULL) {
  	/*
  	* Second parameter RGB(255,255,255) sets the colorkey 
  	* to white LWA_COLORKEY flag indicates that color key 
  	* is valid LWA_ALPHA indicates that ALphablend parameter 
  	* (factor) is valid
  	*/
  	cout << "pSetLayeredWindowAttributes" << endl;
  
  	pSetLayeredWindowAttributes (hWnd, 
  		RGB(255,255,255), (int)transparencyValue, 0x00000001|0x00000002);
  	}
  }
  
  /*
   * Class:	 de_tutorials_SWTTransparencyExample
   * Method:	initModule
   * Signature: (I)V
   */
  JNIEXPORT void JNICALL Java_de_tutorials_SWTTransparencyExample_initModule
  (JNIEnv *env, jclass clazz, jint handle){
  	cout << "initmodule1: " << handle << endl;
  	hWnd = (HWND)handle;
  	SetWindowLong (hWnd , (-20) , GetWindowLong (hWnd , (-20) ) | 0x00080000 );
  }
  
  /*
   * Class:	 de_tutorials_SWTTransparencyExample
   * Method:	destroyModule
   * Signature: (I)V
   */
  JNIEXPORT void JNICALL Java_de_tutorials_SWTTransparencyExample_destroyModule
  (JNIEnv *, jclass, jint){
  	cout << "destroy module" << endl;
  	FreeLibrary(hDLL);
  }
  
  JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved){
  	cout << "JNI_OnLoad" << endl;
  	hDLL = LoadLibrary ("user32");
  	pSetLayeredWindowAttributes = (PSLWA) GetProcAddress(hDLL,"SetLayeredWindowAttributes");
  	return JNI_VERSION_1_4;
  }

Gruß Tom
 

Anhänge

  • swtTransparencyExample.jpg
    swtTransparencyExample.jpg
    65,5 KB · Aufrufe: 464
hmm. Das ist echte Transparenz, währen NO_BACKGROUND lediglich besagt, dass der Hintergrund nicht gezeichnet wird. Wenn aber der Hintergrund nicht gezeichnet wird, und beim Verschieben der alte Inhalt beibehalten wird; dann muss IMO irgendwo ein Caching Mechanismus sein.

Ach ja, ich benutze Linux/GTK+/x86. der shell.handle müsste also irgendwie ein GTK+ handle sein. Ich müsste den X server irgendwie zwingen, die Fenster unterhalb der ClientArea neuzuzeichnen. AFAIK unterstützt der x.org Server neuerdings auch Transparenz, aber bis das in SWT ankommt ...

1.1: Typo
 
Hallo!

Ach ja, ich benutze Linux/GTK+/x86. der shell.handle müsste also irgendwie ein GTK+ handle sein. Ich müsste den X server irgendwie zwingen, die Fenster unterhalb der ClientArea neuzuzeichnen. AFAIK unterstützt der x.org Server neuerdings auch Transparenz, aber bis das in SWT ankommt ...
Na ja, sobald SWT ins Spiel kommt und man sich mit "speziellen" Features beschäftigt ist's mit der Plattformunabhängigkeit sowieso schon geschehen...

Gruß Tom
 
Zurück