Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » Standard Widget Toolkit (SWT) » Erase background transparently
Erase background transparently [message #459796] Wed, 17 August 2005 09:14 Go to next message
Eclipse UserFriend
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 14:21 Go to previous messageGo to next message
Eclipse UserFriend
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 #459808 is a reply to message #459796] Wed, 17 August 2005 14:31 Go to previous messageGo to next message
Eclipse UserFriend
Originally posted by: richkulp.us.NO_SPAM.ibm.com

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.

--
Thanks,
Rich Kulp
Re: Erase background transparently [message #459809 is a reply to message #459796] Wed, 17 August 2005 14:50 Go to previous messageGo to next message
Eclipse UserFriend
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 19:26 Go to previous messageGo to next message
Eclipse UserFriend
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 19:36 Go to previous message
Eclipse UserFriend
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
Previous Topic:can I select multiple rows and columns in a table ?
Next Topic:JFace: NoClassDefFoundError
Goto Forum:
  


Current Time: Sun Apr 18 07:26:42 GMT 2021

Powered by FUDForum. Page generated in 0.03417 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top