JavaSE 1.6提供了java.awt.SystemTray类用于方便地创建托盘图标.但在Windows平台下当explorer崩溃时托盘图标会丢失.
如果是本地代码或.Net平台的程序则可以很简单地获取TaskbarCreated消息并重新添加托盘图标.
但在Java程序中无法直接访问Windows消息.

解决方法是通过JNI调用本地代码安装消息钩子捕获TaskbarCreated消息并通知主程序重建图标.

package idv.takamachi660.platform.win;

import java.util.ArrayList;
import java.util.List;

/**
 * 任务栏重建监视器
 * 
 * 
@author Takamachi660
 * 
 
*/
public class TaskBarMonitor {
    
private static TaskBarMonitor instance;

    
private boolean enabled;
    
private long lastMsg;
    
private int minimumInterval = 1500;
    
private final List<TaskBarListener> listeners = new ArrayList<TaskBarListener>();

    
static {
        
try {
            System.loadLibrary(
"TaskBarMonitor");
            
// 如果本地库成功加载则创建实例
            instance = new TaskBarMonitor();
        } 
catch (Throwable ex) {
            ex.printStackTrace();
        }
    }

    
/**
     * 查询监视器是否可用
     
*/
    
public static boolean isSupported() {
        
return instance != null;
    }

    
/**
     * 返回全局唯一实例,若不可用则返回null
     
*/
    
public static TaskBarMonitor getInstance() {
        
return instance;
    }

    
private TaskBarMonitor() {
    }

    
/**
     * 本地方法,安装钩子,保存必要的全局引用
     
*/
    
private native boolean installHook();

    
/**
     * 本地方法,撤销钩子,释放全局引用
     
*/
    
private native boolean unInstallHook();

    
/**
     * 从钩子处理函数调用
     
*/
    @SuppressWarnings(
"unused")
    
private void hookCallback() {
        
long current = System.currentTimeMillis();
        
if (current - this.lastMsg >= this.getMinimumInterval())
            
for (TaskBarListener l : listeners)
                l.taskBarCreated();
        
this.lastMsg = current;
    }

    
/**
     * 查询监视器状态(钩子是否已经安装)
     
*/
    
public boolean isEnabled() {
        
return enabled;
    }

    
/**
     * 设置监视器状态(安装或撤销钩子),若与当前状态相同则不执行任何操作
     
*/
    
public void setEnable(boolean enable) {
        
if (this.isEnabled() != enable) {
            
if (enable)
                
this.enabled = this.installHook();
            
else
                
this.enabled = !this.unInstallHook();
        }
    }

    
/**
     * 设置最小消息触发间隔(防止重复)
     
*/
    
public void setMinimumInterval(int minimumInterval) {
        
this.minimumInterval = minimumInterval;
    }

    
/**
     * 获取最小消息触发间隔
     
*/
    
public int getMinimumInterval() {
        
return minimumInterval;
    }

    
public void addTaskBarListener(TaskBarListener listener) {
        listeners.add(listener);
    }

    
public void removeTaskBarListener(TaskBarListener listener) {
        listeners.remove(listener);
    }

    @Override
    
protected void finalize() throws Throwable {
        
this.setEnable(false);
        
// 防止忘记调用setEnable(false)造成内存泄漏
        
// 但不可靠
    }

相关文章:

  • 2022-12-23
  • 2021-06-11
  • 2021-08-29
  • 2021-07-15
  • 2022-01-23
  • 2022-12-23
  • 2021-12-06
  • 2021-05-17
猜你喜欢
  • 2021-09-26
  • 2022-12-23
  • 2021-09-02
  • 2022-01-13
  • 2022-12-23
  • 2021-11-30
相关资源
相似解决方案