from:
http://www.blogjava.net/Unmi/archive/2008/03/23/188040.html
我們有些程式會想要托盤處顯示表徵圖,最小化到系統欄;關閉按鈕不關閉程式,也是最小化到系統欄;點擊托盤表徵圖啟用視窗,通過托盤表徵圖的快顯功能表來退出程式。
本段代碼就是要完成這樣的功能,是 SWT 來實現的。
直接代碼給出,代碼中有較詳細的注釋,說明了本程式的功能及實現。文中的工作列和系統欄應該知道是指哪一段吧,微軟就是這麼定義的,用 spyxx 的 findwindow 窺探一下就知道了。
package com.unmi;
import org.eclipse.swt.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.*;
/**
* SWT 3.0 開始引入了 Tray,可以在系統欄放置你的程式表徵圖了
* 本程式實現的功能有四:
* 1. 點擊視窗的最小化或關閉按鈕都是隱藏視窗--工作列裡不顯示,不退出程式
* 2. 視窗隱藏時,工作列無表徵圖,系統欄有表徵圖;視窗處於顯示狀態時則恰好相反
* 3. 視窗隱藏時可通過單擊系統欄表徵圖或點擊系統欄的 "顯示視窗" 菜單顯示視窗
* 4. 程式只能通過點擊系統欄的 "退出程式" 功能表項目退出,視窗的 X 按鍵無效
* @author Unmi
*
*/
public class TrayExample {
public static void main(String[] args) {
Display display = new Display();
//禁用掉了最大化按鈕
final Shell shell = new Shell(display,SWT.SHELL_TRIM ^ SWT.MAX);
shell.setText("TrayExample");
//取系統中預置的表徵圖,省得測試回合時還得加個表徵圖檔案
shell.setImage(display.getSystemImage(SWT.ICON_WORKING));
//構造系統欄控制項
final Tray tray = display.getSystemTray();
final TrayItem trayItem = new TrayItem(tray, SWT.NONE);
//程式啟動時,視窗是顯示的,所以系統欄表徵圖隱藏
trayItem.setVisible(false);
trayItem.setToolTipText(shell.getText());
trayItem.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
toggleDisplay(shell, tray);
}
});
final Menu trayMenu = new Menu(shell, SWT.POP_UP);
MenuItem showMenuItem = new MenuItem(trayMenu, SWT.PUSH);
showMenuItem.setText("顯示視窗(&s)");
//顯示視窗,並隱藏系統欄中的表徵圖
showMenuItem.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {
toggleDisplay(shell, tray);
}
});
trayMenu.setDefaultItem(showMenuItem);
new MenuItem(trayMenu, SWT.SEPARATOR);
//系統欄中的退出菜單,程式只能通過這個菜單退出
MenuItem exitMenuItem = new MenuItem(trayMenu, SWT.PUSH);
exitMenuItem.setText("退出程式(&x)");
exitMenuItem.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {
shell.dispose();
}
});
//在系統欄表徵圖點擊滑鼠右鍵時的事件,彈出系統欄菜單
trayItem.addMenuDetectListener(new MenuDetectListener(){
public void menuDetected(MenuDetectEvent e) {
trayMenu.setVisible(true);
}
});
trayItem.setImage(shell.getImage());
//註冊視窗事件監聽器
shell.addShellListener(new ShellAdapter() {
//點擊視窗最小化按鈕時,視窗隱藏,系統欄顯示表徵圖
public void shellIconified(ShellEvent e) {
toggleDisplay(shell, tray);
}
//點擊視窗關閉按鈕時,並不終止程式,而時隱藏視窗,同時系統欄顯示表徵圖
public void shellClosed(ShellEvent e) {
e.doit = false; //消耗掉原本系統來處理的事件
toggleDisplay(shell, tray);
}
});
shell.setSize(320, 240);
center(shell);
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
/**
* 視窗是可見狀態時,則隱藏視窗,同時把系統欄中表徵圖刪除
* 視窗是隱藏狀態時,則顯示視窗,並且在系統欄中顯示表徵圖
* @param shell 視窗
* @param tray 系統欄表徵圖控制項
*/
private static void toggleDisplay(Shell shell, Tray tray) {
try {
shell.setVisible(!shell.isVisible());
tray.getItem(0).setVisible(!shell.isVisible());
if (shell.getVisible()) {
shell.setMinimized(false);
shell.setActive();
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 視窗置中顯示
* @param shell 要顯示的視窗
*/
private static void center(Shell shell){
Monitor monitor = shell.getMonitor();
Rectangle bounds = monitor.getBounds ();
Rectangle rect = shell.getBounds ();
int x = bounds.x + (bounds.width - rect.width) / 2;
int y = bounds.y + (bounds.height - rect.height) / 2;
shell.setLocation (x, y);
}
}
實現效果如下:
左圖是視窗顯示時,系統欄中無表徵圖,而工作列中有表徵圖。右圖是視窗隱藏時,只有系統欄有表徵圖。
過後,看了翻譯軟體 LINGOES 靈格斯的表現形式是:
1. 任何時候系統欄都有表徵圖
2. 最小化按鈕不會隱藏視窗,只是最小化到工作列
3. 關閉按鈕也是不會關閉程式,而是最小化到系統欄
4. 也是只能通過托盤表徵圖的快顯功能表項“退出” 來關閉程式
參考:http://www.eclipseworld.org/bbs/read-cec-tid-15458-fpage-9.html
但最後還留有一個問題:如何?視窗可見狀態時,工作列裡什麼都不顯示呢?