日期:2014-05-20  浏览次数:20818 次

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)实现的。
下面附有代码,源程序效果图见附件:
Java code

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;
            }
        }
    }
    
    
    
}