|
这将是最后一个组件了,目标定为非可视化,事实上非可视化组件要比可视化组件难做,因为是从TComponent继承而来,就没有了很多属性和事件。而这些都要我们从头来做过。
这个非可视化组件,我决定为托盘组件,其中用到的技术较多,我不如列一个表出来,然后再来讲解好一点。另外,可能篇幅会多一些,请耐心看。
用到的技术:
1作为核心功能,当然是托盘的应用啦。
2?托盘组件怎么样影响到主窗口最小化时隐藏
3?托盘如何处理消息
4?组件编辑器的用法
上面每一个技术都非常有趣,让我们一个个来看吧:
?
一??托盘,是系统壳编程的一个功能,相信我们也看过很多啦,大概知道它用起来是什么样子的。
那么它是如何实现的呢,
Windows定义了这样一个结构来存放托盘的信息:
typedef?strUCt?_NOTIFYICONDATA?{?//?nid??
DWord?cbSize;
????HWND?hWnd;?
????UINT?uID;?
????UINT?uFlags;?
????UINT?uCallbackMessage;?
????HICON?hIcon;?
????char?szTip[64];?
}?NOTIFYICONDATA,?*PNOTIFYICONDATA;
cbSize是NOTIFYICONDATA结构的尺寸,我们一般用Sizeof就可以了
hWnd一个窗口句柄,用于检索托盘消息的。然而我们的非可视组件并没有窗口呀,这就是技术列表第三条要讲的,这里从略
uID?唯?一标识托盘图标的,我们可以随便指定一个数,但如果同时有不同的图标,则数应该不同
uFlags是NIF_ICON,NIF_MESSAGE,NIF_TIP中的一个或多个,我们全用就可以了。
uCallbackMessage;托盘消息,是我们自定义的消息,这里我们定义为:
????????????????const
??????????????????WM_TrayMsg=WM_USER+10;
hIcon托盘图标句柄
szTip这个是托盘提示,当托盘出现时,鼠标移到哪里,就会出现该提示。
Delphi将这个结构重定义为TNotifyIconData,我们照这个来用就行了
?
我们应用托盘要用到API函数Shell_NotifyIcon,其中有两个参数,第一个为
NIM_ADD,NIM_DELETE??,NIM_MODIFY中的一个,分别表示添加托盘(图标出现)
修改托盘(比如图标,提示),删除(图标消失)第二个参数是NOTIFYICONDATA的指针
嗯,托盘应该差不多了。
?
二?这个组件能够决定主窗体最小化时,是否是正常最小化并没有托盘图标。还是最小化到屏幕之外,使我们看不见,且托盘区出现了图标。这里有一个成员为FActive来决定。
那么我们是怎么样影响到主窗体呢,也即怎么截获窗体的最小化消息呢。
全局变量Application有一个方法为procedure?HookMainWindow(Hook:?TWindowHook);
顾名思义,就是钩到主窗口的所有消息。里面的参数是TWindowHook类型,它是一个方法指针,定义如下:
type?TWindowHook?=?function(var?Message:?TMessage):?Boolean?of?object;
我们要自己定义过程的,然后传给HookMainWindow:
function?AppMsgHook(var?Msg:TMessage):Boolean;
Application.HookMainWindow(AppMsgHook);
这样做之后,主窗口的所有消息都会经过AppMsgHook方法啦,最小化消息也不例外,则我们可以在里面截获这个消息,并做一些操作:
?
做什么操作呢,先判断组件是否为设计时,如果是,不进行操作,如果不是进行下一步
if?not?(csDesigning?in?ComponentState)?then
这样的意图是很明显的,因为当设计时的主窗其实是Delphi的IDE,如果让他处理该消息,其实是处理IDE的最小化消息,这时如果你最小化IDE,就会出现托盘啦。所以不能。
?
下一步是是否截获了最小化消息,以及FActive是否为真:
if?(Msg.Msg=WM_SYSCOMMAND)?and(FActive)?then
两样都成立,执行里面的代码,代码中有解释,这里只说两个:
SetWindowLong(Application.Handle,GWL_EXSTYLE?,WS_EX_TOOLWINDOW);
设置了这个属性后,窗口最小化就不会停在任务栏了,而是停在屏幕的某个位置,这个位置在哪里呢,由
placement.flags:=WPF_SETMINPOSITION;
?????placement.ptMinPosition.x:=1050;
?????placement.ptMinPosition.y:=800;
?????SetWindowPlacement(Application.Handle,@placement);
决定,具体的看代码,自己查帮助吧,这里不多说
?
而上说的设置SetWindowLong后,问题来了,窗口最小化的风格一变了,当你把Factive设为False,再最小化窗口,此时是没有托盘图标,但窗口还是最小化到屏幕的那个位置去了,我们看不到,又不能使其恢复(没有托盘)。
上一篇:Delphi 8 for .NET简介
下一篇:WANT的心得
|