如何将程序最小化时,加到任务栏里?(50分)

  • 主题发起人 主题发起人 UKing
  • 开始时间 开始时间
U

UKing

Unregistered / Unconfirmed
GUEST, unregistred user!
如题,当然最好是简单一点的办法,要有源程序的哟!
 

  在Shell32.DLL动态链接库中包括一个函数Shell_NotifyIconA()可通知Windows在任务条右下角加入一个小图标,可惜该函数的详细说明未收入Delphi的帮助文档中,下面以一个简单的实例来说明如果使用该函数。
unit Unit1;
interface
{ 记住在uses部分中包括 ShellAPI}
uses
Windows, Messages, SysUtils, Classes,
Graphics, Controls, Forms, Dialogs,
ShellAPI, StdCtrls;
{自定义消息,当小图标捕捉到鼠标事件时Windows向回调函数发送此消息}
const MY_MESSAGE = WM_USER + 100;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject;
var Action: TCloseAction);
procedure FormPaint(Sender: TObject);
private
procedure OnIconNotify(var Message: TMessage);
message MY_MESSAGE;
public
{ Public declarations }
end;

var
Form1: TForm1;
implementation
{$R *.DFM}
{当小图标捕捉到鼠标事件时进入此过程}
procedure TForm1.OnIconNotify(var Message: TMessage);
const
Busy: Boolean = false;
begin

if not Busy then
begin

Busy := true;
if Message.LParam=WM_LBUTTONDOWN then

if Application.MessageBox('Are you sure',
'Exit', MB_YESNO)=IDYES then
Close;
Busy := false;
end;

end;

{当主Form建立时通知Windows加入小图标}
procedure TForm1.FormCreate(Sender: TObject);
var
nid: TNotifyIconData;
begin

nid.cbSize := sizeof(nid);
// nid变量的字节数
nid.Wnd := Handle;
// 主窗口句柄
nid.uID := -1;
// 内部标识,可设为任意数
nid.hIcon := Application.Icon.Handle;
// 要加入的图标句柄,可任意指定
nid.szTip := 'This is a test application';
// 提示字符串
nid.uCallbackMessage := MY_MESSAGE;
// 回调函数消息
nid.uFlags := NIF_ICON or NIF_TIP or NIF_MESSAGE;
// 指明哪些字段有效
if not Shell_NotifyIcon(NIM_ADD, @nid) then
begin

ShowMessage('Failed!');
Application.Terminate;
end;

{将程序的窗口样式设为TOOL窗口,可避免在任务条上出现}
SetWindowLong(Application.Handle, GWL_EXSTYLE, WS_EX_TOOLWINDOW);
end;

{程序被关闭时通知Windows去掉小图标}
procedure TForm1.FormClose(Sender: TObject;
var Action: TCloseAction);
var
nid: TNotifyIconData;
begin

nid.cbSize := sizeof(nid);
// nid变量的字节数
nid.uID := -1;
//内部标识,与加入小图标时的数一致
nid.Wnd := Handle;
//主窗口句柄
Shell_NotifyIcon(NIM_DELETE, @nid);
//去掉小图标
end;

{主窗口初始化完毕并显示时将激活Paint重画事件,此时将主窗口隐藏}
procedure TForm1.FormPaint(Sender: TObject);
begin

Hide;
end;

end.

 
  上例中将程序的图标放在任务条右下角,然后隐藏自身,当用户移动鼠标至该图标上时会看到提示字符串,如果单击该图标会出现一个对话框,选择Yes退出程序并清除小图标。
 
怎样建立简单的任务栏应用程序:

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 WCdo
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 IconDatado
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 StrRetdo
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&amp;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;
上面,Win 32 API函数ShellExecute做了所有的工作。
现在你应该能用Delphi创建简单的任务栏的程序了。

实际上,有一些免费的元件可以供您直接使用,不过,因为使用VCL,文件的大小将比较大,如果使用上面的方法,文件的大小将只要20K。当然,现在文件的大小已经不是我们该十分关注的问题了。
 
这个问题以前讨论过很多次了,自己去查一查吧(有必要贴这么多吗,很简单的一个函
数嘛)
 
要不要我给你个例程
 
最简单的办法,用控件——Rxlib2.75中就有
 
我有这样的控件,要不要?
 
大家一见到有分都冲进来了了。xixi,在d4从入门到精通上有个例子的,可以找来看看。反正
这书也不错,如果能买到的话就买一本来看看吧。
 
有一个函数。不过我忘了。
 
多人接受答案了。
 
后退
顶部