送分
解决方案 »
- 汇编机器码操作问题
- 请问winexec函数?
- 在客户端如何知道服务器是否运行?
- 一个用Delphi设计的多样式的软件界面
- 无聊,散分。
- 在sql server中,datetime 怎样把毫秒表示出
- delphi6对数据库操作出现的问题?急!急!急!
- 如何让listview自动转到值为listview1.Items[i].Caption=Edit1.Text且被选中
- 请教上下健的健值是什么我知道回车是13
- w102272(Wonder) 怎么和你联系?有人知道w102272(Wonder) 的email吗
- ★★★★★★★★ 再次求职,人在广州 ★★★★★★★★
- 高手原谅我没分了,可问题还是没解决,关于treeview生成结点时的判断问题,请帮忙看我的代码为什么不对?!
_____________________________________________________________________
Delphi托盘编程实战演练 DavidLove(原作)
关键字 RAD 托盘编程 任务栏 消息机制
很多人认为Delphi是一个RAD工具,包括我本人在上学的时候对Delphi也有偏见,现在走出了“象牙塔”,涉及的面广了,遇到的问题多了,慢慢地也有了自己的一点心得体会。其实,Delphi是基于Object Pascal 语言的开发工具,也就是说Delphi本质上是一种语言工具,并且是真正的面向对象的。下面我举的例子就是用Delphi实现的一个托盘小程序。程序短小精悍,脉络分明,我将对关键部分进行详细讲解。就象候俊杰先生把MFC一层一层地剥开一样,今天我也来一次“庖丁解牛”。 在Delphi中涉及到系统编程的方面毫无例外都要调用API函数,在ShellAPI.pas单元中有要用到的API函数的原型。实战演练:一.新建一个应用程序:File->New Applicaton 在Interface部分定义一个消息常量:const WM_NID=WM_USER+1000; 系统规定从WM_USER开始为用户自定义消息。二.定义一个全局变量: NotifyIcon:TNotifyIconData,NotifyIcon是非常重要的一个变量,整个程序基本上是围着这个变量在转。TNotifyIconData是一个记录类型,按住Ctrl键,在TNotifyIconData 双击即进入ShellAPI.pas单元。(注:在Delphi中,这是一个非常好的对源代码进行分析的方法,源代码说明一切,你要想知道程序背后的内幕,最好的方法就是分析源代码!)此时出现了以下赋值语句:TNotifyIconData = TNotifyIconDataA,这个意思很明显,就是说TNotifyIconData和TNotifyIconDataA是同种数据类型,接着往下看有:TNotifyIconDataA = _NOTIFYICONDATAA,意思与刚才的一样,再往下看: type_NOTIFYICONDATAA = record cbSize: DWORD; Wnd: HWND; uID: UINT; uFlags: UINT; uCallbackMessage: UINT; hIcon: HICON;szTip: array [0..63] of AnsiChar;end;这可真是“千呼万唤始出来,犹抱琵琶半遮面”。现在大家很清楚了,我们刚才定义的全局变量NotifyIcon其实是一个包含有7个成分的记录类型变量,就相当于C/C++中的结构体变量(C/C++的程序员应该是再熟悉不过了)。下面我们逐个来解释记录类型中的7个部分各有什么功能。1> cbSize就是你定义的NotifyIcon变量的大小,用SizeOf(TNotifyIconData)可以取得,如果你是一个熟练的C/C++程序员,你应该不会陌生。在C/C++中,每当要为一个结构体变量分配内存的时候都要:通过 SizeOf(Struct type) 来获知存放一个这样的结构体变量要多少内存。2> Wnd是一个句柄,你希望托盘程序产生的消息有哪个窗体来处理就让Wnd指向那个窗体。例如:你准备在任务栏的托盘小图标上单击时窗体是窗体在“显示”和“隐藏”之间切换,则把Wnd指向主窗体。3> uID:如果你要创建多个托盘小程序,那么怎么区分它们呢?就是靠这个ID号来区分。3> uFlags是一个标志位,它表示当前所创建的托盘程序具有哪些性质:NIF_ICON 表示当前所设置的图标(即hIcon的值)是有效的 NIF_MESSAGE 表示当前所设置的系统消息(即uCallBackMessage的值)是有效的NIF_TIP 表示当前所设置的提示条(即szTip的值)是有效的。4> uCallBackMessage这是7个部分里面最重要的一个。这里指定一个回调消息,也就是说这里定义一个消息名,当你单击或者右击托盘图标的时候就会向你在Wnd所指向的窗体发送一个在uCallBackMessage中定义的消息名,然后你在程序中定义一个消息出来函数来处理这个消息。这样就把Windows关于消息的整套流程都处理好了。 6> hIcon为托盘图标的句柄,根据这个句柄你就可以增加、修改、删除图标。7> szTip就是当你的鼠标放到任务栏托盘的小图标上的时候弹出来的提示信息。在这里我花了大量的笔墨介绍TNotifyIconData的内幕,把这部分搞清楚了,后面的东西就顺理成章了。三. 双击主窗体,进入FormCreate的代码区域:TForm1.FormCreate(Sender:TObject);Begin
//NotifyIcon为全局变量,在程序的开头已经定义了
with NotifyIcon do
begin
cbSize:=SizeOf(TNotifyIconData);
Wnd:=Handle; //指向当前窗体Form1的句柄
uID:=1;
uFlags:=NIF_ICON or NIF_MESSAGE or NIF_TIP;
uCallBackMessage:=WM_NID;//自定义消息
hIcon:=Application.Icon.Handle;
szTip:=”张家恶少”;
end;
//把设置好的变量NotifyIcon加入到系统中以便处理
Shell_NotifyIcon(NIM_ADD,@NotifyIcon);
End;四.接下来就是定义一个消息处理函数:系统给窗体发来了一个消息,就由下面这个函数来处理。每个消息处理函数都是处理某一类消息的,大家仔细地看看下面函数体的定义和一般的函数定义有什么不一样:消息处理函数要在后面加上消息的名称,这样当系统发来WM_NID消息时,就是自动触发WMNID消息处理函数。procedure WMNID(var msg:TMessage);message WM_NID; begin case msg.LParam of WM_LBUTTONUp: Form1.Visible:=not Form1.Visible; WM_RBUTTONUP: ShowMessage(‘您点击的是右键’); End;End;好了,一个最简单的程序诞生了,大家自己设置好自己喜欢的图标.Project->Options,选中Application页面,在Icon项中加载自己喜欢的图标,这样程序运行时,在任务栏里显示的就是你喜欢的图标了。当你单击图标时,窗体Form1会在可见与不可见之间切换,也就是说单击一下显示,再单击一下又隐藏。当你右击图标的时候会弹出一条消息:“你点击的是右键”。五.最后要记住在关闭应用程序的时候要释放掉建立的托盘程序,否则会占用系统资源。TForm1.FormDestroy(Sender:TObject);Begin Shell_NotifyIcon(NIM_DELETE,@NotifyIcon);End; 毕业快半年了,很多东西在学校总理解不了,认识不够深刻;出到社会,接触了不少道中朋友,受益非浅,每有心得体会,总想写成文字,一来总结自己学的东西,二来和大家共同交流。
_____________________________________________________________________________
这个程序一般,但是比较通俗,:-)
procedure wmsyscommand(var Msg: TWMSysCommand); message WM_SYSCOMMAND;procedure TForm1.wmsyscommand(var Msg: TWMSysCommand);
begin
if Msg.CmdType = SC_MINIMIZE then
inherited;
end;
这些是我找到的:给你一篇参考资料:
怎样建立简单的任务栏应用程序:
Windows 95 和 Windows NT 4.0包含一个令人兴奋的特性:任务栏。这个通常位于区域任务条右面的区域能包含小的图标,这些图标能引出大的应用程序或者菜单。本篇文章主要讨论如何使用Delphi建立这样的应用程序。 在开始之前,请看下面的需要的接口方面的内容: 从技术方面来说,一个任务栏应用程序非常象普通的应用程序,它有一个消息循环,相应Windows的消息来完成相应的功能。 Procedure RunTrayApplication;
Var Msg : TMsg;
Begin
CreateWindow;
AddTrayIcon;
While GetMessage(Msg,0,0,0) do Begin
TranslateMessage(Msg);
DispatchMessage(Msg);
End;
DeleteTrayIcon;
End;
你能看到:所有需要做的工作是创建一个窗口,注册一个图标到任务栏,设置它的消息循环,最后关闭它。当然,必须还有增加其他代码完成相应的功能,但是,它是真的不需要担心。
让我们从窗口的创建开始。实际上,这个窗口是不是能在任务栏上能见到的窗口。相应的,这个窗口只是处理消息循环、其它父类的工作。任务窗口(Windows 95 & NT)句柄创建消息(例如鼠标单击等)和将消息发到我们的窗口。 Procedure CreateWindow;
Var
WC : TWndClass;
W : hWnd;
Begin
With WC do Begin
Style := 0;
lpfnWndProc := @WndProc;
cbClsExtra := 0;
cbWndExtra := 0;
hIcon := 0;
hCursor := 0;
hbrBackground := 0;
lpszMenuName := nil;
lpszClassName := 'MyTrayIconClass';
hInstance := System.hInstance;
end;
RegisterClass(WC);
W := Windows.CreateWindow('MyTrayIconClass','MyVeryOwnTrayIconWindow',
ws_OverlappedWindow,0,0,0,0,0,0,hInstance,nil);
ShowWindow(W,sw_Hide);
UpdateWindow(W);
MainWindow := W;
End;
这个窗口使用普通的窗口函数创建。注意这个窗口的类型是“ws_OverlappedWindow”,但是这个尺寸是0,并且它是隐藏的,所有,它将不会显示出来。
下一步是加(注册)我们的图标。这将需要使用Shell_NotifyIcon这个API函数,这个函数实际上可以完成三个功能,这里只需要它的增加的特性。 Procedure AddTrayIcon;
Var IconData : TNotifyIconData;
Begin
With IconData do Begin
cbSize := SizeOf(IconData);
Wnd := MainWindow;
uID := 0;
uFlags := nif_Icon Or nif_Message Or nif_Tip;
uCallBackMessage := wm_MyCallBack;
hIcon := LoadIcon(hInstance,'MYICON');
StrCopy(szTip,PChar(TrayIconTip));
End;
Shell_NotifyIcon(nim_Add,@IconData);
End;
这个最重要的事情是TNotifyIconData的数据结构,它是一个设置Window句柄的数据结构,是一个记录参数,对我们来说,我们需要设置这个图标的窗口句柄(这将定义哪个窗口处理消息循环),回调消息号,图标,工具提示等。一旦这个数据设置了,我们就可以增加一个图标到任务栏上了。为了完成这个工作,使用nim_Add程序。
现行我们已经加了我们的图标到任务栏,下面需要决定如何处理消息。 Const
wm_MyCallback = wm_User+1000;
cm_Exit = 100; { we worry about... }
cm_About = 101; { ...these later }
这个实际的窗口处理过程也是相当普通。几个窗口消息(如wm_NCCreate)必须处理。然而,对我们来说,更重要的事情是处理wm_MyCallback和wm_Command消息:
Function WndProc(Window : hWnd; Msg,WParam,LParam : Integer): Integer; StdCall;
Begin
Result := 0;
Case Msg of
wm_NCCreate : Result := 1;
wm_Destroy : PostQuitMessage(0);
wm_Command : Begin { a command was chosen from the popup menu }
If (WParam = cm_Exit) Then
PostMessage(Window,wm_Destroy,0,0)
Else If (WParam = cm_About) Then
MessageBox(0,'Shell Test Copyright ?'+
'Jani J鋜vinen 1996.',
'About Shell Test',mb_OK)
Else OpenDesktopIcon(WParam-cm_About);
End;
wm_MyCallback : Begin { our icon was clicked }
If (LParam = wm_LButtonDown) Then
ShowIconPopupMenu
Else If (LParam = wm_RButtonDown) Then
ShowAboutPopupMenu;
End;
Else Result := DefWindowProc(Window,Msg,WParam,LParam);
End;
End;
就象你看到的一样,当用户单击图标时,Windows提示我们。注意我们不使用通常使用的wm_LButtonDown 消息,而使用wm_MyCallback message,详细的消息信息存储在LParam参数中。
当用户单击鼠标右键,我们创建一个菜单在桌面上。 Type
TIconData = Array[1..100] of String;
Var
IconData : TIconData;
Procedure ShowIconPopupMenu;
Var
ShellFolder : IShellFolder;
EnumIDList : IEnumIDList;
Result : hResult;
Dummy : ULong;
ItemIDList : TItemIDList;
Pntr : PItemIDList;
StrRet : TStrRet;
PopupMenu : hMenu;
ItemID : Integer;
Pos : TPoint;
Procedure AddToMenu(Item : String);
Var S : String;
Begin
IconData[ItemID-cm_About] := Item;
S := ExtractFileName(Item);
If (System.Pos('.',S) <> 0) Then SetLength(S,System.Pos('.',S)-1);
AppendMenu(PopupMenu,mf_Enabled Or mf_String,ItemID,PChar(S));
Inc(ItemID);
End;
begin
PopupMenu := CreatePopupMenu;
ItemID := cm_About+1;
SHGetDesktopFolder(ShellFolder);
ShellFolder.EnumObjects(MainWindow,SHCONTF_NONFOLDERS,EnumIDList);
Pntr := @ItemIDList;
Result := EnumIDList.Next(1,Pntr,Dummy);
While (Result = NoError) do Begin
ShellFolder.GetDisplayNameOf(Pntr,SHGDN_FORPARSING,@StrRet);
With StrRet do AddToMenu(String(CStr));
Result := EnumIDList.Next(1,Pntr,Dummy);
End;
EnumIDList.Release;
ShellFolder.Release;
GetCursorPos(Pos);
AppendMenu(PopupMenu,mf_Separator,0,'');
AppendMenu(PopupMenu,mf_Enabled Or mf_String,cm_Exit,'E&xit');
SetForegroundWindow(MainWindow);
TrackPopupMenu(PopupMenu,tpm_LeftAlign Or tpm_LeftButton,
Pos.X,Pos.Y,0,MainWindow,nil);
DestroyMenu(PopupMenu);
end;
上面的程序看起来有点复杂,你可以将它分成两个部分来看:创建和显示菜单。
列举创建菜单是用Windows的外壳接口完成的。首先,我们使用SHGetDesktopForlder函数得到使用桌面的IShellFolder接口。使用这个接口,我们能得到另一个接口的实例:IEnumIDList。这个接口通常实现实际的列举工作。我们简单的重复调用这个函数直到错误值返回(例如:所有的菜单被列举)。当我们得到一个菜单,我们使用AddToMenu函数加它。 当所有的菜单被列举和创建后,现在我们需要运行这个菜单。我们将找到的菜单保存到一个全局的List变量中,每一个菜单都拥有它的菜单号。这确保我们能得到它的索引。
OpenDesktopIcon(WParam-cm_About) 当然,WParam中储存了用户单击鼠标的菜单的菜单号(ID)。 下面我们将处理运行用户选择的菜单。 Procedure OpenDesktopIcon(Number : Integer);
Var
S : String;
I : Integer;
begin
S := IconData[Number];
I := ShellExecute(0,nil,PChar(S),nil,nil,sw_ShowNormal);
If (I < 32) Then Begin
S := 'Could not open selected item "'+S+'". '+
'Result was: '+IntToStr(I)+'.';
MessageBox(0,PChar(S),'Shell Test',mb_OK);
End;
end;
http://expert.csdn.net/Expert/FAQ/FAQ_Index.asp?id=6657
西安交通大学
刘明华
---- 在Windows桌面的任务栏上有一个凹陷的区域,其中显示着系统时钟以及一些图标,这个长方形的区
域便是Windows的任务栏状态区(taskbar status area)。本文将介绍使用Borland Delphi进行任务栏状态
区的编程,即怎样将应用程序的图标显示在任务栏状态区中。 ---- 实现原理 ---- 任务栏状态区的图标添加、删除、以及修改是通过Windows API函数Shell_NotifyIcon来实现的,该函
数是由Windows的SHELL32.DLL动态联接库提供的。在Delphi中,Shell_NotifyIcon函数是在ShellAPI单元
声明的,其 ---- 函数原型如下: ---- function Shell_NotifyIcon(dwMessage: DWORD; lpData: PNotifyIconData): BOOL; stdcall; ---- 其中参数dwMessage的取值决定函数Shell_NotifyIcon所要进行的操作的类型,它的取值可以是以下三
者之一: ---- NIM_ADD(值为0):在任务栏状态区插入一个图标。 ---- NIM_DELETE(值为1):从任务栏状态区删除一个图标。 ---- NIM_MODIFY(值为2):修改任务栏状态区的图标、提示信息、或者通知消息。 ---- 参数lpData 是一个记录类型(结构类型)的指针,记录类型NotifyIconData的定义如下: NOTIFYICONDATA = record
cbSize: DWORD;
Wnd: HWND;
uID: UINT;
uFlags: UINT;
uCallbackMessage: UINT;
hIcon: HICON;
szTip: array [0..63] of AnsiChar;
end;
---- cbSize:NOTIFYICONDATA记录的大小。
---- Wnd:与此状态区图标相关联的窗口句柄,此窗口将负责处理uCallbackMessage消息。 ---- uID:程序自定义的状态区图标的标识符。 ---- uFlags:这个字段指明NOTIFYICONDATA记录中的成员uCallbackMessage、hIcon和szTip这三者的哪些
项的值有效。它的取值可以是下列三者的组合(or运算): ---- NIF_MESSAGE (值为1):uCallbackMessage项包含了有效的信息。 ---- NIF_ICON(值为2):hIcon项包含了有效的信息。 ---- NIF_TIP(值为4): szTip项包含了有效的信息。 ---- uCallbackMessage:程序定义的消息标识符(32位的整数)。当鼠标在状态区图标上移动或者点击(
即,发生了鼠标事件)时,操作系统将向Wnd指定的那个窗口发送uCallbackMessage消息。
在uCallbackMessage消息中,lParam参数包含了Windows的鼠标消息的类型,而wParam参数则包含了图标标
识(即uID)。有效的鼠标消息包括以下几个:WM_LBUTTONDOWN、WM_RBUTTONDOWN、WM_MBUTTONDOWN、
WM_LBUTTONUP、WM_RBUTTONUP、WM_MBUTTONUP、WM_MOUSEMOVE、WM_LBUTTONDBLCLK、WM_RBUTTONDBLCLK
以及WM_MBUTTONDBLCLK。 ---- hIcon:指定一个图标句柄。 ---- szTip:显示在图标上的提示信息(少于63个字符)。 ---- Delphi中的实现 ---- 通过上面的介绍中,我们不难看出,任务栏状态区的编程主要是处理两方面的工作:添加、删除、修改
图标;以及处理通知消息。对于图标的添加、删除、修改操作,可以通过调用Shell_NotifyIcon函数来实现。
而对于自定义的通知消息,我们就应该在消息循环中给予处理了。
---- 下面的示例给出了状态区图标的添加、修改和删除操作的例子,以及图标的通知消息的基本处理框架。
unit Unit1;interfaceuses
Windows, Messages, SysUtils, Classes, Graphics,
Controls, Forms, Dialogs, ExtCtrls, ShellAPI;const
WM_TRAYNOTIFY=WM_USER+1;//定义通知消息type
TForm1 = class(TForm)
Timer1: TTimer;
procedure FormCreate(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
procedure WndProc(var Msg: TMessage); override;
end;var
Form1: TForm1;
nd0, nd1:NotifyIconData;
hs:array[0..9]of LongWord;implementation
{$R *.DFM}procedure TForm1.FormCreate(Sender: TObject);
begin
//加载Icon0..Icon9这10个图标资源,
并且保存它们的句柄。
//图标Icon0..Icon9分别对应与0..9这9个数字。
hs[0]:=LoadIcon(hInstance, 'Icon0');
hs[1]:=LoadIcon(hInstance, 'Icon1');
hs[2]:=LoadIcon(hInstance, 'Icon2');
hs[3]:=LoadIcon(hInstance, 'Icon3');
hs[4]:=LoadIcon(hInstance, 'Icon4');
hs[5]:=LoadIcon(hInstance, 'Icon5');
hs[6]:=LoadIcon(hInstance, 'Icon6');
hs[7]:=LoadIcon(hInstance, 'Icon7');
hs[8]:=LoadIcon(hInstance, 'Icon8');
hs[9]:=LoadIcon(hInstance, 'Icon9'); //填充NotifyIconData记录型变量nd0
nd0.cbSize := sizeof(NotifyIconData);
nd0.Wnd := handle;
nd0.uID := 0;
nd0.uFlags := NIF_MESSAGE or NIF_ICON or NIF_TIP;
nd0.uCallbackMessage := WM_TRAYNOTIFY;
nd0.hIcon := hs[0];
StrPLCopy(nd0.szTip, 'Hello, World!', 63); //填充NotifyIconData记录型变量nd1
nd1.cbSize := sizeof(NotifyIconData);
nd1.Wnd := handle;
nd1.uID := 1;
nd1.uFlags := NIF_MESSAGE or NIF_ICON or NIF_TIP;
nd1.uCallbackMessage := WM_TRAYNOTIFY;
nd1.hIcon := hs[0];
StrPLCopy(nd1.szTip, 'Simon Loves Daisy', 63); //在任务栏状态区添加图标
Shell_NotifyIcon(NIM_ADD, @nd0);
Shell_NotifyIcon(NIM_ADD, @nd1);
end;procedure TForm1.Timer1Timer(Sender: TObject);
var
st:SystemTime;
begin
//每秒钟更新一次图标:图标0显示秒数的十位,
图标1显示秒数的个位。
GetLocalTime(st);
nd0.hIcon := hs[st.wSecond div 10];
nd1.hIcon := hs[st.wSecond mod 10];
//修改任务栏状态区的图标
Shell_NotifyIcon(NIM_MODIFY, @nd0);
Shell_NotifyIcon(NIM_MODIFY, @nd1);
end;procedure TForm1.FormDestroy(Sender: TObject);
begin
//将图标从任务栏状态区删除
Shell_NotifyIcon(NIM_DELETE, @nd0);
Shell_NotifyIcon(NIM_DELETE, @nd1);
end;//处理 通知消息
procedure TForm1.WndProc(var Msg: TMessage);
var
IconID:integer;
pt:TPOINT;
begin
if msg.Msg = WM_TRAYNOTIFY then
begin
{
在通知消息中,wParam参数为图标的uID,
lParam参数为鼠标事件的类型。
}
iconID := msg.WParam;
//获取鼠标的在屏幕上的位置
GetCursorPos(pt); //通知消息的处理的基本框架结构如下:
case msg.lParam of
WM_LBUTTONDOWN:
begin
//鼠标右键被按下
end;
WM_RBUTTONDOWN:
begin
//鼠标左键被按下
end;
WM_LBUTTONUP:
begin
//释放鼠标左键
end;
WM_RBUTTONUP:
begin
//释放鼠标右键
end;
WM_MOUSEMOVE:
begin
//鼠标在图标上移动
end;
WM_LBUTTONDBLCLK:
begin
//鼠标左键双击
end;
WM_RBUTTONDBLCLK:
begin
//鼠标右键双击
end;
end; //end case
end
else//调用父类的WndProc方法处理其它消息
inherited;
end;end.
_____________________________________________________________________
Delphi托盘编程实战演练 DavidLove(原作)
关键字 RAD 托盘编程 任务栏 消息机制
很多人认为Delphi是一个RAD工具,包括我本人在上学的时候对Delphi也有偏见,现在走出了“象牙塔”,涉及的面广了,遇到的问题多了,慢慢地也有了自己的一点心得体会。其实,Delphi是基于Object Pascal 语言的开发工具,也就是说Delphi本质上是一种语言工具,并且是真正的面向对象的。下面我举的例子就是用Delphi实现的一个托盘小程序。程序短小精悍,脉络分明,我将对关键部分进行详细讲解。就象候俊杰先生把MFC一层一层地剥开一样,今天我也来一次“庖丁解牛”。 在Delphi中涉及到系统编程的方面毫无例外都要调用API函数,在ShellAPI.pas单元中有要用到的API函数的原型。实战演练:一.新建一个应用程序:File->New Applicaton 在Interface部分定义一个消息常量:const WM_NID=WM_USER+1000; 系统规定从WM_USER开始为用户自定义消息。二.定义一个全局变量: NotifyIcon:TNotifyIconData,NotifyIcon是非常重要的一个变量,整个程序基本上是围着这个变量在转。TNotifyIconData是一个记录类型,按住Ctrl键,在TNotifyIconData 双击即进入ShellAPI.pas单元。(注:在Delphi中,这是一个非常好的对源代码进行分析的方法,源代码说明一切,你要想知道程序背后的内幕,最好的方法就是分析源代码!)此时出现了以下赋值语句:TNotifyIconData = TNotifyIconDataA,这个意思很明显,就是说TNotifyIconData和TNotifyIconDataA是同种数据类型,接着往下看有:TNotifyIconDataA = _NOTIFYICONDATAA,意思与刚才的一样,再往下看: type_NOTIFYICONDATAA = record cbSize: DWORD; Wnd: HWND; uID: UINT; uFlags: UINT; uCallbackMessage: UINT; hIcon: HICON;szTip: array [0..63] of AnsiChar;end;这可真是“千呼万唤始出来,犹抱琵琶半遮面”。现在大家很清楚了,我们刚才定义的全局变量NotifyIcon其实是一个包含有7个成分的记录类型变量,就相当于C/C++中的结构体变量(C/C++的程序员应该是再熟悉不过了)。下面我们逐个来解释记录类型中的7个部分各有什么功能。1> cbSize就是你定义的NotifyIcon变量的大小,用SizeOf(TNotifyIconData)可以取得,如果你是一个熟练的C/C++程序员,你应该不会陌生。在C/C++中,每当要为一个结构体变量分配内存的时候都要:通过 SizeOf(Struct type) 来获知存放一个这样的结构体变量要多少内存。2> Wnd是一个句柄,你希望托盘程序产生的消息有哪个窗体来处理就让Wnd指向那个窗体。例如:你准备在任务栏的托盘小图标上单击时窗体是窗体在“显示”和“隐藏”之间切换,则把Wnd指向主窗体。3> uID:如果你要创建多个托盘小程序,那么怎么区分它们呢?就是靠这个ID号来区分。3> uFlags是一个标志位,它表示当前所创建的托盘程序具有哪些性质:NIF_ICON 表示当前所设置的图标(即hIcon的值)是有效的 NIF_MESSAGE 表示当前所设置的系统消息(即uCallBackMessage的值)是有效的NIF_TIP 表示当前所设置的提示条(即szTip的值)是有效的。4> uCallBackMessage这是7个部分里面最重要的一个。这里指定一个回调消息,也就是说这里定义一个消息名,当你单击或者右击托盘图标的时候就会向你在Wnd所指向的窗体发送一个在uCallBackMessage中定义的消息名,然后你在程序中定义一个消息出来函数来处理这个消息。这样就把Windows关于消息的整套流程都处理好了。 6> hIcon为托盘图标的句柄,根据这个句柄你就可以增加、修改、删除图标。7> szTip就是当你的鼠标放到任务栏托盘的小图标上的时候弹出来的提示信息。在这里我花了大量的笔墨介绍TNotifyIconData的内幕,把这部分搞清楚了,后面的东西就顺理成章了。三. 双击主窗体,进入FormCreate的代码区域:TForm1.FormCreate(Sender:TObject);Begin
//NotifyIcon为全局变量,在程序的开头已经定义了
with NotifyIcon do
begin
cbSize:=SizeOf(TNotifyIconData);
Wnd:=Handle; //指向当前窗体Form1的句柄
uID:=1;
uFlags:=NIF_ICON or NIF_MESSAGE or NIF_TIP;
uCallBackMessage:=WM_NID;//自定义消息
hIcon:=Application.Icon.Handle;
szTip:=”张家恶少”;
end;
//把设置好的变量NotifyIcon加入到系统中以便处理
Shell_NotifyIcon(NIM_ADD,@NotifyIcon);
End;四.接下来就是定义一个消息处理函数:系统给窗体发来了一个消息,就由下面这个函数来处理。每个消息处理函数都是处理某一类消息的,大家仔细地看看下面函数体的定义和一般的函数定义有什么不一样:消息处理函数要在后面加上消息的名称,这样当系统发来WM_NID消息时,就是自动触发WMNID消息处理函数。procedure WMNID(var msg:TMessage);message WM_NID; begin case msg.LParam of WM_LBUTTONUp: Form1.Visible:=not Form1.Visible; WM_RBUTTONUP: ShowMessage(‘您点击的是右键’); End;End;好了,一个最简单的程序诞生了,大家自己设置好自己喜欢的图标.Project->Options,选中Application页面,在Icon项中加载自己喜欢的图标,这样程序运行时,在任务栏里显示的就是你喜欢的图标了。当你单击图标时,窗体Form1会在可见与不可见之间切换,也就是说单击一下显示,再单击一下又隐藏。当你右击图标的时候会弹出一条消息:“你点击的是右键”。五.最后要记住在关闭应用程序的时候要释放掉建立的托盘程序,否则会占用系统资源。TForm1.FormDestroy(Sender:TObject);Begin Shell_NotifyIcon(NIM_DELETE,@NotifyIcon);End; 毕业快半年了,很多东西在学校总理解不了,认识不够深刻;出到社会,接触了不少道中朋友,受益非浅,每有心得体会,总想写成文字,一来总结自己学的东西,二来和大家共同交流。
_____________________________________________________________________________
这个程序一般,但是比较通俗,:-)
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Menus,shellapi;
const
wm_trayicon=wm_app+0;type
TForm1 = class(TForm)
PopupMenu1: TPopupMenu;
N1: TMenuItem;
N2: TMenuItem;
procedure FormDestroy(Sender: TObject);
procedure N1Click(Sender: TObject);
procedure N2Click(Sender: TObject);
procedure FormShow(Sender: TObject);
private
{ Private declarations }
procedure wmtrayicon(var message:tmessage); message wm_trayicon;
Procedure WMSysCommand(Var msg : TMessage);Message WM_SYSCOMMAND;
public
{ Public declarations }
end;var
Form1: TForm1;implementation
{$R *.dfm}
procedure modifytrayicon(action:dword);
var
nidata:tnotifyicondata;
begin
with nidata do begin
cbsize:=sizeof(tnotifyicondata);
uid:=0;
uflags:=NIF_MESSAGE or NIF_ICON or NIF_TIP;
wnd:=Form1.handle;
ucallbackmessage:=wm_trayicon;
hicon:=application.Icon.Handle ;
strpcopy(sztip,application.Title );
end;
shell_notifyicon(action,@nidata);
end;procedure TForm1.wmtrayicon(var message:tmessage);
var
mousepos:tpoint;
begin
case message.lParam of
//左键按下
WM_LBUTTONDOWN : begin
application.MainForm.BringToFront; //窗体置前
end;
//左键双击
WM_LBUTTONDBLCLK : begin //窗体隐含或显示
Application.MainForm.Visible := not Application.MainForm.Visible;
SetForegroundWindow(Application.Handle);
end;
//右键按下
WM_RBUTTONDOWN : begin //显示弹出菜单
setactivewindow(handle);
getcursorpos(mousepos);
popupmenu1.Popup(mousepos.X,mousepos.Y);
end;
end//case
end;procedure Tform1.WMSysCommand(var msg: TMessage);
begin
case Msg.WParam of
SC_MINIMIZE: begin
msg.WParam:=0;
modifytrayicon(nim_add);
Application.MainForm.Visible:=false;
end;
SC_CLOSE :begin
msg.WParam :=0;
modifytrayicon(nim_add);
Application.MainForm.Visible:=false;
end;
end;
Inherited;
end;procedure TForm1.FormDestroy(Sender: TObject);
begin
modifytrayicon(nim_delete); //删除托盘
end;procedure TForm1.N1Click(Sender: TObject);
begin
Application.MainForm.Visible :=true;
end;procedure TForm1.N2Click(Sender: TObject);
begin
close;
end;procedure TForm1.FormShow(Sender: TObject);
begin
modifytrayicon(nim_delete);
end;end.
给你个托盘控件!