SWT透明窗口
描述:
建立一个父shell显示主线程信息,建立一个半透明的子shell线程显示消息信息,想让两个shell关联起来时,让透明窗口浮动在父窗口之上,即:子shell在父shell上显示,同时两个线程继续进行。当一段时间后,子shell自动隐藏销毁,父shell继续运行。透明窗口在SWT只能用API函数调用绘制,我的要求是只需要绘制该子shell,但实际的情况是:子shell在弹出时连同父shell也同时进行了重绘!而且子shell销毁后,父shell会留下子shell绘制时绘制的父shell窗口的残影。注:我是用SWT中调用OS.CallWindowProc(fun,shell.handle, 0, 150, 2)实现的。
下面附有代码,源程序效果图见附件:
import java.awt.BorderLayout;import java.awt.Color;import java.awt.Frame;import java.awt.Panel;import org.eclipse.swt.SWT;import org.eclipse.swt.awt.SWT_AWT;import org.eclipse.swt.events.SelectionAdapter;import org.eclipse.swt.events.SelectionEvent;import org.eclipse.swt.events.ShellAdapter;import org.eclipse.swt.events.ShellEvent;import org.eclipse.swt.internal.win32.OS;import org.eclipse.swt.internal.win32.TCHAR;import org.eclipse.swt.widgets.Button;import org.eclipse.swt.widgets.Composite;import org.eclipse.swt.widgets.Display;import org.eclipse.swt.widgets.Label;import org.eclipse.swt.widgets.Shell;import com.swtdesigner.SWTResourceManager;public class Popup extends Thread { final Shell shell; final Composite composite; eventShell es; boolean terminated = false; boolean isEvent = false; protected int moveStep = 2; //每次移动的pixel protected int upPosition; //能移动到的最上面坐标 protected int downPosition; //当前popup的边框坐标 protected int leftPosition; //popup左边边框坐标 public Popup(final String message,Shell parent) { shell = new Shell(parent,SWT.NO_TRIM); shell.addShellListener(new ShellAdapter() { public void shellClosed(final ShellEvent e) { terminated = true; } }); //取屏莫大小 upPosition = parent.getLocation().y+95;//计算出popup界面在屏幕显示的最高位置 downPosition = parent.getLocation().y+ 155;//计算出popup界面的初始位置 leftPosition = parent.getLocation().x+7 ; shell.setSize(168, 78);// shell.setAlpha(200); //初始化popup位置 shell.setLocation(leftPosition, downPosition); shell.open(); resetShell(); //OS.SetWindowPos(shell.handle , OS.HWND_TOPMOST, 0 , 700 , 1024 , 68 , SWT.NULL); //透明窗体 composite = new Composite(shell, SWT.NONE); composite.setBackground(SWTResourceManager.getColor(225, 252, 255)); composite.setBounds(0, 0, 168, 78);/* Frame frame = SWT_AWT.new_Frame(composite); Panel panel = new Panel(new BorderLayout()) { public void update(java.awt.Graphics g) { paint(g); } }; panel.setForeground(Color.YELLOW);// 在容器中添加子容器 frame.add(panel); */ final Button button = new Button(composite, SWT.NONE); button.setBounds(94, 48,60, 20); button.addSelectionListener(new SelectionAdapter() { public void widgetSelected(final SelectionEvent e) { es = new eventShell(shell,"一个巨大的好消息:IBM向Open Source社群捐献了自己的Visual Editor项目,不久Eclipse将在此项目基础上发布可视化GUI编辑工具。看来,不用太久,Eclipse的用户们就不用再羡慕JBuilder的可视化GUI编辑器了——而且这还是免费的,而且这还是基于SWT的。"); isEvent = true; es.start(); /* if(es.isAlive()) System.out.print("event窗口活着!"); else System.out.print("event窗口死亡!");*/ } }); button.setText("点击查看"); final Button xButton = new Button(composite, SWT.NONE); xButton.addSelectionListener(new SelectionAdapter() { public void widgetSelected(final SelectionEvent e) { shell.dispose(); } }); xButton.setBounds(150, 0, 17, 14); final Label label = new Label(composite, SWT.NONE); label.setBackground(SWTResourceManager.getColor(225, 252, 255)); label.setBounds(10, 20, 144, 14); label.setText(message); } private void resetShell() { //设置窗体透明 OS.SetWindowLong(shell.handle, OS.GWL_EXSTYLE, OS.GetWindowLong( shell.handle, OS.GWL_EXSTYLE) ^ 0x80000); // load User32.dll lib TCHAR lpLibFileName = new TCHAR(0, "User32.dll", true); int hInst = OS.LoadLibrary(lpLibFileName); if (hInst != 0) { // 设定调用函数名称 //System.out.println("hInst!=0"); String name = "SetLayeredWindowAttributes\0"; byte[] lpProcName = new byte[name.length()]; for (int i = 0; i < lpProcName.length; i++) { lpProcName[i] = (byte) name.charAt(i); } // 检索DLL输出函数地址 int fun = OS.GetProcAddress(hInst, lpProcName); // 当函数存在 if (fun != 0){ // 150为透明度,在0-255之间 System.out.println("透明度为50"); OS.CallWindowProc(fun,shell.handle, 0, 150, 2); } // 释放lib OS.FreeLibrary(hInst); } } public void run() { while (true) { try { Thread.sleep(10); //判断当前位置是否小于能出现的最高位置,小于的话就说明还可以向上移动。 if ((downPosition - moveStep) > upPosition) { Display.getDefault().asyncExec( new Runnable(){ public void run(){ shell.setLocation(leftPosition, downPosition- moveStep); // resetShell(); downPosition -= moveStep;}});//判断当前位置是否小于能出现的最高位置,小于的话就说明还可以向上移动。 } else { // //this.resetShell(); //OS.FreeLibrary(hInst); // Thread.sleep(5000); if(!isEvent) { Display.getDefault().asyncExec(new Runnable(){ public void run(){ shell.dispose();}}); terminated = true; } else if(isEvent) { try { es.join(); isEvent = false; System.out.print("event窗口已经死亡!"); } catch(InterruptedException e) { e.printStackTrace(); } Display.getDefault().asyncExec(new Runnable(){ public void run(){ shell.dispose();}}); terminated = true; } } } catch(InterruptedException e) {e.printStackTrace();} if(terminated ==true) { System.out.print("Popup窗体关闭!"); return; } } } }