查看完整版本: 详解VB托盘知识

王懿 2008-5-23 13:21

详解VB托盘知识

[font=宋体][size=10.5pt]  很多软件运行时会在系统托盘区[/size][/font][font=&quot][size=10.5pt]([/size][/font][font=宋体][size=10.5pt]就是桌面右下角显示时间的区域[/size][/font][font=&quot][size=10.5pt])[/size][/font][font=宋体][size=10.5pt]出现一个小图标,它作为程序运行的一个标志,我们可以通过使用小图标所弹出的菜单来控制应[/size][/font]
[font=宋体][size=10.5pt]用程序的状态。本例就给出了一个功能比较完整的托盘程序,我们可以看到怎样用[/size][/font][font=&quot][size=10.5pt]API[/size][/font][font=宋体][size=10.5pt]函数[/size][/font][font=&quot][size=10.5pt]Shell_NotifyIcon[/size][/font][font=宋体][size=10.5pt]来添加、删除、更改托盘图标;而[/size][/font]
[font=宋体][size=10.5pt]且例中还演示了为托盘图标添加右键菜单和浮动提示的方法。[/size][/font]
[font=宋体][size=10.5pt]  程序[/size][/font][font=&quot][size=10.5pt]([/size][/font][font=宋体][size=10.5pt]附后[/size][/font][font=&quot][size=10.5pt])[/size][/font][font=宋体][size=10.5pt]用到了[/size][/font][font=&quot][size=10.5pt]Shell_NotifyIcon[/size][/font][font=宋体][size=10.5pt]、[/size][/font][font=&quot][size=10.5pt] SendMessage[/size][/font][font=宋体][size=10.5pt]、[/size][/font][font=&quot][size=10.5pt]CallWindowProc[/size][/font][font=宋体][size=10.5pt]、[/size][/font][font=&quot][size=10.5pt]SetWindowLong[/size][/font][font=宋体][size=10.5pt]等[/size][/font][font=&quot][size=10.5pt]API[/size][/font][font=宋体][size=10.5pt]函数,其中[/size][/font][font=&quot][size=10.5pt]Shell_NotifyIcon[/size][/font][font=宋体][size=10.5pt]是主要的函数,[/size][/font]
[font=宋体][size=10.5pt]它用来添加、删除、更改系统托盘区[/size][/font][font=&quot][size=10.5pt](taskbar status area)[/size][/font][font=宋体][size=10.5pt]的图标,所以我们先来看看这个函数的声明和参数:
  [/size][/font][font=宋体][size=10.5pt]使用[/size][/font][font=&quot][size=10.5pt]API[/size][/font][font=宋体][size=10.5pt]函数之前必须先在程序中声明如下:
  [/size][/font][font=&quot][size=10.5pt]Declare Function Shell_NotifyIcon Lib "shell32.dll" Alias"Shell_NotifyIconA" (ByVal dwMessage As Long, lpData AsNOTIFYICONDATA) As Long
  [/size][/font][font=宋体][size=10.5pt]其中各参数的意义如下表[/size][/font][font=&quot][size=10.5pt]:
  [/size][/font][align=center][table=98%] [tr]  [td=1,1,155]  [font=宋体]参数:[/font][font=宋体][size=12pt][/size][/font]
  [/td]  [td]  [font=宋体]意义[/font][font=宋体][size=12pt][/size][/font]
  [/td] [/tr] [tr]  [td=1,1,155]  dwMessage[font=宋体][size=12pt][/size][/font]
  [/td]  [td]  [font=宋体]为消息设置值,它可以是以下的几个常数值:[/font]0[font=宋体]、[/font]1[font=宋体]、[/font]2[font=宋体][size=12pt][/size][/font]
  [/td] [/tr] [tr]  [td=1,1,155]  NIM_ADD = 0
[font=宋体][size=12pt][/size][/font]
  [/td]  [td]  [font=宋体]加入图标到系统状态栏中[/font][font=宋体][size=12pt][/size][/font]
  [/td] [/tr] [tr]  [td=1,1,155]  NIM_MODIFY = 1 [font=宋体][size=12pt][/size][/font]
  [/td]  [td]  [font=宋体]修改系统状态栏中的图标[/font][font=宋体][size=12pt][/size][/font]
  [/td] [/tr] [tr]  [td=1,1,155]  NIM_DELETE = 2 [font=宋体][size=12pt][/size][/font]
  [/td]  [td]  [font=宋体]删除系统状态栏中的图标[/font][font=宋体][size=12pt][/size][/font]
  [/td] [/tr][/table][/align]  [font=&quot][size=10.5pt]LpData [/size][/font][font=宋体][size=10.5pt]用以传入[/size][/font][font=&quot][size=10.5pt]NOTIFYICONDATA[/size][/font][font=宋体][size=10.5pt]数据结构变量,其结构如下所示:
  [/size][/font][align=center][table=98%,rgb(235, 233, 235)] [tr]  [td]  Type NOTIFYICONDATA
  
  
cbSize As  Long [font=宋体]       需填入[/font]NOTIFYICONDATA[font=宋体]数据结构的长度[/font]

HWnd As  Long [font=宋体]        设置成窗口的句柄[/font]

Uid As  Long[font=宋体]         为图标所设置的[/font]ID[font=宋体]值[/font]

UFlags As  Long [font=宋体]       设置[/font]uCallbackMessage,hIcon,szTip[font=宋体]是否有效[/font]

UCallbackMessage  As Long
[font=宋体]消息编号[/font]

HIcon As  Long
[font=宋体]显示在状态栏上的图标[/font]

SzTip As  String * 64
[font=宋体]提示信息[/font]
  End Type[font=宋体][size=12pt][/size][/font]
  [/td] [/tr][/table][/align]  [font=宋体]返回值[/font] Long[font=宋体],非零表示成功,零表示失败[/font]

[font=宋体]  在使用这个[/font]API[font=宋体]函数之前我们应该先定义结构类型[/font]NOTIFYICONDATA[font=宋体]:[/font]
[align=center][table=98%,rgb(235, 233, 235)] [tr]  [td]  Public Type NOTIFYICONDATA
  
cbSize  As Long HWnd As Long
  
Uid As  Long UFlags As Long
  
UCallbackMessage  As Long
  
HIcon  As Long
  
SzTip  As String * 64
  
End Type [font=宋体][size=12pt][/size][/font]
  [/td] [/tr][/table][align=left][font=宋体][size=10.5pt]  然后定义一个[/size][/font][font=&quot][size=10.5pt]NOTIFYICONDATA[/size][/font][font=宋体][size=10.5pt]的变量[/size][/font][font=&quot][size=10.5pt]TheData[/size][/font][font=宋体][size=10.5pt]来记录设置托盘图标的数据
  [/size][/font][font=&quot][size=10.5pt]Private TheData As NOTIFYICONDATA
  [/size][/font][font=宋体][size=10.5pt]这时我们就可以使用这个函数来设置系统托盘图标了,具体方法如下:
  [/size][/font][font=&quot][size=10.5pt]1[/size][/font][font=宋体][size=10.5pt]、添加图标
  [/size][/font][align=center][table=98%,rgb(235, 233, 235)] [tr]  [td]  With TheData
  
.Uid = 0
  
.HWnd =  frm.HWnd
'frm.HWnd[font=宋体]是程序主窗体的句柄[/font]

.cbSize  = Len(TheData)
  
.HIcon =  frm.Icon.Handle
'frm.Icon.Handle[font=宋体]指向主窗体的图标[/font]

.UFlags  = NIF_ICON
  
.UCallbackMessage  = TRAY_CALLBACK
  
'[font=宋体]作用是允许返回消息,在下一节中会有详细解释。[/font]

.UFlags  = .UFlags Or NIF_MESSAGE
  
.cbSize  = Len(TheData)
  
End With
  
Shell_NotifyIcon  NIM_ADD, TheData


'[font=宋体]根据前面定义[/font]NIM_ADD[font=宋体],设置为[/font]“[font=宋体]添加模式[/font]”[font=宋体],然后添加[/font]

  [/td] [/tr][/table][align=left]  [font=&quot][size=10.5pt]2[/size][/font][font=宋体][size=10.5pt]、删去图标
  [/size][/font][align=center][table=98%,rgb(235, 233, 235)] [tr]  [td]  With TheData
  
.UFlags  = 0
  End With
  Shell_NotifyIcon NIM_DELETE, TheData

  '[font=宋体]根据前面定义[/font]NIM_DELETE[font=宋体],设置为[/font]“[font=宋体]删除模式[/font]”[font=宋体][size=12pt][/size][/font]
  [/td] [/tr][/table][/align]  [font=&quot][size=10.5pt]3[/size][/font][font=宋体][size=10.5pt]、更改图标
  [/size][/font][align=center][table=98%,rgb(235, 233, 235)] [tr]  [td]  With TheData
  
.HIcon =  pic.Handle


'pic[font=宋体]是图片狂[/font]PictureBox[font=宋体],存放图标文件[/font]

.UFlags =  NIF_ICON
  End With
  Shell_NotifyIcon NIM_MODIFY, TheData

  '[font=宋体]根据前面定义[/font]NIM_MODIFY[font=宋体],设置为[/font]“[font=宋体]更改模式[/font]”[font=宋体][size=12pt][/size][/font]
  [/td] [/tr][/table][/align]  [font=&quot][size=10.5pt]4[/size][/font][font=宋体][size=10.5pt]、为图标添加浮动提示信息
  [/size][/font][align=center][table=98%,rgb(235, 233, 235)] [tr]  [td]  With TheData
  
.SzTip =  tip & vbNullChar


'tip[font=宋体]是字符串[/font]string[font=宋体],存储提示信息[/font]

.UFlags  = NIF_TIP


'[font=宋体]指明要对浮动提示进行设置[/font]
  End With
  Shell_NotifyIcon NIM_MODIFY, TheData

  '[font=宋体]根据前面定义[/font]NIM_MODIFY[font=宋体],设置为[/font]“[font=宋体]修改模式[/font]” [font=宋体][size=12pt][/size][/font]
  [/td] [/tr][/table][/align]  [font=宋体][size=10.5pt]通过以上几段代码我们就能根据自己需要添加、删除、更改系统托盘图标,并能添加系统图标上的浮动提示信息。但这时的托盘图标是孤立的,我们并不能利用它来控制应用程序的行为,怎么办呢?别急,请往下看[/size][/font][font=&quot][size=10.5pt]……
[/size][/font]





[/align]
[/align][/align]
[/align]

王懿 2008-5-23 13:25

详解VB托盘知识

[font=宋体][size=10.5pt]  如果你下载[/size][/font][font=&quot][size=10.5pt]([/size][/font][font=宋体][size=10.5pt]源程序下载[/size][/font][font=&quot][size=10.5pt])[/size][/font][font=宋体][size=10.5pt]并运行这个例程序,你会发现如果我们在托盘图标上点击鼠标右键,则会弹出一个右键菜单。如果点击相应的菜单项,程序主窗体会随之[/size][/font]
[font=宋体][size=10.5pt]变化,这样就可以控制程序的行为。而如果当主窗体处于最小化状态时,我们在托盘图标上点击左键,窗体会恢复到原来的大小。其实实现上述的功能都要依赖于[/size][/font][font=&quot][size=10.5pt] WINDOWS[/size][/font][font=宋体][size=10.5pt]操作系统的消息机制,要完全弄懂这个机制挺不容易的,但是我们可以按下述文字来理解它。
  [/size][/font][font=宋体][size=10.5pt]把[/size][/font][font=&quot][size=10.5pt]WINDOWS[/size][/font][font=宋体][size=10.5pt]操作系统看作[/size][/font]
[font=宋体][size=10.5pt]人的大脑,它接收、处理、并发送各种各样的信息给我们的各个器官[/size][/font][font=&quot][size=10.5pt]([/size][/font][font=宋体][size=10.5pt]当然是比喻各个应用程序了[/size][/font][font=&quot][size=10.5pt])[/size][/font][font=宋体][size=10.5pt],也就是说它是消息的中枢。而每个应用程序[/size][/font][font=&quot][size=10.5pt]([/size][/font][font=宋体][size=10.5pt]甚至每一个按[/size][/font]
[font=宋体][size=10.5pt]钮、标签、窗体等等统称为窗口[/size][/font][font=&quot][size=10.5pt])[/size][/font][font=宋体][size=10.5pt]在运行时都会被分配一个窗口过程[/size][/font][font=&quot][size=10.5pt]WINDOWPROC[/size][/font][font=宋体][size=10.5pt],由这个窗口过程来接收和处理操作系统发来的消息[/size][/font][font=&quot][size=10.5pt]([/size][/font][font=宋体][size=10.5pt]实际上存在一个消[/size][/font]
[font=宋体][size=10.5pt]息队列[/size][/font][font=&quot][size=10.5pt])[/size][/font][font=宋体][size=10.5pt],通常情况下这个窗口过程是由操作系统指定的,它会自动的响应并处理一些[/size][/font][font=&quot][size=10.5pt]WINDOWS[/size][/font][font=宋体][size=10.5pt]消息[/size][/font][font=&quot][size=10.5pt]([/size][/font][font=宋体][size=10.5pt]如窗体移动、最大化、最小化、错误信息等[/size][/font][font=&quot][size=10.5pt])[/size][/font][font=宋体][size=10.5pt]。好,到[/size][/font]
[font=宋体][size=10.5pt]这我们先停一下,提出一个疑问,这些消息能否由我们自己写程序来处理呢?答案是肯定的,不过还得借助[/size][/font][font=&quot][size=10.5pt]API[/size][/font][font=宋体][size=10.5pt]函数的威力了,怎么用?我们还是先看看这些[/size][/font][font=&quot][size=10.5pt] API[/size][/font][font=宋体][size=10.5pt]函数的定义和参数吧。
  [/size][/font][font=宋体][size=10.5pt]程序中用到了[/size][/font][font=&quot][size=10.5pt]SendMessage[/size][/font][font=宋体][size=10.5pt]、[/size][/font][font=&quot][size=10.5pt]CallWindowProc[/size][/font][font=宋体][size=10.5pt]、[/size][/font][font=&quot][size=10.5pt]SetWindowLong[/size][/font][font=宋体][size=10.5pt]等[/size][/font][font=&quot][size=10.5pt] API[/size][/font][font=宋体][size=10.5pt]函数,其中[/size][/font][font=&quot][size=10.5pt]SendMessage[/size][/font][font=宋体][size=10.5pt]函数的作用是将一条消息发给某个窗口;[/size][/font][font=&quot][size=10.5pt]CallWindowProc[/size][/font][font=宋体][size=10.5pt]函数用来发送消息到一个窗口过程;而使用[/size][/font][font=&quot][size=10.5pt] SetWindowLong[/size][/font][font=宋体][size=10.5pt]函数来为窗口结构中为指定的窗口设置属性。使用[/size][/font][font=&quot][size=10.5pt]API[/size][/font][font=宋体][size=10.5pt]函数之前必须先在程序中声明如下:
  [/size][/font][align=center][table=98%,rgb(235, 233, 235)] [tr]  [td]  
Declare  Function CallWindowProc Lib "user32" Alias  "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal HWnd As Long,  ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
  
  
Declare  Function SetWindowLong Lib "user32" Alias  "SetWindowLongA" (ByVal HWnd As Long, ByVal nIndex As Long, ByVal  dwNewLong As Long) As Long
  
  
Private  Declare Function SendMessage Lib "user32" Alias  "SendMessageA" (ByVal HWnd As Long, ByVal wMsg As Long, ByVal  wParam As Long, lParam As Any) As Long [font=宋体][size=12pt][/size][/font]
  [/td] [/tr][/table][/align]  [font=宋体][size=10.5pt]其中各参数的意义如下表[/size][/font][font=&quot][size=10.5pt]:
  [/size][/font][font=&quot][size=10.5pt]CallWindowProc[/size][/font][font=宋体][size=10.5pt]函数:
  [/size][/font][align=center][table=98%] [tr]  [td]  [font=宋体]参数[/font][font=宋体][size=12pt][/size][/font]
  [/td]  [td]  [font=宋体]意义[/font][font=宋体][size=12pt][/size][/font]
  [/td] [/tr] [tr]  [td]  lpPrevWndFunc [font=宋体][size=12pt][/size][/font]
  [/td]  [td]  Long[font=宋体],原来的窗口过程地址[/font][font=宋体][size=12pt][/size][/font]
  [/td] [/tr] [tr]  [td]  HWnd[font=宋体][size=12pt][/size][/font]
  [/td]  [td]  Long[font=宋体],窗口句柄[/font][font=宋体][size=12pt][/size][/font]
  [/td] [/tr] [tr]  [td]  Msg[font=宋体][size=12pt][/size][/font]
  [/td]  [td]  Long[font=宋体],发送的消息[/font][font=宋体][size=12pt][/size][/font]
  [/td] [/tr] [tr]  [td]  wParam[font=宋体][size=12pt][/size][/font]
  [/td]  [td]  Long[font=宋体],消息类型,参考[/font]wParam[font=宋体]参数表[/font] [font=宋体][size=12pt][/size][/font]
  [/td] [/tr] [tr]  [td]  lParam[font=宋体][size=12pt][/size][/font]
  [/td]  [td]  Long[font=宋体],依据[/font]wParam[font=宋体]参数的不同而不同[/font] [font=宋体][size=12pt][/size][/font]
  [/td] [/tr][/table][/align]  [font=宋体][size=10.5pt]返回值[/size][/font][font=&quot][size=10.5pt] Long[/size][/font][font=宋体][size=10.5pt],依据发送的消息不同而变化

  [/size][/font][font=&quot][size=10.5pt]SetWindowLong[/size][/font][font=宋体][size=10.5pt]函数[/size][/font]
[font=宋体][size=10.5pt]:
  [/size][/font][align=center][table=98%] [tr]  [td]  [font=宋体]参数[/font][font=宋体][size=12pt][/size][/font]
  [/td]  [td]  [font=宋体]意义[/font][font=宋体][size=12pt][/size][/font]
  [/td] [/tr] [tr]  [td]  hwnd [font=宋体][size=12pt][/size][/font]
  [/td]  [td]  Long[font=宋体],欲为其取得信息的窗口的句柄[/font][font=宋体][size=12pt][/size][/font]
  [/td] [/tr] [tr]  [td]  nIndex[font=宋体][size=12pt][/size][/font]
  [/td]  [td]  Long[font=宋体],请参考[/font]GetWindowLong[font=宋体]函数的[/font]nIndex[font=宋体]参数的说明[/font][font=宋体][size=12pt][/size][/font]
  [/td] [/tr] [tr]  [td]  dwNewLong[font=宋体][size=12pt][/size][/font]
  [/td]  [td]  Long[font=宋体],由[/font]nIndex[font=宋体]指定的窗口信息的新值[/font] [font=宋体][size=12pt][/size][/font]
  [/td] [/tr][/table][/align]  [font=宋体][size=10.5pt]返回值[/size][/font][font=&quot][size=10.5pt] Long[/size][/font][font=宋体][size=10.5pt],指定数据的前一个值

  [/size][/font][font=&quot][size=10.5pt]SendMessage[/size][/font][font=宋体][size=10.5pt]函数[/size][/font]
[font=宋体][size=10.5pt]:
  [/size][/font][align=center][table=98%] [tr]  [td]  [font=宋体]参数[/font][font=宋体][size=12pt][/size][/font]
  [/td]  [td]  [font=宋体]意义[/font][font=宋体][size=12pt][/size][/font]
  [/td] [/tr] [tr]  [td]  hwnd [font=宋体][size=12pt][/size][/font]
  [/td]  [td]  Long[font=宋体],要接收消息的那个窗口的句柄[/font][font=宋体][size=12pt][/size][/font]
  [/td] [/tr] [tr]  [td]  wMsg[font=宋体][size=12pt][/size][/font]
  [/td]  [td]  Long[font=宋体],消息的标识符[/font][font=宋体][size=12pt][/size][/font]
  [/td] [/tr] [tr]  [td]  wParam[font=宋体][size=12pt][/size][/font]
  [/td]  [td]  Long[font=宋体],具体取决于消息[/font][font=宋体][size=12pt][/size][/font]
  [/td] [/tr] [tr]  [td]  lParam[font=宋体][size=12pt][/size][/font]
  [/td]  [td]  Any[font=宋体],具体取决于消息[/font]  [font=宋体][size=12pt][/size][/font]
  [/td] [/tr][/table][/align]  [font=宋体][size=10.5pt]返回值[/size][/font][font=&quot][size=10.5pt] Long[/size][/font][font=宋体][size=10.5pt],由具体的消息决定

  [/size][/font][font=宋体][size=10.5pt]我们要自己写程序来处理消息,必须先更改窗口的属性,从原来由默认的窗口过程来处理消息变成由我们自己写的消息处理过程来处理消息。方法是使用[/size][/font][font=&quot][size=10.5pt]SetWindowLong[/size][/font][font=宋体][size=10.5pt]函数来取得默认窗口过程的地址,然后转向为我们自己写的窗口过程的地址,具体的实现方法如下代码:
  [/size][/font][align=center][table=98%,rgb(235, 233, 235)] [tr]  [td]  'GWL_WNDPROC[font=宋体]获得该窗口的窗口过程的地址,[/font]AddressOf[font=宋体]是取址函数,[/font]NewWindowProc[font=宋体]是我们写的过程[/font]
  OldWindowProc = SetWindowLong(frm.HWnd, GWL_WNDPROC, AddressOf
  
NewWindowProc)[font=宋体][size=12pt][/size][/font]
  [/td] [/tr][/table][/align]  [font=宋体]  然后在[/font]NewWindowProc[font=宋体]函数中写入如下代码,需要注意的是下面代码中红色的[/font]TRAY_CALLBACK[font=宋体]是由托盘区图标传来的消息,要让托盘图标传回消息,必须在添加托盘图标时指定:[/font]


[align=center][table=98%,rgb(235, 233, 235)] [tr]  [td]  
Public  Function NewWindowProc(ByVal HWnd As Long, ByVal Msg As Long, ByVal wParam As  Long, ByVal lParam As Long) As Long
  
'[font=宋体]如果用户点击了托盘中的图标,则进行判断是点击了左键还是右键[/font]

If Msg =  TRAY_CALLBACK Then
  
'[font=宋体]如果点击了左键[/font]

If  lParam = WM_LBUTTONUP Then
  
'[font=宋体]而这时窗体的状态是最小化时[/font]

If  TheForm.WindowState = vbMinimized Then _
  
'[font=宋体]恢复到最小化前的窗体状态[/font]

TheForm.WindowState  = TheForm.LastState
  
TheForm.SetFocus
  
Exit  Function
  
End  If
  
End If
  
'[font=宋体]如果点击了右键[/font]

If  lParam = WM_RBUTTONUP Then
  
'[font=宋体]则弹出右键菜单[/font]

TheForm.PopupMenu  TheMenu
  
Exit  Function
  
End If
  
End If
  
'[font=宋体]如果是其他类型的消息则传递给原有默认的窗口函数[/font]

NewWindowProc  = CallWindowProc(OldWindowProc, HWnd, Msg, wParam, lParam)
  
End  Function [font=宋体][size=12pt][/size][/font]
  [/td] [/tr][/table][/align]  [font=宋体]  这样我们就取得并处理了来自托盘图标的消息,现在的问题是在鼠标右键菜单弹出后,怎么控制程序主窗体的状态,这时我们需要用到[/font]SendMessage[font=宋体]函[/font] [font=宋体]数来向主窗体发送最大化、最小化、关闭、移动等消息,具体的代码实现如下,其中[/font]HWnd[font=宋体]是主窗体的句柄,[/font]WM_SYSCOMMAND[font=宋体]表示发送的是系统控制[/font] [font=宋体]类的消息,[/font]SC_MOVE[font=宋体]、[/font]SC_SIZE[font=宋体]、[/font]SC_RESTORE[font=宋体]便是要发送的消息了:[/font]
  [align=center][table=98%,rgb(235, 233, 235)] [tr]  [td]  
'[font=宋体]托盘图标右键菜单上的[/font]“[font=宋体]移动[/font]”[font=宋体]项被点击时[/font]

Private  Sub mnuTrayMove_Click()
  
SendMessage  HWnd, WM_SYSCOMMAND, SC_MOVE, 0&
  
End Sub
  
'[font=宋体]托盘图标右键菜单上的[/font]“[font=宋体]恢复[/font]”[font=宋体]项被点击时[/font]

Private  Sub mnuTrayRestore_Click()
  
SendMessage  HWnd, WM_SYSCOMMAND, SC_RESTORE, 0&
  
End Sub
  
'[font=宋体]托盘图标右键菜单上的[/font]“[font=宋体]退出[/font]”[font=宋体]项被点击时[/font]

Private  Sub mnuTraySize_Click()
  
SendMessage  HWnd, WM_SYSCOMMAND, SC_SIZE, 0&
  
End Sub [font=宋体][size=12pt][/size][/font]
  [/td] [/tr][/table][/align]  [font=宋体][size=10.5pt]最后要提醒你,在程序退出时一定要把窗口过程的地址恢复为默认值,同时把托盘图标移去哦。[/size][/font]
[font=宋体][size=10.5pt]为了学习方便,以下提供了源代码:
  [/size][/font][align=center][table=98%,rgb(235, 233, 235)] [tr]  [td]  '---------------------------------------------
  ' [font=宋体]使用系统托盘程序演示[/font]
  '---------------------------------------------
  '[font=宋体]程序说明:[/font]
  ' [font=宋体]这是一个比较完整的使用系统托盘的程序实例,包括[/font]
  '[font=宋体]了:添加托盘图标,删除托盘图标,动态改变托盘图标,[/font]
  '[font=宋体]为托盘图标添加浮动提示信息,实现托盘图标的鼠标右键[/font]
  '[font=宋体]菜单等内容。[/font]
  '-------[font=宋体]名称[/font]-------------------[font=宋体]作用[/font]------------
  ' Form1 [font=宋体]主窗体[/font]
  ' mnuFile,mnuFileExit [font=宋体]文件菜单,菜单项[/font]
  ' mnuTray,mnuTrayClose... [font=宋体]托盘区右键菜单,菜单项[/font]
  '---------------------------------------------
  
  Option Explicit
  
  'LastState[font=宋体]变量的作用是标示主窗体原有状态[/font]
  Public LastState As Integer
  
  '[font=宋体]【[/font]VB[font=宋体]声明】[/font]
  ' Private Declare Function SendMessage Lib "user32" Alias  "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal  wParam As Long, lParam As Any) As Long
  
  '[font=宋体]【说明】[/font]
  ' [font=宋体]调用一个窗口的窗口函数,将一条消息发给那个窗口。除非消息处理完毕,否则该函数不会返回。[/font]SendMessageBynum[font=宋体],[/font]
  ' SendMessageByString[font=宋体]是该函数的[/font]“[font=宋体]类型安全[/font]”[font=宋体]声明形式[/font]
  
  '[font=宋体]【返回值】[/font]
  ' Long[font=宋体],由具体的消息决定[/font]
  
  '[font=宋体]【参数表】[/font]
  ' hwnd ----------- Long[font=宋体],要接收消息的那个窗口的句柄[/font]
  
  ' wMsg ----------- Long[font=宋体],消息的标识符[/font]
  
  ' wParam --------- Long[font=宋体],具体取决于消息[/font]
  
  ' lParam --------- Any[font=宋体],具体取决于消息[/font]
  Private Declare Function SendMessage Lib "user32" Alias  "SendMessageA" (ByVal HWnd As Long, ByVal wMsg As Long, ByVal  wParam As Long, lParam As Any) As Long
  
  '[font=宋体]表示发送的是系统命令[/font]
  Private Const WM_SYSCOMMAND = &H112
  Private Const SC_MOVE = &HF010&
  Private Const SC_RESTORE = &HF120&
  Private Const SC_SIZE = &HF000&
  
  '[font=宋体]当主窗体加载时[/font]
  Private Sub Form_Load()
  
  '[font=宋体]窗体的[/font]WindowState[font=宋体]属性,返回或设置一个值,该值用来指定在运行时窗体窗口的可视状态[/font]
  'vbNormal 0 [font=宋体](缺省值)正常[/font] [font=宋体]。[/font]
  'VbMinimized 1 [font=宋体]最小化(最小化为一个图标)[/font]
  'VbMaximized 2 [font=宋体]最大化(扩大到最大尺寸)[/font]
  If WindowState = vbMinimized Then
  LastState = vbNormal
  Else
  LastState = WindowState
  End If
  
  '[font=宋体]将图标添加到托盘的函数,参见模块中的解释[/font]
  '[font=宋体]注意了这是从主程序到模块的入口,本例中并没有直接调用[/font]Shell_NotifyIcon[font=宋体]函数[/font]
  AddToTray Me, mnuTray
  
  SetTrayTip "[font=宋体]托盘图标演示,点击右键弹出菜单[/font]"
  End Sub
  
  '[font=宋体]在主窗体[/font]Form1[font=宋体]大小改变时,相应改变右键菜单[/font]mnuTray[font=宋体]的菜单项的可用属性[/font]Enabled
  Private Sub Form_Resize()
  Select Case WindowState
  
  '[font=宋体]如果窗体最小化了,把菜单项[/font]“[font=宋体]最大化[/font]”“[font=宋体]恢复[/font]”[font=宋体]设为可用,[/font]
  '[font=宋体]而把[/font]“[font=宋体]最小化[/font]”“[font=宋体]移动[/font]”“[font=宋体]大小[/font]”[font=宋体]三项设为不可用[/font].
  '[font=宋体]如果这时在托盘图标上点击鼠标右键,会发现不可用项变为灰色[/font]
  Case vbMinimized
  mnuTrayMaximize.Enabled = True
  mnuTrayMinimize.Enabled = False
  mnuTrayMove.Enabled = False
  mnuTrayRestore.Enabled = True
  mnuTraySize.Enabled = False
  
  '[font=宋体]窗体最大化时[/font]
  Case vbMaximized
  mnuTrayMaximize.Enabled = False
  mnuTrayMinimize.Enabled = True
  mnuTrayMove.Enabled = False
  mnuTrayRestore.Enabled = True
  mnuTraySize.Enabled = False
  
  '[font=宋体]一般状态下[/font]
  Case vbNormal
  mnuTrayMaximize.Enabled = True
  mnuTrayMinimize.Enabled = True
  mnuTrayMove.Enabled = True
  mnuTrayRestore.Enabled = False
  mnuTraySize.Enabled = True
  End Select
  
  If WindowState <> vbMinimized Then LastState = WindowState
  End Sub
  
  '[font=宋体]保证在程序退出时删除托盘图标[/font]
  Private Sub Form_Unload(Cancel As Integer)
  RemoveFromTray
  End Sub
  
  '“[font=宋体]文件[/font]”[font=宋体]菜单的[/font]“[font=宋体]退出[/font]”[font=宋体]项被点击时[/font]
  Private Sub mnuFileExit_Click()
  Unload Me
  End Sub
  
  '[font=宋体]托盘图标右键菜单上的[/font]“[font=宋体]退出[/font]”[font=宋体]项被点击时[/font]
  Private Sub mnuTrayClose_Click()
  Unload Me
  End Sub
  
  '[font=宋体]托盘图标右键菜单上的[/font]“[font=宋体]最大化[/font]”[font=宋体]项被点击时[/font]
  Private Sub mnuTrayMaximize_Click()
  WindowState = vbMaximized
  End Sub
  
  '[font=宋体]托盘图标右键菜单上的[/font]“[font=宋体]最小化[/font]”[font=宋体]项被点击时[/font]
  Private Sub mnuTrayMinimize_Click()
  WindowState = vbMinimized
  End Sub
  
  '[font=宋体]托盘图标右键菜单上的[/font]“[font=宋体]移动[/font]”[font=宋体]项被点击时[/font]
  Private Sub mnuTrayMove_Click()
  SendMessage HWnd, WM_SYSCOMMAND, _
  SC_MOVE, 0&
  End Sub
  
  '[font=宋体]托盘图标右键菜单上的[/font]“[font=宋体]恢复[/font]”[font=宋体]项被点击时[/font]
  Private Sub mnuTrayRestore_Click()
  SendMessage HWnd, WM_SYSCOMMAND, _
  SC_RESTORE, 0&
  End Sub
  
  '[font=宋体]托盘图标右键菜单上的[/font]“[font=宋体]退出[/font]”[font=宋体]项被点击时[/font]
  Private Sub mnuTraySize_Click()
  SendMessage HWnd, WM_SYSCOMMAND, _
  SC_SIZE, 0&
  End Sub
  '-----------------------------------------
  '[font=宋体]以下为模块中的代码:[/font]
  '-----------------------------------------
  Option Explicit
  
  Public OldWindowProc As Long
  Public TheForm As Form
  Public TheMenu As Menu
  '[b][font=宋体]【[/font]VB[/b][b][font=宋体]声明】[/font][/b]
  'Declare Function CallWindowProc Lib "user32" Alias  "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal HWnd As Long,  ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
  
  '[font=宋体]【说明】[/font]
  ' [font=宋体]此函数发送消息到一个窗口过程[/font]
  
  '[b][font=宋体]【返回值】[/font][/b]
  ' Long[font=宋体],依据发送的消息不同而变化[/font]
  
  '[b][font=宋体]【参数表】[/font][/b]
  ' lpPrevWndFunc----- Long[font=宋体],原来的窗口过程地址[/font]
  
  ' HWnd-------------- Long[font=宋体],窗口句柄[/font]
  
  ' Msg -------------- Long[font=宋体],发送的消息[/font]
  
  ' wParam ----------- Long[font=宋体],消息类型,参考[/font]wParam[font=宋体]参数表[/font]
  
  ' lParam ----------- Long[font=宋体],依据[/font]wParam[font=宋体]参数的不同而不同[/font]
  
  Declare Function CallWindowProc Lib "user32" Alias  "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal HWnd As Long,  ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
  
  '[b][font=宋体]【[/font]VB[/b][b][font=宋体]声明】[/font][/b]
  ' Private Declare Function SetWindowLong Lib "user32" Alias  "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal  dwNewLong As Long) As Long
  
  '[b][font=宋体]【说明】[/font][/b]
  ' [font=宋体]在窗口结构中为指定的窗口设置信息[/font]
  
  '[b][font=宋体]【返回值】[/font][/b]
  ' Long[font=宋体],指定数据的前一个值[/font]
  
  '[b][font=宋体]【参数表】[/font][/b]
  ' hwnd ----------- Long[font=宋体],欲为其取得信息的窗口的句柄[/font]
  
  ' nIndex --------- Long[font=宋体],请参考[/font]GetWindowLong[font=宋体]函数的[/font]nIndex[font=宋体]参数的说明[/font]
  
  ' dwNewLong ------ Long[font=宋体],由[/font]nIndex[font=宋体]指定的窗口信息的新值[/font]
  Declare Function SetWindowLong Lib "user32" Alias  "SetWindowLongA" (ByVal HWnd As Long, ByVal nIndex As Long, ByVal  dwNewLong As Long) As Long
  
  '[b][font=宋体]【[/font]VB[/b][b][font=宋体]声明】[/font][/b]
  'Declare Function Shell_NotifyIcon Lib "shell32.dll" Alias  "Shell_NotifyIconA" (ByVal dwMessage As Long, lpData As  NOTIFYICONDATA) As Long
  
  '[b][font=宋体]【说明】[/font][/b]
  
  '[b][font=宋体]【参数表】[/font][/b]
  '[font=宋体]参数[/font]dwMessage  ---- [font=宋体]为消息设置值,它可以是以下的几个常数值:[/font]0[font=宋体]、[/font]1[font=宋体]、[/font]2
  
  'NIM_ADD = 0 [font=宋体]加入图标到系统状态栏中[/font]
  'NIM_MODIFY = 1 [font=宋体]修改系统状态栏中的图标[/font]
  'NIM_DELETE = 2 [font=宋体]删除系统状态栏中的图标[/font]
  
  '[font=宋体]参数[/font]LpData ----  [font=宋体]用以传入[/font]NOTIFYICONDATA[font=宋体]数据结构变量,我们也需要在[/font]"[font=宋体]模块[/font]"[font=宋体]中定义其结构如下:[/font]
  
  'Type NOTIFYICONDATA
  ' cbSize As Long [font=宋体]需填入[/font]NOTIFYICONDATA[font=宋体]数据结构的长度[/font]
  ' HWnd As Long [font=宋体]设置成窗口的句柄[/font]
  ' Uid As Long [font=宋体]为图标所设置的[/font]ID[font=宋体]值[/font]
  ' UFlags As Long [font=宋体]用来设置以下三个参数[/font]uCallbackMessage[font=宋体]、[/font]hIcon[font=宋体]、[/font]szTip[font=宋体]是否有效[/font]
  ' UCallbackMessage As Long [font=宋体]消息编号[/font]
  ' HIcon As Long [font=宋体]显示在状态栏上的图标[/font]
  ' SzTip As String * 64 [font=宋体]提示信息[/font]
  'End Type
  
  '---- [font=宋体]其中参数[/font]uCallbackMessage[font=宋体]、[/font]hIcon[font=宋体]、[/font]szTip[font=宋体]也应在模块中声明为以下的常量:[/font]
  'Public Const NIF_MESSAGE = 1
  'Public Const NIF_ICON = 2
  'Public Const NIF_TIP = 4
  
  Declare Function Shell_NotifyIcon Lib "shell32.dll" Alias  "Shell_NotifyIconA" (ByVal dwMessage As Long, lpData As  NOTIFYICONDATA) As Long
  
  
  Public Const WM_USER = &H400
  Public Const WM_LBUTTONUP = &H202
  Public Const WM_MBUTTONUP = &H208
  Public Const WM_RBUTTONUP = &H205
  Public Const TRAY_CALLBACK = (WM_USER + 1001&)
  Public Const GWL_WNDPROC = (-4)
  Public Const GWL_USERDATA = (-21)
  Public Const NIF_ICON = &H2
  Public Const NIF_TIP = &H4
  Public Const NIM_ADD = &H0
  Public Const NIF_MESSAGE = &H1
  Public Const NIM_MODIFY = &H1
  Public Const NIM_DELETE = &H2
  
  '[font=宋体]记录[/font] [font=宋体]设置托盘图标的数据[/font]  [font=宋体]的数据类型[/font]NOTIFYICONDATA
  Public Type NOTIFYICONDATA
  cbSize As Long
  HWnd As Long
  Uid As Long
  UFlags As Long
  UCallbackMessage As Long
  HIcon As Long
  SzTip As String * 64
  End Type
  
  'TheData[font=宋体]变量记录设置托盘图标的数据[/font]
  Private TheData As NOTIFYICONDATA
  ' *********************************************
  ' [font=宋体]新的窗口过程[/font]--[font=宋体]主程序中采用[/font]SetWindowLong[font=宋体]函数改变了窗口函数的地址,消息转向由[/font]NewWindowProc[font=宋体]处理[/font]
  ' *********************************************
  Public Function NewWindowProc(ByVal HWnd As Long, ByVal Msg As Long, ByVal  wParam As Long, ByVal lParam As Long) As Long
  
  '[font=宋体]如果用户点击了托盘中的图标,则进行判断是点击了左键还是右键[/font]
  If Msg = TRAY_CALLBACK Then
  '[font=宋体]如果点击了左键[/font]
  If lParam = WM_LBUTTONUP Then
  '[font=宋体]而这时窗体的状态是最小化时[/font]
  If TheForm.WindowState = vbMinimized Then _
  '[font=宋体]恢复到最小化前的窗体状态[/font]
  TheForm.WindowState = TheForm.LastState
  TheForm.SetFocus
  Exit Function
  End If
  End If
  '[font=宋体]如果点击了右键[/font]
  If lParam = WM_RBUTTONUP Then
  '[font=宋体]则弹出右键菜单[/font]
  TheForm.PopupMenu TheMenu
  Exit Function
  End If
  End If
  
  '[font=宋体]如果是其他类型的消息则传递给原有默认的窗口函数[/font]
  NewWindowProc = CallWindowProc(OldWindowProc, HWnd, Msg, wParam, lParam)
  End Function
  ' *********************************************
  ' [font=宋体]把主窗体的图标([/font]Form1.icon[font=宋体]属性可改变)添加到托盘中[/font]
  ' *********************************************
  Public Sub AddToTray(frm As Form, mnu As Menu)
  
  '[font=宋体]保存当前窗体和菜单信息[/font]
  Set TheForm = frm
  Set TheMenu = mnu
  
  'GWL_WNDPROC[font=宋体]获得该窗口的窗口函数的地址[/font]
  OldWindowProc = SetWindowLong(frm.HWnd, GWL_WNDPROC, AddressOf NewWindowProc)
  
  '[font=宋体]知识点滴:[/font]HWnd[font=宋体]属性[/font]
  '[font=宋体]返回窗体或控件的句柄。语法[/font]: object.HWnd
  '[font=宋体]说明[/font]:Microsoft  Windows [font=宋体]运行环境,通过给应用程序中的每个窗体和控件[/font]
  '[font=宋体]分配一个句柄(或[/font]  hWnd[font=宋体])来标识它们。[/font]hWnd [font=宋体]属性用于[/font]Windows API[font=宋体]调用。[/font]
  
  '[font=宋体]将主窗体图标添加在托盘中[/font]
  With TheData
  .Uid = 0 '[font=宋体]忘了吗?参考一下前面内容[/font],Uid[font=宋体]图标的序号,做动画图标有用[/font]
  .HWnd = frm.HWnd
  .cbSize = Len(TheData)
  .HIcon = frm.Icon.Handle
  .UFlags = NIF_ICON '[font=宋体]指明要对图标进行设置[/font]
  .UCallbackMessage = TRAY_CALLBACK
  .UFlags = .UFlags Or NIF_MESSAGE '[font=宋体]指明要设置图标或返回信息给主窗体,此句不能省去[/font]
  .cbSize = Len(TheData) '[font=宋体]为什么呢?我们需要在添加图标的同时,让其返回信息[/font]
  End With '[font=宋体]给主窗体,[/font]Or[font=宋体]的意思是同时进行设置和返回消息[/font]
  Shell_NotifyIcon NIM_ADD, TheData '[font=宋体]根据前面定义[/font]NIM_ADD[font=宋体],设置为[/font]“[font=宋体]添加模式[/font]”
  End Sub
  ' *********************************************
  ' [font=宋体]删除系统托盘中的图标[/font]
  ' *********************************************
  Public Sub RemoveFromTray()
  '[font=宋体]删除托盘中的图标[/font]
  With TheData
  .UFlags = 0
  End With
  Shell_NotifyIcon NIM_DELETE, TheData '[font=宋体]根据前面定义[/font]NIM_DELETE[font=宋体],设置为[/font]“[font=宋体]删除模式[/font]”
  
  '[font=宋体]恢复原有的设置[/font]
  SetWindowLong TheForm.HWnd, GWL_WNDPROC, OldWindowProc
  End Sub
  ' *********************************************
  ' [font=宋体]为托盘中的图标加上浮动提示(也就是鼠标移上去时出现的提示字条)[/font]
  ' *********************************************
  Public Sub SetTrayTip(tip As String)
  With TheData
  .SzTip = tip & vbNullChar
  .UFlags = NIF_TIP '[font=宋体]指明要对浮动提示进行设置[/font]
  End With
  Shell_NotifyIcon NIM_MODIFY, TheData '[font=宋体]根据前面定义[/font]NIM_MODIFY[font=宋体],设置为[/font]“[font=宋体]修改模式[/font]”
  End Sub
  ' *********************************************
  ' [font=宋体]设置托盘的图标(在本例中没有用到,如果要动态改变托盘内显示的图标,它非常有用)[/font]
  ' [font=宋体]例如:[/font]1[font=宋体]、显示动画图标(方法你一定猜到了,对!使用[/font]Timer[font=宋体]控件,不断调用此过程,注意把动画放在[/font]pic[font=宋体]数组中)[/font]
  ' 2[font=宋体]、程序处于不同状态时,显示不同的图标,方法是类似的[/font]
  ' [font=宋体]有兴趣的话试一试吧。[/font]
  ' *********************************************
  Public Sub SetTrayIcon(pic As Picture)
  '[font=宋体]判断一下[/font]pic[font=宋体]中存放的是不是图标[/font]
  If pic.Type <> vbPicTypeIcon Then Exit Sub
  
  '[font=宋体]更换图标为[/font]pic[font=宋体]中存放的图标[/font]
  With TheData
  .HIcon = pic.Handle
  .UFlags = NIF_ICON
  End With
  Shell_NotifyIcon NIM_MODIFY, TheData
  End Sub[font=宋体][size=12pt][/size][/font]
  [/td] [/tr][/table][/align]

替身 2008-5-23 13:51

呵呵     超牛啊
好好学习下__a1

cwctt 2008-5-23 16:21

告诉你 你这样是不对的~应该把源程序给带上 写的好乱:012

王懿 2008-5-23 16:22

有关于托盘的源码,想要留下E-mail

风之承诺 2008-5-31 16:15

不太懂API,感觉有点复杂,学习学习:008 :008

王懿 2008-5-31 16:31

呵呵,Vb相关知识都是容易上手的。加油

xebjz 2008-6-26 11:03

我要代码,我邮箱是QQ的:[email]494047021@qq.com[/email],有劳了。

mjgmjg 2008-8-11 11:42

非常感谢:_001 :_014 :_014 ,向你致敬!!!!

机械 2008-8-20 04:56

煤矸石破碎机 焦炭破碎机 环锤破碎机

*** 作者被禁止或删除 内容自动屏蔽 ***
页: [1]
查看完整版本: 详解VB托盘知识