📄 034.htm
字号:
<HTML><HEAD><meta http-equiv="Content-Type" content="text/html; charset=GB2312"><TITLE>-->DELPHI专题文档-程序应用-->怎样建立简单的任务栏应用程序</TITLE>
<META NAME="keywords" CONTENT=" DELPHI专题文档-程序应用 怎样建立简单的任务栏应用程序">
<META NAME="description" CONTENT=" - DELPHI专题文档-程序应用 - 怎样建立简单的任务栏应用程序">
<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">怎样建立简单的任务栏应用程序</FONT></B></center>
<hr color="#EE9B73" size="1" width="94%">
<p class="tt2"><span>Windows 95 和 Windows NT 4.0包含一个令人兴奋的特性:任务栏。这个通常位于区域任务条右面的区域能包含小的图标,这些图标能引出大的应用程序或者菜单。本篇文章主要讨论如何使用Delphi建立这样的应用程序。
<br>
在开始之前,请看下面的需要的接口方面的内容: <br>
从技术方面来说,一个任务栏应用程序非常象普通的应用程序,它有一个消息循环,相应Windows的消息来完成相应的功能。<br>
Procedure RunTrayApplication;<br>
Var Msg : TMsg;<br>
Begin <br>
CreateWindow;<br>
AddTrayIcon; <br>
While GetMessage(Msg,0,0,0) do <br>
Begin <br>
TranslateMessage(Msg);<br>
DispatchMessage(Msg);<br>
End; DeleteTrayIcon; <br>
End; <br>
<br>
你能看到:所有需要做的工作是创建一个窗口,注册一个图标到任务栏,设置它的消息循环,最后关闭它。当然,必须还有增加其他代码完成相应的功能,但是,它是真的不需要担心。
<br>
让我们从窗口的创建开始。实际上,这个窗口是不是能在任务栏上能见到的窗口。相应的,这个窗口只是处理消息循环、其它父类的工作。任务窗口(Windows
95 & NT)句柄创建消息(例如鼠标单击等)和将消息发到我们的窗口。
<br>
<br>
Procedure CreateWindow;<br>
Var WC : TWndClass;<br>
W : hWnd;<br>
Begin <br>
With WC do <br>
Begin<br>
Style := 0;<br>
lpfnWndProc := @WndProc;<br>
cbClsExtra := 0;<br>
cbWndExtra := 0;<br>
hIcon := 0;<br>
hCursor := 0;<br>
hbrBackground := 0;<br>
lpszMenuName := nil;<br>
lpszClassName := 'MyTrayIconClass';<br>
hInstance := System.hInstance;<br>
end;<br>
RegisterClass(WC);<br>
W := Windows.CreateWindow('MyTrayIconClass','MyVeryOwnTrayIconWindow',
ws_OverlappedWindow,0,0,0,0,0,0,hInstance,nil);<br>
ShowWindow(W,sw_Hide);<br>
UpdateWindow(W);<br>
MainWindow := W;<br>
End; <br>
这个窗口使用普通的窗口函数创建。注意这个窗口的类型是“ws_OverlappedWindow”,但是这个尺寸是0,并且它是隐藏的,所有,它将不会显示出来。
<br>
下一步是加(注册)我们的图标。这将需要使用Shell_NotifyIcon这个API函数,这个函数实际上可以完成三个功能,这里只需要它的增加的特性。
</span></p>
<p class="p2"><span>Procedure AddTrayIcon;<br>
Var IconData : TNotifyIconData;<br>
Begin<br>
With IconData do<br>
Begin<br>
cbSize := SizeOf(IconData)<br>
; Wnd := MainWindow;<br>
uID := 0;<br>
uFlags := nif_Icon Or nif_Message Or nif_Tip;<br>
uCallBackMessage := wm_MyCallBack;<br>
hIcon := LoadIcon(hInstance,'MYICON');<br>
StrCopy(szTip,PChar(TrayIconTip));<br>
End;<br>
Shell_NotifyIcon(nim_Add,@IconData);<br>
End; <br>
<br>
这个最重要的事情是TNotifyIconData的数据结构,它是一个设置Window句柄的数据结构,是一个记录参数,对我们来说,我们需要设置这个图标的窗口句柄(这将定义哪个窗口处理消息循环),回调消息号,图标,工具提示等。一旦这个数据设置了,我们就可以增加一个图标到任务栏上了。为了完成这个工作,使用nim_Add程序。
<br>
现行我们已经加了我们的图标到任务栏,下面需要决定如何处理消息。
<br>
<br>
Const wm_MyCallback = wm_User+1000;<br>
cm_Exit = 100;<br>
{ we worry about... }<br>
cm_About = 101;<br>
{ ...these later } <br>
<br>
这个实际的窗口处理过程也是相当普通。几个窗口消息(如wm_NCCreate)必须处理。然而,对我们来说,更重要的事情是处理wm_MyCallback和wm_Command消息:
<br>
<br>
Function WndProc(Window : hWnd; Msg,WParam,LParam : Integer): Integer; StdCall;<br>
Begin<br>
Result := 0;<br>
Case Msg of wm_NCCreate :<br>
Result := 1;<br>
wm_Destroy : PostQuitMessage(0);<br>
wm_Command :<br>
Begin { a command was chosen from the popup menu }<br>
If (WParam = cm_Exit) Then <br>
PostMessage(Window,wm_Destroy,0,0)<br>
Else If (WParam = cm_About) Then<br>
MessageBox(0,'Shell Test Copyright ?'+ 'Jani J鋜vinen 1996.', 'About Shell
Test',mb_OK)<br>
Else
OpenDesktopIcon(WParam-cm_About);<br>
End;<br>
wm_MyCallback : Begin { our icon was clicked } <br>
If (LParam = wm_LButtonDown) Then <br>
ShowIconPopupMenu<br>
Else If (LParam = wm_RButtonDown) Then<br>
ShowAboutPopupMenu;<br>
End;<br>
Else<br>
Result := DefWindowProc(Window,Msg,WParam,LParam);<br>
End;<br>
End; <br>
<br>
就象你看到的一样,当用户单击图标时,Windows提示我们。注意我们不使用通常使用的wm_LButtonDown
消息,而使用wm_MyCallback message,详细的消息信息存储在LParam参数中。
<br>
当用户单击鼠标右键,我们创建一个菜单在桌面上。 <br>
<br>
Type TIconData = Array[1..100] of String;<br>
Var IconData : TIconData;<br>
Procedure ShowIconPopupMenu;<br>
Var ShellFolder : IShellFolder;<br>
EnumIDList : IEnumIDList;<br>
Result : hResult;<br>
Dummy : ULong;<br>
ItemIDList : TItemIDList;<br>
Pntr : PItemIDList;<br>
StrRet : TStrRet;<br>
PopupMenu : hMenu;<br>
ItemID : Integer;<br>
Pos : TPoint;<br>
Procedure AddToMenu(Item : String);<br>
Var S : String;<br>
Begin<br>
IconData[ItemID-cm_About] := Item;<br>
S := ExtractFileName(Item);<br>
If (System.Pos('.',S) <> 0) Then
SetLength(S,System.Pos('.',S)-1);<br>
AppendMenu(PopupMenu,mf_Enabled Or mf_String,ItemID,PChar(S));<br>
Inc(ItemID);<br>
End;<br>
begin<br>
PopupMenu := CreatePopupMenu;<br>
ItemID := cm_About+1;<br>
SHGetDesktopFolder(ShellFolder);<br>
ShellFolder.EnumObjects(MainWindow,SHCONTF_NONFOLDERS,EnumIDList);<br>
Pntr := @ItemIDList;<br>
Result := EnumIDList.Next(1,Pntr,Dummy);<br>
While (Result = NoError) do <br>
Begin<br>
ShellFolder.GetDisplayNameOf(Pntr,SHGDN_FORPARSING,@StrRet);<br>
With StrRet do<br>
AddToMenu(String(CStr));<br>
Result := EnumIDList.Next(1,Pntr,Dummy);<br>
End;<br>
EnumIDList.Release;<br>
ShellFolder.Release;<br>
GetCursorPos(Pos); AppendMenu(PopupMenu,mf_Separator,0,'');<br>
AppendMenu(PopupMenu,mf_Enabled Or mf_String,cm_Exit,'E&xit'); <br>
SetForegroundWindow(MainWindow);<br>
TrackPopupMenu(PopupMenu,tpm_LeftAlign Or tpm_LeftButton,
Pos.X,Pos.Y,0,MainWindow,nil);<br>
DestroyMenu(PopupMenu);<br>
end; </span></p>
<p class="p2"> </p>
<p class="p2"><span>
上面的程序看起来有点复杂,你可以将它分成两个部分来看:创建和显示菜单。
</span></p>
<p class="p2"><span> 列举创建菜单是用Windows的外壳接口完成的。首先,我们使用SHGetDesktopForlder函数得到使用桌面的IShellFolder接口。使用这个接口,我们能得到另一个接口的实例:IEnumIDList。这个接口通常实现实际的列举工作。我们简单的重复调用这个函数直到错误值返回(例如:所有的菜单被列举)。当我们得到一个菜单,我们使用AddToMenu函数加它。
</span></p>
<p class="p2"><span>
当所有的菜单被列举和创建后,现在我们需要运行这个菜单。我们将找到的菜单保存到一个全局的List变量中,每一个菜单都拥有它的菜单号。这确保我们能得到它的索引。
<br>
<br>
OpenDesktopIcon(WParam-cm_About) </span></p>
<p class="p2"><span>当然,WParam中储存了用户单击鼠标的菜单的菜单号(ID)。
</span></p>
<p class="p2"><span> 下面我们将处理运行用户选择的菜单。
</span></p>
<p class="p2"><span>Procedure OpenDesktopIcon(Number : Integer);<br>
Var S : String;<br>
I : Integer;<br>
begin<br>
S := IconData[Number];<br>
I := ShellExecute(0,nil,PChar(S),nil,nil,sw_ShowNormal);<br>
If (I < 32) Then<br>
Begin<br>
S := 'Could not open selected item "'+S+'". '+
'Result was: '+IntToStr(I)+'.';<br>
MessageBox(0,PChar(S),'Shell Test',mb_OK);<br>
End;<br>
end; <br>
<br>
上面,Win 32 API函数ShellExecute做了所有的工作。 </span></p>
<p class="p2"><span> 现在你应该能用Delphi创建简单的任务栏的程序了。
<br>
<br>
实际上,有一些免费的元件可以供您直接使用,不过,因为使用VCL,文件的大小将比较大,如果使用上面的方法,文件的大小将只要20K。当然,现在文件的大小已经不是我们该十分关注的问题了</span></p>
<hr color="#EE9B73" size="1" width="94%">
</TD>
</TR>
</table>
</BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -