SWT 中实现最小化到托盘图标,并只能通过托盘的弹出菜单关闭程序
我们有些程序会想要托盘处显示图标,最小化到系统栏;关闭按钮不关闭程序,也是最小化到系统栏;点击托盘图标激活窗口,通过托盘图标的弹出菜单来退出程序。
本段代码就是要完成这样的功能,是 SWT 来实现的。
直接代码给出,代码中有较详细的注释,说明了本程序的功能及实现。文中的任务栏和系统栏应该知道是指哪一段吧,微软就是这么定义的,用 spyxx 的 findwindow 窥探一下就知道了。
实现效果如下:
左图是窗口显示时,系统栏中无图标,而任务栏中有图标。右图是窗口隐藏时,只有系统栏有图标。
过后,看了翻译软件 LINGOES 灵格斯的表现形式是:
1. 任何时候系统栏都有图标
2. 最小化按钮不会隐藏窗口,只是最小化到任务栏
3. 关闭按钮也是不会关闭程序,而是最小化到系统栏
4. 也是只能通过托盘图标的弹出菜单项“退出” 来关闭程序
参考:http://www.eclipseworld.org/bbs/read-cec-tid-15458-fpage-9.html
但最后还留有一个问题:如何实现窗口可见状态时,任务栏里什么都不显示呢? 永久链接 https://yanbin.blog/swt-systray-close-via-tray/, 来自 隔叶黄莺 Yanbin's Blog
[版权声明]
本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。
本段代码就是要完成这样的功能,是 SWT 来实现的。
直接代码给出,代码中有较详细的注释,说明了本程序的功能及实现。文中的任务栏和系统栏应该知道是指哪一段吧,微软就是这么定义的,用 spyxx 的 findwindow 窥探一下就知道了。
1package com.unmi;
2
3import org.eclipse.swt.*;
4import org.eclipse.swt.events.*;
5import org.eclipse.swt.graphics.*;
6import org.eclipse.swt.widgets.*;
7
8/**
9 * SWT 3.0 开始引入了 Tray,可以在系统栏放置你的程序图标了
10 * 本程序实现的功能有四:
11 * 1. 点击窗口的最小化或关闭按钮都是隐藏窗口--任务栏里不显示,不退出程序
12 * 2. 窗口隐藏时,任务栏无图标,系统栏有图标;窗口处于显示状态时则恰好相反
13 * 3. 窗口隐藏时可通过单击系统栏图标或点击系统栏的 "显示窗口" 菜单显示窗口
14 * 4. 程序只能通过点击系统栏的 "退出程序" 菜单项退出,窗口的 X 按钮无效
15 * @author Unmi
16 *
17 */
18public class TrayExample {
19
20 public static void main(String[] args) {
21 Display display = new Display();
22
23 //禁用掉了最大化按钮
24 final Shell shell = new Shell(display,SWT.SHELL_TRIM ^ SWT.MAX);
25 shell.setText("TrayExample");
26
27 //取系统中预置的图标,省得测试运行时还得加个图标文件
28 shell.setImage(display.getSystemImage(SWT.ICON_WORKING));
29
30 //构造系统栏控件
31 final Tray tray = display.getSystemTray();
32 final TrayItem trayItem = new TrayItem(tray, SWT.NONE);
33
34 //程序启动时,窗口是显示的,所以系统栏图标隐藏
35 trayItem.setVisible(false);
36 trayItem.setToolTipText(shell.getText());
37
38 trayItem.addSelectionListener(new SelectionAdapter() {
39 public void widgetSelected(SelectionEvent e) {
40 toggleDisplay(shell, tray);
41 }
42 });
43
44 final Menu trayMenu = new Menu(shell, SWT.POP_UP);
45 MenuItem showMenuItem = new MenuItem(trayMenu, SWT.PUSH);
46 showMenuItem.setText("显示窗口(&s)");
47
48 //显示窗口,并隐藏系统栏中的图标
49 showMenuItem.addSelectionListener(new SelectionAdapter() {
50 public void widgetSelected(SelectionEvent event) {
51 toggleDisplay(shell, tray);
52 }
53 });
54
55 trayMenu.setDefaultItem(showMenuItem);
56
57 new MenuItem(trayMenu, SWT.SEPARATOR);
58
59 //系统栏中的退出菜单,程序只能通过这个菜单退出
60 MenuItem exitMenuItem = new MenuItem(trayMenu, SWT.PUSH);
61 exitMenuItem.setText("退出程序(&x)");
62
63 exitMenuItem.addSelectionListener(new SelectionAdapter() {
64 public void widgetSelected(SelectionEvent event) {
65 shell.dispose();
66 }
67 });
68
69 //在系统栏图标点击鼠标右键时的事件,弹出系统栏菜单
70 trayItem.addMenuDetectListener(new MenuDetectListener(){
71 public void menuDetected(MenuDetectEvent e) {
72 trayMenu.setVisible(true);
73 }
74 });
75
76 trayItem.setImage(shell.getImage());
77
78 //注册窗口事件监听器
79 shell.addShellListener(new ShellAdapter() {
80
81 //点击窗口最小化按钮时,窗口隐藏,系统栏显示图标
82 public void shellIconified(ShellEvent e) {
83 toggleDisplay(shell, tray);
84 }
85
86 //点击窗口关闭按钮时,并不终止程序,而时隐藏窗口,同时系统栏显示图标
87 public void shellClosed(ShellEvent e) {
88 e.doit = false; //消耗掉原本系统来处理的事件
89 toggleDisplay(shell, tray);
90 }
91 });
92
93 shell.setSize(320, 240);
94 center(shell);
95 shell.open();
96 while (!shell.isDisposed()) {
97 if (!display.readAndDispatch())
98 display.sleep();
99 }
100 display.dispose();
101 }
102
103 /**
104 * 窗口是可见状态时,则隐藏窗口,同时把系统栏中图标删除
105 * 窗口是隐藏状态时,则显示窗口,并且在系统栏中显示图标
106 * @param shell 窗口
107 * @param tray 系统栏图标控件
108 */
109 private static void toggleDisplay(Shell shell, Tray tray) {
110 try {
111 shell.setVisible(!shell.isVisible());
112 tray.getItem(0).setVisible(!shell.isVisible());
113 if (shell.getVisible()) {
114 shell.setMinimized(false);
115 shell.setActive();
116 }
117 } catch (Exception e) {
118 e.printStackTrace();
119 }
120 }
121
122 /**
123 * 窗口居中显示
124 * @param shell 要显示的窗口
125 */
126 private static void center(Shell shell){
127 Monitor monitor = shell.getMonitor();
128 Rectangle bounds = monitor.getBounds ();
129 Rectangle rect = shell.getBounds ();
130 int x = bounds.x + (bounds.width - rect.width) / 2;
131 int y = bounds.y + (bounds.height - rect.height) / 2;
132 shell.setLocation (x, y);
133 }
134}实现效果如下:
左图是窗口显示时,系统栏中无图标,而任务栏中有图标。右图是窗口隐藏时,只有系统栏有图标。过后,看了翻译软件 LINGOES 灵格斯的表现形式是:
1. 任何时候系统栏都有图标
2. 最小化按钮不会隐藏窗口,只是最小化到任务栏
3. 关闭按钮也是不会关闭程序,而是最小化到系统栏
4. 也是只能通过托盘图标的弹出菜单项“退出” 来关闭程序
参考:http://www.eclipseworld.org/bbs/read-cec-tid-15458-fpage-9.html
但最后还留有一个问题:如何实现窗口可见状态时,任务栏里什么都不显示呢? 永久链接 https://yanbin.blog/swt-systray-close-via-tray/, 来自 隔叶黄莺 Yanbin's Blog
[版权声明]
本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。