系统托盘中的快捷图标

系统托盘中的快捷图标,第1张

系统托盘中的快捷图标,第2张

在这节课中,我们将学习如何把小图标放到系统托盘中,以及如何创建和使用弹出菜单。
理论:
系统托盘是指任务栏中的一个正方形区域,可以放一些小图标。通常在这里可以看到系统提供的最晚时间。当然,你也可以把快捷图标放在这里。下面是怎么做的:
设置NOTIFYICONDATA类型的结构变量的成员变量的值:
cbSize这个结构的大小。
hwnd窗口的句柄。当鼠标滑过小图标时,窗口会收到相关消息。
uid图标的ID号。你可以取任何值,但是当你的应用有多个小图标的时候,你要能分辨出哪个小图标收到了鼠标的消息,也就是ID号一定是。
uFlags指定该结构变量的那些成员变量是有效的。
NIF图标有效。
NIF消息有效。
NIF小费是有效的。
uCallbackMessage自定义消息。当鼠标作用于小图标时,WINDOWS shell会将消息发送到您的应用程序。这条信息的价值可以自己定义。
HICON放在系统托盘中的图标的句柄。
szTip 64字节缓冲区,用来放提示字符串,当鼠标悬停在小图标上时会显示提示字符串。
调用Shell_NotifyIcon函数。shell32.inc中定义了这个函数,其原型如下:

shell _ NotifyIcon PROTO dw message:DWORD,pnid:DWORD

DW是发送给WINDOWS shell的消息:
NIM_ADD在系统托盘区添加一个小图标。
NIM_DELETE从系统托盘中删除小图标。
NIM_MODIFY修改小图标。
pnid是指向NOTIFYICONDATA类型的结构变量的指针。
如果要添加小图标,使用NIM_ADD,删除时使用NIM_DELETE消息。

这是基本消息。但是在大多数情况下,你不会仅仅满足于在那里放一个小图标。您还必须适当地响应鼠标事件。您可以在NOTIFYICONDATA类型的结构变量的成员变量uCallbackMessage中设置要处理的消息,然后当这些事件发生时,WINDOWS shell将通知您的应用程序。随消息发送的参数wParam和lParam的值如下:
wParam图标的ID号。它与您在NOTIFYICONDATA结构变量的成员变量uID中设置的值相同。
lParam低位字包含鼠标消息。例如,当用户按下小图标上的右键时,消息WM_RBUTTONDOWN将包含在lParam中。
系统托盘中的大部分小图标在用户用鼠标右键点击时都会弹出菜单,方便用户选择。我们可以先创建一个菜单,然后调用TrackPopupMenu函数来显示它。步骤如下:
调用CreatePopupMenu函数创建菜单。这个函数创建空的菜单。如果成功,该菜单的句柄将在eax中返回。
调用AppendMenu、InsertMenu或InsertMenuItem向菜单添加菜单项。
当要在当前鼠标位置显示菜单时,调用GetCursorPosition函数获取鼠标的当前屏幕位置,然后调用TrackPopupMenu显示菜单。当用户从弹出菜单中选择一个菜单项时,WINDOWS会将WM_COMMAND消息发送到你的应用程序的消息处理进程中,这与通常的菜单选择是一样的。。
注意:在使用系统托盘中的小图标时有两个恼人的事情:
菜单可能不会像往常一样很快消失。这是因为从弹出窗口接收消息的窗口必须是前台窗口。通过调用SetForegroundWindow函数可以纠正该错误;
调用SetForegroundWindow函数后,你会发现弹出菜单会正常弹出,第一次效果很好。但是菜单一弹出就消失了。据MSDN说,这是故意的。为了保留弹出菜单,接下来需要切换到程序的主窗口。您可以通过向程序窗口发送任何消息来强制任务切换。注意使用PostMessage而不是SendMessage。

例如:
.386
。modelflat,stdcall
option casemap:none
include \ masm 32 \ include \ windows . Inc
include \ masm 32 \ include \ USER 32 . Inc
include \ masm 32 \ include \ kernel 32 . Inc
include \ masm 32 \ include \ shell 32 . Inc
include lib \ masm 32 \ lib \ USER 32 . lib
include lib \ masm 32 \ lib \ kernel 32 .

。data
class name db " tray icon winclass ",0
AppName db "TrayIcon Demo ",0
RestoreString db " & Restore ",0
exit string db " E & exit Program ",0

。数据?
hInstance dd?
NOTIFYICONDATA
hPopupMenu DD?

。code
start:
invoke GetModuleHandle,NULL
mov hInstance,eax
invoke WinMain,hInstance,NULL,NULL,SW _ show default
invoke exit process,eax

WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
LOCAL WC:WNDCLASSEX
LOCAL MSG:MSG
LOCAL HWND:HWND
mov WC . cbsize,SIZEOF WNDCLASSEX
mov WC . style,CS_HREDRAW或CS_VREDRAW或CS _ DBLCLKS
mov WC . lpfnwndproc,OFFSET WndProc而TRUE
调用GetMessage,ADDR消息,NULL,0,0
。休息。如果(!eax)
调用TranslateMessage,ADDR消息
调用DispatchMessage,ADDR消息
。endw
mov eax,msg . wParam
ret
WinMain endp
WndProc proc hWnd:hWnd,uMsg:UINT,wParam:WPARAM,lParam:lParam
LOCAL pt:POINT
。if uMsg = = WM _ CREATE
invoke CreatePopupMenu
mov hPopupMenu,eax
invoke AppendMenu,hPopupMenu,MF_STRING,IDM_RESTORE,addr restoring
invoke AppendMenu,hPopupMenu,MF_STRING,IDM_EXIT,addr ExitString
。else if uMsg = = WM _ DESTROY
invoke DESTROY menu,hPopupMenu
invoke PostQuitMessage,NULL
。elseif uMsg==WM_SIZE
。if wParam = = SIZE _ MINIMIZED
mov note . cbsize,sizeof NotifyIcon data
push hWnd
pop note . hWnd
mov note . uid,IDI _托盘
mov note.uFlags,NIF _ ICON+NIF _ MESSAGE+NIF _ TIP
mov note . ucallbackmessage,WM _ Shell notify
invoke LoadIcon,NULL,IDI _ WINLOGO
mov note . hic lagsendif
。elseif uMsg==WM_COMMAND
。如果lParam==0
调用Shell_NotifyIcon,NIM_DELETE,addr note
mov eax,wParam
。if ax==IDM_RESTORE
调用ShowWindow,hWnd,SW_RESTORE
。否则
调用DestroyWindow,hWnd
。endif
。endif
。else if uMsg = = WM _ shell notify
。如果wParam==IDI托盘
。if lParam = = WM _ RBUTTONDOWN
invoke GetCursorPos,addr pt
invoke SetForegroundWindow,hWnd
invoke TrackPopupMenu,hPopupMenu,TPM_RIGHTALIGN,pt.x,pt.y,NULL,hWnd,NULL
invoke PostMessage,hWnd,WM_NULL,0,0
。else if lParam = = WM _ LBUTTONDBLCLK
invoke SendMessage,hWnd,WM_COMMAND,IDM_RESTORE,0
。endif
。endif
。else
调用DefWindowProc,hWnd,uMsg,wParam,lParam
ret
。endif
xor eax,eax
ret
WndProc endp

结束开始

分析:
程序会显示一个简单的窗口。当你按下最小化按钮,窗口将被隐藏,然后一个小图标将被放置在系统托盘中。当你双击小图标时,应用程序会自动恢复并从系统托盘中删除小图标。右键单击小图标时,会显示一个弹出菜单。您可以在菜单中选择是恢复窗口还是退出应用程序。
。if uMsg = = WM _ CREATE
invoke CreatePopupMenu
mov hPopupMenu,eax
invoke AppendMenu,hPopupMenu,MF_STRING,IDM_RESTORE,addr restoring
invoke AppendMenu,hPopupMenu,MF_STRING,IDM_EXIT,addr ExitString

创建主窗口时,将创建一个弹出菜单,并添加两个菜单项。AppendMenu的语法如下:


append menu PROTO hMenu:DWORD,uFlags:DWORD,uIDNewItem:DWORD,lpNewItem:DWORD

HMU是要添加到菜单项的菜单的句柄。
uFlags告诉WINDOWS要添加的菜单项是位图、字符串还是自绘项,以及它们是可用、不可用还是灰显。您可以从WIN32 API指南中获得标志位的所有信息。在我们的例子中,我们使用标志位MF_STRING,它表示我们加入的菜单项是一个字符串。
uIDNewItem是菜单项的ID号。这是用户定义的值,用于准确表示菜单项。。
lpNewItem用于指定菜单项的内容,它所代表的内容取决于uFlags中指定的标志。我们之前指定了MF_STRING标志,所以它在这里代表一个字符串
主窗口创建后,用户就可以开始测试了。此时,按下最小化键。
当窗口最小化时,将收到一条WM_SIZE消息,其中wParam参数中的值是SIZE_MINIMIZED。
。elseif uMsg==WM_SIZE
。if wParam = = SIZE _ MINIMIZED
mov note . cbsize,sizeof NotifyIcon data
push hWnd
pop note . hWnd
mov note . uid,IDI _托盘
mov note.uFlags,NIF _ ICON+NIF _ MESSAGE+NIF _ TIP
mov note . ucallbackmessage,WM _ Shell notify
invoke LoadIcon,NULL,IDI _ WINLOGO
mov note . hic lags结束条件

此时,让我们为NOTIFYICONDATA结构变量赋值。IDI _托盘是一个在代码开头定义的数值常量,你可以任意设置它的值。因为我们只有一个图标,所以没关系。如果你想同时添加几个系统图标,那么每个图标必须有一个唯一的ID号。因为我们已经指定了一个图标NIF图标,我们必须在uFlags成员变量中指定所有的标志位。我们还指定了自定义消息NIF _消息和帮助文本NIF _提示。WM_SHELLNOTIFY定义为WM_USER+5。只要是值,什么都无所谓,只要大于WM_USER就行。当WINDOWS登录到这里时,我们使用图标。当然,你可以使用任何你想要的图标。您可以使用LoadIcon函数从资源中加载它,该函数返回图标的句柄。最后,我们把鼠标在图标上时显示的提示文本放在szTip中。为了达到“最小化后只显示图标”的效果,此时我们隐藏主窗口。
接下来,我们调用Shell_NotifyIcon函数并指定标志NIM_ADD,将图标添加到系统托盘中。

现在我们的主窗口是隐藏的,图标显示在系统托盘中。如果将鼠标滚动到图标上,您将看到提示文本。如果双击小图标,将显示主窗口,图标将消失。

。else if uMsg = = WM _ shell notify
。如果wParam==IDI托盘
。if lParam = = WM _ RBUTTONDOWN
invoke GetCursorPos,addr pt
invoke SetForegroundWindow,hWnd
invoke TrackPopupMenu,hPopupMenu,TPM_RIGHTALIGN,pt.x,pt.y,NULL,hWnd,NULL
invoke PostMessage,hWnd,WM_NULL,0,0
。else if lParam = = WM _ LBUTTONDBLCLK
invoke SendMessage,hWnd,WM_COMMAND,IDM_RESTORE,0
。endif
。结束条件

当鼠标事件发生在系统托盘中的图标上时,您的窗口将收到WM_SHELLNOTIFY消息,该消息在uCallbackMessage成员变量中指定。收到消息时,wParam包含图标的ID号,lParam包含鼠标动作的原始数据。在上面的代码中,我们首先检查它是否是我们感兴趣的消息。如果是的话,我们正在看它是什么新闻。因为我们只对右击和双击事件感兴趣,所以我们只处理WM_RBUTTONDOWN和WM_LBUTTONDBLCLK消息。
如果是WM_RBUTTONDOWN,我们调用GetCursorPos获取鼠标光标所在的当前屏幕位置。注意,我指的是屏幕位置,也就是它的坐标是相对于整个屏幕的。举个例子,如果屏幕的分辨率是640*480,那么它右下角的坐标就是x==639,y==479。如果想把屏幕位置转换成窗口的坐标,可以调用ScreenToClient函数
。如果要在当前位置显示弹出菜单,我们会调用TrackPopupMenu函数,这个函数需要屏幕的坐标,GetCursorPos函数返回的坐标可以原封不动地使用。
轨道弹出菜单的原型如下:


trackpoppmenu PROTO hMenu:DWORD,uFlags:DWORD,x:DWORD,y:DWORD,nReserved:DWORD,hWnd:DWORD,prcRect:DWORD

Hmu是弹出hMenu的手柄。
u flags函数的选择。比如把菜单放在哪里(相对于后面要指定的坐标),用哪个鼠标键来跟踪弹出菜单。在我们的示例中,我们使用TPM_RIGHTALIGN标志位来指定弹出菜单位于坐标的左侧。
x和Y指定位置菜单的屏幕坐标。
nReserved必须为空。
hWnd是将接收消息的窗口的句柄。
prcRect指定一个矩形区域。如果在矩形区域外按下鼠标,菜单将消失。一般情况下,我们将该值设置为NULL,这样当用户在菜单外按下鼠标时,菜单立即消失。


当用户双击图标时,我们向自己的窗口发送WM_COMMAND消息,并将消息指定为IDM_Restore,可以达到与在弹出菜单中选择“恢复”菜单项相同的效果。为了接收双击消息,主窗口必须具有CS_DBLCLKS样式。

调用Shell_NotifyIcon,NIM_DELETE,addr note
mov eax,wParam
。if ax==IDM_RESTORE
调用ShowWindow,hWnd,SW_RESTORE
。否则
调用DestroyWindow,hWnd
。结束条件

当用户选择恢复主窗口时,我们调用Shell_NotifyIcon函数删除系统托盘中的图标。这一次,我们将指定NIM_DELETE消息。接下来,让我们将主窗口恢复到原始状态。如果用户选择退出菜单项,我们不仅要删除图标,还要退出整个应用程序。

位律师回复
DABAN RP主题是一个优秀的主题,极致后台体验,无插件,集成会员系统
白度搜_经验知识百科全书 » 系统托盘中的快捷图标

0条评论

发表评论

提供最优质的资源集合

立即查看 了解详情