Home » Eclipse Projects » Standard Widget Toolkit (SWT) » Erase background transparently
Erase background transparently [message #459796] |
Wed, 17 August 2005 05:14  |
Eclipse User |
|
|
|
Originally posted by: groovynfunky.gmx.net
Hello,
I am playing around with the advanced graphics features of SWT 3.1.
Unfortunately I can't figure out, how to erase the background of a
transparent shell, so that it is completely transparent again.
Below is a Snippet to show what I mean. Push a mouse button and drag the
mouse to rotate the text. Double click to close the shell.
As you can seen I do not want the old content of my shell to stay on
screen.
I'd be grateful for any ideas, even platform specific solutions (windows).
Thanks,
Michael
import org.eclipse.swt.*;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.internal.win32.OS;
import org.eclipse.swt.internal.win32.RECT;
import org.eclipse.swt.widgets.*;
public class Snippet10b {
public static void main( String[] args ) {
final Display display = new Display();
final Shell shell = new Shell(display, SWT.NO_BACKGROUND);
shell.setText("Advanced Graphics");
shell.setData(new Integer(0));
FontData fd = shell.getFont().getFontData()[0];
final Font font = new Font(display, fd.getName(), 60, SWT.BOLD |
SWT.ITALIC);
shell.addListener(SWT.Paint, new Listener() {
public void handleEvent( Event event ) {
GC gc = event.gc;
Image image = getImage(event);
gc.drawImage(image, 0, 0);
image.dispose();
}
private Image getImage( Event event ) {
Image bufferImage = new Image(display, event.width,
event.height);
GC gc = new GC(bufferImage);
gc.setAntialias(SWT.ON);
Transform tr = new Transform(display);
tr.translate(50, 120);
tr.rotate(((Integer)shell.getData()).intValue());
gc.setTransform(tr);
Path path = new Path(display);
path.addString("SWT", 0, 0, font);
gc.setBackground(display.getSystemColor(SWT.COLOR_GREEN));
gc.setForeground(display.getSystemColor(SWT.COLOR_BLUE));
gc.fillPath(path);
gc.drawPath(path);
tr.dispose();
path.dispose();
gc.dispose();
ImageData id = bufferImage.getImageData();
int whitePixel = id.palette.getPixel(new RGB(255, 255, 255));
byte[] alphaData = new byte[event.height * event.width];
for ( int y = 0; y < event.height; y++ ) {
byte[] alphaRow = new byte[event.width];
for ( int x = 0; x < event.width; x++ ) {
if ( id.getPixel(x, y) == whitePixel )
alphaRow[x] = 0;
else
alphaRow[x] = 100;
System.arraycopy(alphaRow, 0, alphaData, y *
event.width, event.width);
}
}
id.alphaData = alphaData;
Image image = new Image(display, id);
bufferImage.dispose();
return image;
}
});
Listener listener = new Listener() {
boolean isMouseDown;
Point mouseLocationOnClick;
Integer originalAngle;
public void handleEvent( Event event ) {
if ( event.type == SWT.MouseMove && isMouseDown ) {
Point mouseLocation =
((Control)event.widget).toDisplay(event.x, event.y);
int newAngle = originalAngle + (mouseLocationOnClick.y -
mouseLocation.y);
shell.setData(new Integer(newAngle));
shell.redraw();
shell.update();
}
else if ( event.type == SWT.MouseDoubleClick ) {
shell.dispose();
}
else if ( event.type == SWT.MouseDown ) {
mouseLocationOnClick =
((Control)event.widget).toDisplay(event.x, event.y);
originalAngle = (Integer)shell.getData();
isMouseDown = true;
}
if ( event.type == SWT.MouseUp ) {
isMouseDown = false;
}
}
};
shell.addListener(SWT.MouseMove, listener);
shell.addListener(SWT.MouseDoubleClick, listener);
shell.addListener(SWT.MouseDown, listener);
shell.addListener(SWT.MouseUp, listener);
shell.setSize(300, 300);
shell.open();
while ( !shell.isDisposed() ) {
if ( !display.readAndDispatch() )
display.sleep();
}
font.dispose();
display.dispose();
}
}
|
|
|
Re: Erase background transparently [message #459806 is a reply to message #459796] |
Wed, 17 August 2005 10:21   |
Eclipse User |
|
|
|
Originally posted by: sunil_kamath.nohotspammail.com
"Michael Kerbel" <groovynfunky@gmx.net> wrote in message
news:55eeb9a7272aaacf715aa41a34a261d4$1@www.eclipse.org...
> Hello,
>
> I am playing around with the advanced graphics features of SWT 3.1.
> Unfortunately I can't figure out, how to erase the background of a
> transparent shell, so that it is completely transparent again.
> Below is a Snippet to show what I mean. Push a mouse button and drag the
> mouse to rotate the text. Double click to close the shell.
> As you can seen I do not want the old content of my shell to stay on
> screen.
>
> I'd be grateful for any ideas, even platform specific solutions (windows).
> Thanks,
> Michael
>
SWT doesn't support this (as yet).
On Windows 2000 or better:
a) Create the shell with the SWT.NO_BACKGROUND style.
b) OS.SetWindowLong(shell.handle, OS.GWL_EXSTYLE,
GetWindowLong(shell.handle, OS.GWL_EXSTYLE)|0x80000); //0x80000 ==
WS_EX_LAYERED
c) Create a JNI call to SetLayeredWindowAttributes.
d) SetLayeredWindowAttributes(shell.handle, 0, 0, 0, 0, 2); //2 == LWA_ALPHA
this will change the alpha value for the shell to 0 (transparent).
---
Sunil
|
|
| |
Re: Erase background transparently [message #459809 is a reply to message #459796] |
Wed, 17 August 2005 10:50   |
Eclipse User |
|
|
|
Originally posted by: groovynfunky.gmx.net
Hello again,
> I am playing around with the advanced graphics features of SWT 3.1.
> Unfortunately I can't figure out, how to erase the background of a
> transparent shell, so that it is completely transparent again.
I realized, that what I need is to redraw the region underneath my shell.
This can belong to anyone, so I have no clue how to do this. Any ideas how
to mark it dirty? I'd be happy even for Windows dependant clues.
Meanwhile I did a hack which works for static background, i.e. background
which does not change. See below, sorry for the bad code and the long
"Snippet".
Bye,
Michael
import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.*;
public class Snippet10c {
public static void main( String[] args ) {
final Display display = new Display();
final Shell shell = new Shell(display, SWT.NO_BACKGROUND |
SWT.NO_TRIM);
shell.setData(new Integer(0));
FontData fd = shell.getFont().getFontData()[0];
final Font font = new Font(display, fd.getName(), 40, SWT.BOLD |
SWT.ITALIC);
shell.addListener(SWT.Paint, new Listener() {
Image backgroundScreenshot;
public void handleEvent( Event event ) {
GC gc = event.gc;
if ( backgroundScreenshot == null ) {
GC displayGc = new GC(display);
backgroundScreenshot = new Image(display,
shell.getSize().x, shell.getSize().y);
displayGc.copyArea(backgroundScreenshot,
shell.getLocation().x, shell.getLocation().y);
displayGc.dispose();
}
Image image = getImage(event);
gc.drawImage(image, 0, 0);
image.dispose();
}
private Image getImage( Event event ) {
Image bufferImage = new Image(display, event.width,
event.height);
GC gc = new GC(bufferImage);
gc.setAntialias(SWT.ON);
Transform tr = new Transform(display);
tr.translate(150, 150);
tr.rotate(((Integer)shell.getData()).intValue());
gc.setTransform(tr);
Path path = new Path(display);
path.addString("SWT", 0, 0, font);
gc.setBackground(display.getSystemColor(SWT.COLOR_GREEN));
gc.setForeground(display.getSystemColor(SWT.COLOR_BLUE));
gc.fillPath(path);
gc.drawPath(path);
tr.dispose();
path.dispose();
gc.dispose();
ImageData id = bufferImage.getImageData();
int whitePixel = id.palette.getPixel(new RGB(255, 255, 255));
byte[] alphaData = new byte[event.height * event.width];
for ( int y = 0; y < event.height; y++ ) {
byte[] alphaRow = new byte[event.width];
for ( int x = 0; x < event.width; x++ ) {
if ( id.getPixel(x, y) == whitePixel )
alphaRow[x] = 0;
else
alphaRow[x] = 100;
System.arraycopy(alphaRow, 0, alphaData, y *
event.width, event.width);
}
}
id.alphaData = alphaData;
Image image = new Image(display, id);
bufferImage.dispose();
bufferImage = new Image(display, event.width, event.height);
gc = new GC(bufferImage);
gc.drawImage(backgroundScreenshot, 0, 0);
gc.drawImage(image, 0, 0);
image.dispose();
gc.dispose();
return bufferImage;
}
});
Listener listener = new Listener() {
boolean isMouseDown;
Point mouseLocationOnClick;
Integer originalAngle;
public void handleEvent( Event event ) {
if ( event.type == SWT.MouseMove && isMouseDown ) {
Point mouseLocation =
((Control)event.widget).toDisplay(event.x, event.y);
int newAngle = originalAngle + (mouseLocationOnClick.y -
mouseLocation.y);
shell.setData(new Integer(newAngle));
shell.redraw();
shell.update();
}
else if ( event.type == SWT.MouseDoubleClick ) {
shell.dispose();
}
else if ( event.type == SWT.MouseDown ) {
mouseLocationOnClick =
((Control)event.widget).toDisplay(event.x, event.y);
originalAngle = (Integer)shell.getData();
isMouseDown = true;
}
if ( event.type == SWT.MouseUp ) {
isMouseDown = false;
}
}
};
shell.addListener(SWT.MouseMove, listener);
shell.addListener(SWT.MouseDoubleClick, listener);
shell.addListener(SWT.MouseDown, listener);
shell.addListener(SWT.MouseUp, listener);
shell.setSize(300, 300);
shell.open();
while ( !shell.isDisposed() ) {
if ( !display.readAndDispatch() )
display.sleep();
}
font.dispose();
display.dispose();
}
}
|
|
|
Re: Erase background transparently [message #459814 is a reply to message #459806] |
Wed, 17 August 2005 15:26   |
Eclipse User |
|
|
|
Originally posted by: groovynfunky.gmx.net
>> I am playing around with the advanced graphics features of SWT 3.1.
>> Unfortunately I can't figure out, how to erase the background of a
>> transparent shell, so that it is completely transparent again.
>> Below is a Snippet to show what I mean.
> SWT doesn't support this (as yet).
> On Windows 2000 or better:
> a) Create the shell with the SWT.NO_BACKGROUND style.
> b) OS.SetWindowLong(shell.handle, OS.GWL_EXSTYLE,
> GetWindowLong(shell.handle, OS.GWL_EXSTYLE)|0x80000); //0x80000 ==
> WS_EX_LAYERED
> c) Create a JNI call to SetLayeredWindowAttributes.
> d) SetLayeredWindowAttributes(shell.handle, 0, 0, 0, 0, 2); //2 == LWA_ALPHA
> this will change the alpha value for the shell to 0 (transparent).
Thanks for your help! I'll have to reactivate my knowledge about JNI
before I can try your hints - it has been a while...
Meanwhile the hack I posted some minutes after your answer seems good
enough for me - if you add an activation listener which refreshes the
screenshot.
Do you have any idea, if such a feature is planned in SWT? Do you think it
is feasible at all for all the supported platforms?
Thanks,
Michael
|
|
|
Re: Erase background transparently [message #459815 is a reply to message #459808] |
Wed, 17 August 2005 15:36  |
Eclipse User |
|
|
|
Originally posted by: groovynfunky.gmx.net
> I don't think it is possible with a shell. That is because what is
> behind the shell is the desktop or some other shell's contents. There is
> no way for you to tell those objects to repaint because for most desktop
> systems, when the section of the desktop that contains your shell is
> asked to repaint, it actually goes straight to your shell (since your
> shell is on top) and asks only it to repaint for that exposed section.
> It doesn't ask those under it to repaint.
> This is true of standard windows, I don't know how it works if you turn
> on skins. That may allow something like that since those have irregular
> borders.
I share your doubts whether such a feature is possible on all supported
platforms. But if any applications with transparent shells exist for each
platform, it should be. I have no idea about non-windows platforms in this
respect...
Thank you,
Michael
|
|
|
Goto Forum:
Current Time: Wed Jul 23 13:44:47 EDT 2025
Powered by FUDForum. Page generated in 0.24606 seconds
|