精华区 [关闭][返回]

当前位置:网易精华区>>讨论区精华>>编程开发>>● Delphi>>Windows API函数>>任务栏>>Re: 最小化

主题:Re: 最小化
发信人: dillon()
整理人: kingron(2000-12-05 19:17:48), 站内信件
【 在 lit_mer (久久) 的大作中提到: 】
: 请教高手:
:     如何实现将窗口最小化时置于Windows任务栏发射架中?
 
从技术方面来说,一个任务栏应用程序非常象普通的应用程序,它有一个消息循
环,相应Windows的消息来完成相应的功能。
Procedure RunTrayApplication;
Var Msg : TMsg;
Begin
  CreateWindow;
  AddTrayIcon;
  While GetMessage(Msg,0,0,0) do Begin
    TranslateMessage(Msg);
    DispatchMessage(Msg);
  End;
  DeleteTrayIcon;
End;
你能看到:所有需要做的工作是创建一个窗口,注册一个图标到任务栏,设置它
的消息循环,最后关闭它。当然,必须还有增加其他代码完成相应的功能,但是
,它是真的不需要担心。
    让我们从窗口的创建开始。实际上,这个窗口是不是能在任务栏上能见到的
窗口。相应的,这个窗口只是处理消息循环、其它父类的工作。任务窗口(Windo
ws 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_OverlappedWin
dow”,但是这个尺寸是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_Ad
d程序。
    现行我们已经加了我们的图标到任务栏,下面需要决定如何处理消息。
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的外壳接口完成的。首先,我们使用SHGetDesktopFor
lder函数得到使用桌面的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创建简单的任务栏的程序了。


--
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.104.23.10]

[关闭][返回]