描述:
建立一个父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;
}
}
}



}

解决方案 »

  1.   

    此回复为自动发出,仅用于显示而已,并无任何其他特殊作用
    楼主【still_rain】截止到2008-07-12 15:30:23的历史汇总数据(不包括此帖):
    发帖的总数量:13                       发帖的总分数:180                      每贴平均分数:13                       
    回帖的总数量:23                       得分贴总数量:2                        回帖的得分率:8%                       
    结贴的总数量:12                       结贴的总分数:80                       
    无满意结贴数:8                        无满意结贴分:240                      
    未结的帖子数:1                        未结的总分数:100                      
    结贴的百分比:92.31 %               结分的百分比:44.44 %                  
    无满意结贴率:66.67 %               无满意结分率:300.00%                  
    值得尊敬
      

  2.   

    import com.swtdesigner.SWTResourceManager;这个是 什么包包呀 我怎么找不到呀??呵呵
      

  3.   

    这应该是lz自己写的东西,专门处理资源文件
    -------------------------------------------
    Quietly through ....
      

  4.   

     OS.SetWindowLong(shell.handle, OS.GWL_EXSTYLE, OS.GetWindowLong(
                    shell.handle, OS.GWL_EXSTYLE) ^ 0x80000)看不懂
      

  5.   

    大哥,这个SWTResourceManager是系统自己生成的,windowbuilder工具用过没?