📄 076.htm
字号:
<HTML><HEAD><meta http-equiv="Content-Type" content="text/html; charset=GB2312"><TITLE>-->DELPHI专题文档-程序应用-->如何做一个SYSTRAY程序</TITLE>
<META NAME="keywords" CONTENT=" DELPHI专题文档-程序应用 如何做一个SYSTRAY程序">
<META NAME="description" CONTENT=" - DELPHI专题文档-程序应用 - 如何做一个SYSTRAY程序">
<style>
<!--
#page {position:absolute; z-index:0; left:0px; top:0px}
.tt3 {font: 9pt/12pt "宋体"}
.tt2 {font: 12pt/15pt "宋体"}
a {text-decoration:none}
a:hover {color: blue;text-decoration:underline}
-->
</style>
</HEAD>
<a href="index6.html">返回</a>
<body text="#000000" aLink=#9900ff link=#006699 vLink=#006699 bgcolor="#FFFFFF" leftmargin="3" topmargin="3" marginheight="3" marginwidth="3">
<TABLE WIDTH="100%" CELLPADDING=10 CELLSPACING=0 BORDER=0>
<TR>
<TD class="tt2" bgcolor="#F5F8F8" width="84%"><center><B><FONT style="FONT-SIZE: 16.5pt" COLOR="#FF6666" FACE="楷体_GB2312">如何做一个SYSTRAY程序</FONT></B></center>
<hr color="#EE9B73" size="1" width="94%">
<p class="tt2">Windows 95作为Windows家族的一个里程碑,不仅增加了系统的稳定性,更在易用性上下了很大的功夫。其中任务栏的引入可以说是易用性方面的典范。系统运行的每一个应用程序都在任务栏的任务切换区有对应的按钮,用户可以简便、快捷地在应用程序间切换。通过任务栏的状态指示区,用户可以很方便地到当前系统时间,调节声音大小,切换输入法等。Windows
<br>
95也允许应用程序在状态指示区上放置图标,以指示应用程序目前的状态,或者提醒用户某个事件的发生。现在,越来越多的应用程序,如拨号软件、网络监视软件、杀毒软件、字典等都把自己的图标加到状态指示区上。在大家享受如此方便快捷的服务的同时,作为程序员则更加关注此功能的实现方法,以使自己的产品立于不败之地。<br>
<br>
针对这个问题,我查阅了大量的技术资料及Delphi 3.0所带的源代码,成功地解决了它。以下是对这个问题分析及解决它的三个步骤。<br>
<br>
1.在状态指示区上安装、更改、卸载图标<br>
<br>
Windows 95是基于事件驱动机制的操作系统。任何一个控件都是通过发消息或对系统消息的处理来实现功能的。状态指示区实际上也是一个标准控件。对它的控制和操纵,与其他的标准控件一样,也是通过发消息和处理消息进行的。应用程序通过系统功能调用Shell_NotifyIcon向状态指示区发消息,它的函数说明如下(摘自Delphi的Source\RTL\WIN\shellapi.pas文件):<br>
<br>
function Shell_NotifyIcon(dwMessage: DWORD; lpData: PNotifyIconData): BOOL; stdcall;<br>
<br>
其中:<br>
<br>
<br>
dwMessage:要发给状态指示区的消息,可以取以下三个值:<br>
NIM_ADD 在状态指示区上增加一个图标<br>
NIM_MODIFY 修改一个状态指示区的图标<br>
NIM_DELETE 删除状态指示区的一个图标<br>
lpData:指向TNotifyIconDataA结构的指针,此结构是要增加的图标的信息。<br>
PNotifyIconData = ^TNotifyIconDataA<br>
TNotifyIconDataA = record<br>
cbSize : DWORD;<br>
Wnd : HWND;<br>
uID : UINT;<br>
uFlags : UINT;<br>
uCallbackMessage : UINT;<br>
hIcon : HICON;<br>
szTip : array [0..63] of AnsiChar;<br>
end;<br>
<br>
<br>
各字段的含义如下所述:<br>
<br>
cbSize:记录TNotifyIconDataA的大小,设置为SizeOf( TNotifyIconDataA);<br>
Wnd:接收状态指示区鼠标事件的窗口的句柄,例如:Form1.Handle;<br>
uID:图标的ID(状态指示区鼠标事件的wPara参数的值);<br>
uFlags:此条消息的有效范围(低三位有效)<br>
NIF_MESSAGE 0x1 // uCallbackMessage参数有效<br>
NIF_ICON 0x2 // hIcon is valid参数有效<br>
NIF_TIP 0x4 // szTip is valid参数有效<br>
uCallbackMessage:系统回送消息的ID;<br>
hIcon:显示在状态指示区上的图标的句柄;<br>
szTip:鼠标移动到图标上时系统显示的提示信息。<br>
<br>
<br>
在安装图标时,需要对结构的每一个字段都赋值。而当更改、卸载图标时,则有些字段可以不赋值。当更改图标信息时,除设置需要更改的内容外,要把cbSize,Wnd,uID设置成正确的值,还要按照更改的内容将uFlags调到的相应的位置。例如,只更改图标的提示信息时,把cbSize,Wnd,uID设置为正确的值,szTip赋值为要更改成的提示信息,uFlags赋值为4即可。需要删除图标时,只需要把cbSize,Wnd,uID设置成正确的值即可。<br>
<br>
2.对状态指示区上图标鼠标事件的响应<br>
现在,我们已经在状态指示区上安装了自己的图标,但它并不产生任何实际效果。因为当应用程序接收到鼠标事件后,除了可以显示提示信息外,没有产生任何动作。我们现在要做的就是要响应图标上的鼠标事件。<br>
当用户在你的图标上移动、点击时,状态指示区会向应用程序发送如下的消息:<br>
messageID = uCallbackMessage<br>
wParam = uID<br>
lParam = mouse event (如:WM_LBUTTONDOWN)<br>
我们只需在主窗口的定义中,声明一个过程,来响应这个消息,在它的实现部分就可以对消息进行处理了。<br>
3.隐藏任务切换区的应用程序按钮<br>
完成了上面这些工作以后,我们已经可以在状态指示区成功地安装上图标,而且也可以响应图标上的事件了。美中不足的是,在状态指示区显示应用程序图标的同时,任务切换区也存在此应用程序的按钮,怎么让它不出现在任务切换区上呢?这里又要提到一个系统调用ShowWindow,它的说明如下(摘自Delphi的Source\RTL\WIN\
<br>
windows.pas文件):<br>
function ShowWindow(hWnd: HWND; nCmdShow: Integer): BOOL; stdcall;<br>
<br>
其中:<br>
<br>
hWnd:要改变显示状态的窗口的句柄;<br>
nCmdShow:窗口要改变成为的显示状态:<br>
SW_HIDE 隐藏本窗口,激活另一个窗口<br>
SW_SHOW 激活本窗口<br>
<br>
<br>
当一个应用程序的所有窗口都隐藏时,它的任务按钮就不显示。在用户选取状态指示区的图标时,再让某一个窗口激活就可以了。<br>
<br>
4. 样例<br>
<br>
下面是我在研究过程中做的一个小例子。它运行时在状态指示区上安装一个图标。此图标共有两个运行状态:激活状态和非激活状态。在激活状态下,状态显示区显示一个“笑脸”图标;非激活状态显示一个“哭脸”图标。用户右击此图标,则弹出一个菜单,选取“激活”菜单项时,将切换运行状态,状态指示区的图标也做相应的变化。选取“关闭”菜单项时,卸载状态指示区的图标。<br>
<br>
<br>
unit Utest;<br>
interface<br>
uses<br>
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls,
Menus, <br>
shellapi, StdCtrls;<br>
const<br>
ICON_ID = 1; // 图标在本应用程序中的编号<br>
MI_ICONEVENT = WM_USER + 1; // 图标上的鼠标事件<br>
<br>
type<br>
TForm1 = class(TForm)<br>
pop1: TPopupMenu; // 在图标上右点鼠标时弹出的菜单<br>
status1: TMenuItem; // pop1菜单的第一项,选取它会改变程序的状态<br>
N1: TMenuItem;<br>
close1: TMenuItem; // pop1菜单的最后一项,它会关闭此应用程序<br>
procedure FormCreate(Sender: TObject);<br>
procedure FormClose(Sender: TObject; var Action: TCloseAction);<br>
procedure close1Click(Sender: TObject);<br>
procedure status1Click(Sender: TObject);<br>
private<br>
normalicon, disabledicon: TIcon; //需放在状态指示区的图标<br>
status: Boolean;<br>
procedure InstallIcon; //在状态指示区上安装图标<br>
procedure ChangeIcon(status:Boolean);//根据参数,显示不同的图标<br>
procedure UnInstallIcon; //卸载图标<br>
procedure IconOnClick(var message: TMessage); message MI_ICONEVENT; //响应图标上的鼠标事件<br>
end;<br>
<br>
var<br>
Form1: TForm1;<br>
<br>
implementation<br>
{$R *.DFM}<br>
<br>
procedure TForm1.FormCreate(Sender: TObject);<br>
begin<br>
InstallIcon;<br>
ChangeIcon(False );<br>
ShowWindow(Application.Handle, SW_HIDE ); //隐藏应用程序主窗口机<br>
end;<br>
<br>
procedure TForm1.InstallIcon;<br>
var IconData: TNotifyIconData;<br>
begin<br>
normalicon := TIcon.Create;<br>
disabledicon := TIcon.Create;<br>
normalicon.LoadFromFile( 'normal.ico' );<br>
disabledicon.LoadFromFile( 'disable.ico' );<br>
IconData.cbSize := SizeOf( IconData );<br>
IconData.Wnd := Handle;<br>
IconData.uID := ICON_ID;<br>
IconData.uFlags := NIF_ICON or NIF_MESSAGE or NIF_TIP;<br>
IconData.uCallBackMessage := MI_ICONEVENT;<br>
IconData.hIcon := normalicon.Handle;<br>
IconData.szTip := '我可以在状态指示区上加图标了!';<br>
Shell_NotifyIcon( NIM_ADD, @IconData );<br>
end;<br>
<br>
procedure TForm1.ChangeIcon( status: boolean );<br>
var IconData: TNotifyIconData;<br>
begin<br>
IconData.cbSize := SizeOf(IconData);<br>
IconData.wnd := Handle;<br>
IconData.uID := ICON_ID;<br>
if IconData.fconectado then IconData.hIcon := normalicon.Handle else IconData.hIcon
:= <br>
disabledIcon.Handle;<br>
IconData.uFlags := NIF_ICON;<br>
Shell_NotifyIcon(NIM_MODIFY, @IconData);<br>
end;<br>
<br>
procedure TForm1.UnInstallIcon;<br>
var IconData: TNotifyIconData;<br>
begin<br>
IconData.cbSize := SizeOf( IconData );<br>
IconData.Wnd := Handle;<br>
IconData.uID := ICON_ID;<br>
Shell_NotifyIcon( NIM_DELETE, @IconData );<br>
end;<br>
<br>
procedure TForm1.IconOnClick( var message: Tmessage);<br>
var p : TPoint;<br>
begin<br>
if (message.lParam = WM_LBUTTONDOWN) then<br>
ShowWindow( Application.Handle, SW_SHOW );<br>
if (message.lParam = WM_RBUTTONDOWN) then begin<br>
GetCursorPos( p );<br>
pop1.Popup( p.x ,p.y );<br>
ChangeIcon( status );<br>
end;<br>
end;<br>
<br>
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);<br>
begin<br>
UnInstallIcon;<br>
normalicon.Free;<br>
disabledicon.Free;<br>
end;<br>
<br>
procedure TForm1.FormActivate(Sender: TObject);<br>
begin<br>
ShowWindow( Application.Handle, SW_HIDE );<br>
end;<br>
<br>
procedure TForm1.close1Click(Sender: TObject);<br>
begin<br>
Close;<br>
end;<br>
<br>
procedure TForm1.status1Click(Sender: TObject);<br>
begin<br>
status := not status;<br>
if status then status1.Caption := 'Enable'<br>
else status1.Caption := 'Disable';<br>
end;<br>
end.<br>
</p>
<hr color="#EE9B73" size="1" width="94%">
</TD>
</TR>
</table>
</BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -