`
dowhathowtodo
  • 浏览: 777452 次
文章分类
社区版块
存档分类
最新评论

系统托盘中的快捷图标

 
阅读更多

第二十三课 系统托盘中的快捷图标


本课中,我们将学习如何把小图标放到系统托盘中去以及如何创建和使用弹出式菜单。

理论:

系统托盘是指任务条中的一个方形区域,在该区域中可以放入一些小图标,通常您可以在此处看到系统提供的最新时间。您自己当然也可以把快捷小图标放到此处。下面是这么做的步骤:
  1. 设置NOTIFYICONDATA型的结构体变量的成员变量的值:
    • cbSize 该结构体的大小。
    • hwnd 窗口的句柄。当鼠标滑过该小图标时,该窗口将接收到相关的消息。
    • uID 小图标的ID号。您可以取任意值,只是当您的应用程序有不止一个小图标时,您要能够区分出到底是那一个小图标接收到了鼠标的消息,也即ID号必须唯一。
    • uFlags 指定该结构体变量的那些成员变量有效。
      • NIF_ICON 有效。
      • NIF_MESSAGE 有效。
      • NIF_TIP 有效。
    • uCallbackMessage 自定义的消息。当鼠标对小图标动作时,WINDOWS外壳将把该消息发送到您的应用程序。该消息的值您可以自己定义。
    • hIcon 放入系统托盘中的图标的句柄。
    • szTip 64字节的缓冲区,它用来放入提示字符串,当鼠标停留在小图标上时,就会显示该字符串。
  2. 调用Shell_NotifyIcon函数。该函数在shell32.inc中定义,其原型如下:


    Shell_NotifyIcon PROTO dwMessage:DWORD ,pnid:DWORD

    dwMessage 是发送到WINDOWS外壳的消息:
    NIM_ADD 把小图标加到系统托盘区。
    NIM_DELETE 从系统托盘中删除小图标。
    NIM_MODIFY 修改小图标。
    pnid 是指向NOTIFYICONDATA型结构体变量的指针。
    如果您想要加入一个小图标就用NIM_ADD,删除时使用NIM_DELETE消息。

基本上的消息就是这些。但是大多数的情况下,您不会仅仅满足把一个小图标放到那里。您还必须要对鼠标事件作出适当的反应。您可以在NOTIFYICONDATA型的结构体变量的成员变量uCallbackMessage 中设置您要处理的消息,然后WINDOWS外壳将在发生这些事件时通知您的应用程序。随着消息传送的参数wParam和lParam的值如下:
  • wParam 小图标的ID号。它和您在NOTIFYICONDATA型结构体变量中的成员变量uID中设置的值一样。
  • lParam 低字包含鼠标消息。譬如,用户在小图标上按下了右键时,lParam中将包含WM_RBUTTONDOWN消息。
大多数的系统托盘中的小图标,在用户用鼠标右击时都会弹出一个菜单以方便用户选择。我们可先创建菜单,然后调用TrackPopupMenu函数来显示它。步骤如下:
  1. 调用CreatePopupMenu函数来创建菜单。该函数创建一个空的菜单。如果成功,将在eax中返回该菜单的句柄。
  2. 调用AppendMenu, InsertMenu 或 InsertMenuItem来向菜单中加入菜单项。
  3. 当您想在当前鼠标位置显示该菜单时,调用GetCursorPosition函数来得到鼠标当前的屏幕位置,然后调用TrackPopupMenu来显示菜单。当用户从弹出式菜单中选择了一个菜单项时,WINDOWS将发送WM_COMMAND消息给您应用程序的消息处理过程,这和通常的菜单选择是一样的。.
注意:当您使用系统托盘中的小图标时有两件比较讨厌的事:
  1. 该菜单可能不会像通常那样马上消失掉。这是因为从弹出式接收消息的窗口必须是前景窗口。调用SetForegroundWindow函数就可以纠正该错误;
  2. 在调用了SetForegroundWindow函数后,您会发现第一次该弹出式菜单会正常弹出而且工作的很好。但是随后,该菜单只是一弹出就立即消失。根据MSDN,这么做是故意的。为了使得弹出菜单保持住,必须要求下一个切换到的是程序的主窗口。您可以通过邮寄任何消息给该程序的窗口来强行进行任务切换。注意要使用PostMessage而不是SendMessage。

例子:

.386
.model flat,stdcall
option casemap:none
include /masm32/include/windows.inc
include /masm32/include/user32.inc
include /masm32/include/kernel32.inc
include /masm32/include/shell32.inc
includelib /masm32/lib/user32.lib
includelib /masm32/lib/kernel32.lib
includelib /masm32/lib/shell32.lib

WM_SHELLNOTIFY equ WM_USER+5
IDI_TRAY equ 0
IDM_RESTORE equ 1000
IDM_EXIT equ 1010
WinMain PROTO :DWORD,:DWORD,:DWORD,:DWORD

.data
ClassName db "TrayIconWinClass",0
AppName db "TrayIcon Demo",0
RestoreString db "&Restore",0
ExitString db "E&xit Program",0

.data?
hInstance dd ?
note NOTIFYICONDATA <>
hPopupMenu dd ?

.code
start:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke WinMain, hInstance,NULL,NULL, SW_SHOWDEFAULT
invoke ExitProcess,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 or CS_VREDRAW or CS_DBLCLKS
mov wc.lpfnWndProc, OFFSET WndProc
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,NULL
push hInst
pop wc.hInstance
mov wc.hbrBackground,COLOR_APPWORKSPACE
mov wc.lpszMenuName,NULL
mov wc.lpszClassName,OFFSET ClassName
invoke LoadIcon,NULL,IDI_APPLICATION
mov wc.hIcon,eax
mov wc.hIconSm,eax
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax
invoke RegisterClassEx, addr wc
invoke CreateWindowEx,WS_EX_CLIENTEDGE,ADDR ClassName,ADDR AppName,/
WS_OVERLAPPED+WS_CAPTION+WS_SYSMENU+WS_MINIMIZEBOX+WS_MAXIMIZEBOX+WS_VISIBLE,CW_USEDEFAULT,/
CW_USEDEFAULT,350,200,NULL,NULL,/
hInst,NULL
mov hwnd,eax
.while TRUE
invoke GetMessage, ADDR msg,NULL,0,0
.BREAK .IF (!eax)
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
.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 RestoreString
invoke AppendMenu,hPopupMenu,MF_STRING,IDM_EXIT,addr ExitString
.elseif uMsg==WM_DESTROY
invoke DestroyMenu,hPopupMenu
invoke PostQuitMessage,NULL
.elseif uMsg==WM_SIZE
.if wParam==SIZE_MINIMIZED
mov note.cbSize,sizeof NOTIFYICONDATA
push hWnd
pop note.hwnd
mov note.uID,IDI_TRAY
mov note.uFlags,NIF_ICON+NIF_MESSAGE+NIF_TIP
mov note.uCallbackMessage,WM_SHELLNOTIFY
invoke LoadIcon,NULL,IDI_WINLOGO
mov note.hIcon,eax
invoke lstrcpy,addr note.szTip,addr AppName
invoke ShowWindow,hWnd,SW_HIDE
invoke Shell_NotifyIcon,NIM_ADD,addr note
.endif
.elseif uMsg==WM_COMMAND
.if lParam==0
invoke Shell_NotifyIcon,NIM_DELETE,addr note
mov eax,wParam
.if ax==IDM_RESTORE
invoke ShowWindow,hWnd,SW_RESTORE
.else
invoke DestroyWindow,hWnd
.endif
.endif
.elseif uMsg==WM_SHELLNOTIFY
.if wParam==IDI_TRAY
.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
.elseif lParam==WM_LBUTTONDBLCLK
invoke SendMessage,hWnd,WM_COMMAND,IDM_RESTORE,0
.endif
.endif
.else
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.endif
xor eax,eax
ret
WndProc endp

end start

分析:

该程序将显示一个简单的窗口。当您按下最小化按钮时,该窗口将隐藏,然后放一个小图标到系统托盘中。当您双击小图标时,应用程序将恢复自己,并把小图标从系统托盘中删除。当您右击小图标时,会显示一个弹出式菜单。您可以在菜单中选择是恢复窗口还是退出应用程序。

.if uMsg==WM_CREATE
invoke CreatePopupMenu
mov hPopupMenu,eax
invoke AppendMenu,hPopupMenu,MF_STRING,IDM_RESTORE,addr RestoreString
invoke AppendMenu,hPopupMenu,MF_STRING,IDM_EXIT,addr ExitString

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

AppendMenu PROTO hMenu:DWORD, uFlags:DWORD, uIDNewItem:DWORD, lpNewItem:DWORD
  • hMenu 是将要加入菜单项的菜单的句柄。
  • 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 NOTIFYICONDATA
push hWnd
pop note.hwnd
mov note.uID,IDI_TRAY
mov note.uFlags,NIF_ICON+NIF_MESSAGE+NIF_TIP
mov note.uCallbackMessage,WM_SHELLNOTIFY
invoke LoadIcon,NULL,IDI_WINLOGO
mov note.hIcon,eax
invoke lstrcpy,addr note.szTip,addr AppName
invoke ShowWindow,hWnd,SW_HIDE
invoke Shell_NotifyIcon,NIM_ADD,addr note
.endif

这时我们来给NOTIFYICONDATA型结构体变量赋值。IDI_TRAY是在代码开始处定义的一个数值常量,您可以任意设定它的值。由于我们仅有一个图标,所以这一点并不重要,如果要同时加入几个系统图标的话,那么每个图标都要有一个唯一的ID号。由于我们指定了一个图标NIF_ICON,所以我们要在uFlags成员变量中指定所有的标志位,我们还指定了一个自定义的消息NIF_MESSAGE和帮助文本NIF_TIP。 WM_SHELLNOTIFY 被定义为WM_USER+5,只要是唯一的值,就无所谓是多少了,只要大于WM_USER。我们这里用的是WINDOWS登录时的图标,当然您可以使用任意您想要用的图标,您可以用LoadIcon函数从资源中装载,该函数返回一个图标的句柄。最后我们在szTip中放入当鼠标放在图标时显示的提示文本。为了达到“最小化然后只显示图标的效果”,我们在这时隐藏掉主窗口。
接下来,我们调用Shell_NotifyIcon函数并指定标志位NIM_ADD把图标加到系统托盘中去。

现在我们的主窗口隐藏了,图标显示在系统托盘中。如果您让鼠标从图标上滑过,将看到提示文本。如果您双击小图标,主窗口就会显示,图标将消失。

.elseif uMsg==WM_SHELLNOTIFY
.if wParam==IDI_TRAY
.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
.elseif lParam==WM_LBUTTONDBLCLK
invoke SendMessage,hWnd,WM_COMMAND,IDM_RESTORE,0
.endif
.endif

当在系统托盘中的图标发生鼠标事件时,您的窗口将接收到WM_SHELLNOTIFY消息,该消息是在uCallbackMessage成员变量中指定的。在接收到该消息时,wParam中包含了图标的ID号,lParam中包含了鼠标动作的原始数据。在上面的代码中,我们首先检测是否是我们感兴趣的消息。如果是的话,我们在看看是什么消息。因为我们只对右击和双击事件感兴趣,所以我们仅仅处理WM_RBUTTONDOWN和WM_LBUTTONDBLCLK消息。
如果是WM_RBUTTONDOWN,我们调用GetCursorPos来得到鼠标光标所在的当前屏幕位置。注意我指的是屏幕位置,即,其坐标是相对于整个的屏幕的。譬如,如果屏幕的解析读640*480,那么它的右下角的坐标是x==639 ,y==479。如果您想要把屏幕位置转换成窗口的坐标,可以调用ScreenToClient函数
我们想要在当前的位置显示弹出式菜单,我们就调用TrackPopupMenu函数,该函数需要屏幕的坐标,由GetCursorPos函数返回的坐标就可以原封不动的拿过来用。
TrackPopupMenu的原型如下:

    TrackPopupMenu PROTO hMenu:DWORD, uFlags:DWORD, x:DWORD, y:DWORD, nReserved:DWORD, hWnd:DWORD, prcRect:DWORD
  • hMenu 是弹出式菜单的句柄。
  • uFlags 功能的选择。像在哪里放置(相对于随后将指定的坐标)菜单,那一个鼠标按钮用来跟踪弹出式菜单。在我们的例子中,我们用TPM_RIGHTALIGN标志位来指定弹出式菜单放在坐标的左边。
  • x 和 y 指定放置菜单的屏幕坐标。
  • nReserved 必须为NULL。
  • hWnd 是将要接收消息的窗口的句柄。
  • prcRect 指定一个矩形区域。如果在该矩形区域外面按下鼠标的话,菜单将消失。一般我们把该值设为NULL,这样当用户只要在菜单外面按下鼠标,菜单立即消失。

当用户双击图标时,我们给我们自己的窗口发送WM_COMMAND消息,并指定消息为IDM_RESTORE,这样可以达到和在弹出式菜单中选择“Restore”菜单项同样的效果。为了能够接收到双击消息,主窗口必须要有的CS_DBLCLKS 风格。

invoke Shell_NotifyIcon,NIM_DELETE,addr note
mov eax,wParam
.if ax==IDM_RESTORE
invoke ShowWindow,hWnd,SW_RESTORE
.else
invoke DestroyWindow,hWnd
.endif

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


第二十三课 系统托盘中的快捷图标


本课中,我们将学习如何把小图标放到系统托盘中去以及如何创建和使用弹出式菜单。

理论:

系统托盘是指任务条中的一个方形区域,在该区域中可以放入一些小图标,通常您可以在此处看到系统提供的最新时间。您自己当然也可以把快捷小图标放到此处。下面是这么做的步骤:
  1. 设置NOTIFYICONDATA型的结构体变量的成员变量的值:
    • cbSize 该结构体的大小。
    • hwnd 窗口的句柄。当鼠标滑过该小图标时,该窗口将接收到相关的消息。
    • uID 小图标的ID号。您可以取任意值,只是当您的应用程序有不止一个小图标时,您要能够区分出到底是那一个小图标接收到了鼠标的消息,也即ID号必须唯一。
    • uFlags 指定该结构体变量的那些成员变量有效。
      • NIF_ICON 有效。
      • NIF_MESSAGE 有效。
      • NIF_TIP 有效。
    • uCallbackMessage 自定义的消息。当鼠标对小图标动作时,WINDOWS外壳将把该消息发送到您的应用程序。该消息的值您可以自己定义。
    • hIcon 放入系统托盘中的图标的句柄。
    • szTip 64字节的缓冲区,它用来放入提示字符串,当鼠标停留在小图标上时,就会显示该字符串。
  2. 调用Shell_NotifyIcon函数。该函数在shell32.inc中定义,其原型如下:


    Shell_NotifyIcon PROTO dwMessage:DWORD ,pnid:DWORD

    dwMessage 是发送到WINDOWS外壳的消息:
    NIM_ADD 把小图标加到系统托盘区。
    NIM_DELETE 从系统托盘中删除小图标。
    NIM_MODIFY 修改小图标。
    pnid 是指向NOTIFYICONDATA型结构体变量的指针。
    如果您想要加入一个小图标就用NIM_ADD,删除时使用NIM_DELETE消息。

基本上的消息就是这些。但是大多数的情况下,您不会仅仅满足把一个小图标放到那里。您还必须要对鼠标事件作出适当的反应。您可以在NOTIFYICONDATA型的结构体变量的成员变量uCallbackMessage 中设置您要处理的消息,然后WINDOWS外壳将在发生这些事件时通知您的应用程序。随着消息传送的参数wParam和lParam的值如下:
  • wParam 小图标的ID号。它和您在NOTIFYICONDATA型结构体变量中的成员变量uID中设置的值一样。
  • lParam 低字包含鼠标消息。譬如,用户在小图标上按下了右键时,lParam中将包含WM_RBUTTONDOWN消息。
大多数的系统托盘中的小图标,在用户用鼠标右击时都会弹出一个菜单以方便用户选择。我们可先创建菜单,然后调用TrackPopupMenu函数来显示它。步骤如下:
  1. 调用CreatePopupMenu函数来创建菜单。该函数创建一个空的菜单。如果成功,将在eax中返回该菜单的句柄。
  2. 调用AppendMenu, InsertMenu 或 InsertMenuItem来向菜单中加入菜单项。
  3. 当您想在当前鼠标位置显示该菜单时,调用GetCursorPosition函数来得到鼠标当前的屏幕位置,然后调用TrackPopupMenu来显示菜单。当用户从弹出式菜单中选择了一个菜单项时,WINDOWS将发送WM_COMMAND消息给您应用程序的消息处理过程,这和通常的菜单选择是一样的。.
注意:当您使用系统托盘中的小图标时有两件比较讨厌的事:
  1. 该菜单可能不会像通常那样马上消失掉。这是因为从弹出式接收消息的窗口必须是前景窗口。调用SetForegroundWindow函数就可以纠正该错误;
  2. 在调用了SetForegroundWindow函数后,您会发现第一次该弹出式菜单会正常弹出而且工作的很好。但是随后,该菜单只是一弹出就立即消失。根据MSDN,这么做是故意的。为了使得弹出菜单保持住,必须要求下一个切换到的是程序的主窗口。您可以通过邮寄任何消息给该程序的窗口来强行进行任务切换。注意要使用PostMessage而不是SendMessage。

例子:

.386
.model flat,stdcall
option casemap:none
include /masm32/include/windows.inc
include /masm32/include/user32.inc
include /masm32/include/kernel32.inc
include /masm32/include/shell32.inc
includelib /masm32/lib/user32.lib
includelib /masm32/lib/kernel32.lib
includelib /masm32/lib/shell32.lib

WM_SHELLNOTIFY equ WM_USER+5
IDI_TRAY equ 0
IDM_RESTORE equ 1000
IDM_EXIT equ 1010
WinMain PROTO :DWORD,:DWORD,:DWORD,:DWORD

.data
ClassName db "TrayIconWinClass",0
AppName db "TrayIcon Demo",0
RestoreString db "&Restore",0
ExitString db "E&xit Program",0

.data?
hInstance dd ?
note NOTIFYICONDATA <>
hPopupMenu dd ?

.code
start:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke WinMain, hInstance,NULL,NULL, SW_SHOWDEFAULT
invoke ExitProcess,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 or CS_VREDRAW or CS_DBLCLKS
mov wc.lpfnWndProc, OFFSET WndProc
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,NULL
push hInst
pop wc.hInstance
mov wc.hbrBackground,COLOR_APPWORKSPACE
mov wc.lpszMenuName,NULL
mov wc.lpszClassName,OFFSET ClassName
invoke LoadIcon,NULL,IDI_APPLICATION
mov wc.hIcon,eax
mov wc.hIconSm,eax
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax
invoke RegisterClassEx, addr wc
invoke CreateWindowEx,WS_EX_CLIENTEDGE,ADDR ClassName,ADDR AppName,/
WS_OVERLAPPED+WS_CAPTION+WS_SYSMENU+WS_MINIMIZEBOX+WS_MAXIMIZEBOX+WS_VISIBLE,CW_USEDEFAULT,/
CW_USEDEFAULT,350,200,NULL,NULL,/
hInst,NULL
mov hwnd,eax
.while TRUE
invoke GetMessage, ADDR msg,NULL,0,0
.BREAK .IF (!eax)
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
.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 RestoreString
invoke AppendMenu,hPopupMenu,MF_STRING,IDM_EXIT,addr ExitString
.elseif uMsg==WM_DESTROY
invoke DestroyMenu,hPopupMenu
invoke PostQuitMessage,NULL
.elseif uMsg==WM_SIZE
.if wParam==SIZE_MINIMIZED
mov note.cbSize,sizeof NOTIFYICONDATA
push hWnd
pop note.hwnd
mov note.uID,IDI_TRAY
mov note.uFlags,NIF_ICON+NIF_MESSAGE+NIF_TIP
mov note.uCallbackMessage,WM_SHELLNOTIFY
invoke LoadIcon,NULL,IDI_WINLOGO
mov note.hIcon,eax
invoke lstrcpy,addr note.szTip,addr AppName
invoke ShowWindow,hWnd,SW_HIDE
invoke Shell_NotifyIcon,NIM_ADD,addr note
.endif
.elseif uMsg==WM_COMMAND
.if lParam==0
invoke Shell_NotifyIcon,NIM_DELETE,addr note
mov eax,wParam
.if ax==IDM_RESTORE
invoke ShowWindow,hWnd,SW_RESTORE
.else
invoke DestroyWindow,hWnd
.endif
.endif
.elseif uMsg==WM_SHELLNOTIFY
.if wParam==IDI_TRAY
.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
.elseif lParam==WM_LBUTTONDBLCLK
invoke SendMessage,hWnd,WM_COMMAND,IDM_RESTORE,0
.endif
.endif
.else
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.endif
xor eax,eax
ret
WndProc endp

end start

分析:

该程序将显示一个简单的窗口。当您按下最小化按钮时,该窗口将隐藏,然后放一个小图标到系统托盘中。当您双击小图标时,应用程序将恢复自己,并把小图标从系统托盘中删除。当您右击小图标时,会显示一个弹出式菜单。您可以在菜单中选择是恢复窗口还是退出应用程序。

.if uMsg==WM_CREATE
invoke CreatePopupMenu
mov hPopupMenu,eax
invoke AppendMenu,hPopupMenu,MF_STRING,IDM_RESTORE,addr RestoreString
invoke AppendMenu,hPopupMenu,MF_STRING,IDM_EXIT,addr ExitString

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

AppendMenu PROTO hMenu:DWORD, uFlags:DWORD, uIDNewItem:DWORD, lpNewItem:DWORD
  • hMenu 是将要加入菜单项的菜单的句柄。
  • 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 NOTIFYICONDATA
push hWnd
pop note.hwnd
mov note.uID,IDI_TRAY
mov note.uFlags,NIF_ICON+NIF_MESSAGE+NIF_TIP
mov note.uCallbackMessage,WM_SHELLNOTIFY
invoke LoadIcon,NULL,IDI_WINLOGO
mov note.hIcon,eax
invoke lstrcpy,addr note.szTip,addr AppName
invoke ShowWindow,hWnd,SW_HIDE
invoke Shell_NotifyIcon,NIM_ADD,addr note
.endif

这时我们来给NOTIFYICONDATA型结构体变量赋值。IDI_TRAY是在代码开始处定义的一个数值常量,您可以任意设定它的值。由于我们仅有一个图标,所以这一点并不重要,如果要同时加入几个系统图标的话,那么每个图标都要有一个唯一的ID号。由于我们指定了一个图标NIF_ICON,所以我们要在uFlags成员变量中指定所有的标志位,我们还指定了一个自定义的消息NIF_MESSAGE和帮助文本NIF_TIP。 WM_SHELLNOTIFY 被定义为WM_USER+5,只要是唯一的值,就无所谓是多少了,只要大于WM_USER。我们这里用的是WINDOWS登录时的图标,当然您可以使用任意您想要用的图标,您可以用LoadIcon函数从资源中装载,该函数返回一个图标的句柄。最后我们在szTip中放入当鼠标放在图标时显示的提示文本。为了达到“最小化然后只显示图标的效果”,我们在这时隐藏掉主窗口。
接下来,我们调用Shell_NotifyIcon函数并指定标志位NIM_ADD把图标加到系统托盘中去。

现在我们的主窗口隐藏了,图标显示在系统托盘中。如果您让鼠标从图标上滑过,将看到提示文本。如果您双击小图标,主窗口就会显示,图标将消失。

.elseif uMsg==WM_SHELLNOTIFY
.if wParam==IDI_TRAY
.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
.elseif lParam==WM_LBUTTONDBLCLK
invoke SendMessage,hWnd,WM_COMMAND,IDM_RESTORE,0
.endif
.endif

当在系统托盘中的图标发生鼠标事件时,您的窗口将接收到WM_SHELLNOTIFY消息,该消息是在uCallbackMessage成员变量中指定的。在接收到该消息时,wParam中包含了图标的ID号,lParam中包含了鼠标动作的原始数据。在上面的代码中,我们首先检测是否是我们感兴趣的消息。如果是的话,我们在看看是什么消息。因为我们只对右击和双击事件感兴趣,所以我们仅仅处理WM_RBUTTONDOWN和WM_LBUTTONDBLCLK消息。
如果是WM_RBUTTONDOWN,我们调用GetCursorPos来得到鼠标光标所在的当前屏幕位置。注意我指的是屏幕位置,即,其坐标是相对于整个的屏幕的。譬如,如果屏幕的解析读640*480,那么它的右下角的坐标是x==639 ,y==479。如果您想要把屏幕位置转换成窗口的坐标,可以调用ScreenToClient函数
我们想要在当前的位置显示弹出式菜单,我们就调用TrackPopupMenu函数,该函数需要屏幕的坐标,由GetCursorPos函数返回的坐标就可以原封不动的拿过来用。
TrackPopupMenu的原型如下:

    TrackPopupMenu PROTO hMenu:DWORD, uFlags:DWORD, x:DWORD, y:DWORD, nReserved:DWORD, hWnd:DWORD, prcRect:DWORD
  • hMenu 是弹出式菜单的句柄。
  • uFlags 功能的选择。像在哪里放置(相对于随后将指定的坐标)菜单,那一个鼠标按钮用来跟踪弹出式菜单。在我们的例子中,我们用TPM_RIGHTALIGN标志位来指定弹出式菜单放在坐标的左边。
  • x 和 y 指定放置菜单的屏幕坐标。
  • nReserved 必须为NULL。
  • hWnd 是将要接收消息的窗口的句柄。
  • prcRect 指定一个矩形区域。如果在该矩形区域外面按下鼠标的话,菜单将消失。一般我们把该值设为NULL,这样当用户只要在菜单外面按下鼠标,菜单立即消失。

当用户双击图标时,我们给我们自己的窗口发送WM_COMMAND消息,并指定消息为IDM_RESTORE,这样可以达到和在弹出式菜单中选择“Restore”菜单项同样的效果。为了能够接收到双击消息,主窗口必须要有的CS_DBLCLKS 风格。

invoke Shell_NotifyIcon,NIM_DELETE,addr note
mov eax,wParam
.if ax==IDM_RESTORE
invoke ShowWindow,hWnd,SW_RESTORE
.else
invoke DestroyWindow,hWnd
.endif

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

分享到:
评论

相关推荐

    2024-2030全球与中国盐氯化系统市场现状及未来发展趋势.docx

    2024-2030全球与中国盐氯化系统市场现状及未来发展趋势

    基于深度学习的积灰检测识别-图像分类源码+数据集.zip

    详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;

    沈阳药科大学-答辩通用PPT模板我给母校送模板作品.pptx

    PPT模板,答辩PPT模板,毕业答辩,学术汇报,母校模板,我给母校送模板作品,周会汇报,开题答辩,教育主题模板下载。PPT素材下载。

    微信备忘录小程序源码 作业设计demo 计算机专业作业

    微信备忘录小程序源码 作业设计demo 微信备忘录小程序是一种便捷的个人记事应用,它允许用户在微信内快速记录和查看备忘录。以下是对微信备忘录小程序的简要介绍: --- **微信备忘录小程序** 微信备忘录小程序为用户提供了一个简单、直观的记事平台。用户可以通过这个小程序记录日常事务、重要提醒和个人笔记,非常适合忙碌的现代生活节奏。 主要特点包括: 1. **快速记录**:用户可以迅速添加文本、列表或语音备忘录。 2. **定时提醒**:为每个备忘录设置提醒时间,确保不会错过任何重要事项。 3. **个性化分类**:支持自定义分类,便于管理和查找备忘录。 4. **界面友好**:清晰的界面设计,操作简便,无需复杂的学习过程。 5. **数据同步**:通过微信账号登录,实现备忘录的云端同步,方便在不同设备间切换使用。 此外,小程序还具备以下优势: - **隐私保护**:备忘录内容仅对用户本人可见,保障个人隐私。 - **无广告干扰**:提供一个无广告的清爽记事环境。 - **离线存储**:即使在无网络环境下,也能正常使用,记录的内容会在联网后自动同步。 微信备忘录小程序是日

    中国海洋大学-汇报答辩专用PPT模板我给母校送模板作品.pptx

    PPT模板,答辩PPT模板,毕业答辩,学术汇报,母校模板,我给母校送模板作品,周会汇报,开题答辩,教育主题模板下载。PPT素材下载。

    毕业设计:python基于深度学习的交通标志识别系统(源码 + 数据库 + 说明文档) 太多存百度云盘

    毕业设计:python基于深度学习的交通标志识别系统(源码 + 数据库 + 说明文档) 2 开发工具及技术 2 2.1 B/S结构的介绍 2 2.2 PYTHON技术的介绍 2 2.3 HTML技术的介绍 2 2.4 MYSQL数据库的介绍 3 2.5 深度算法的介绍 3 2.6 开发环境的介绍 3 3 需求分析 4 3.1 可行性分析 4 3.2 功能需求分析 4 3.3 非功能需求分析 4 4 总体设计 6 4.1 系统总体结构设计 6 4.2 系统的数据库设计 6 5 系统功能实现 6 5.1 登录及注册 6 5.2 首页展示 6 5.3 个人信息 6 5.4 用户管理 6 5.5 修改密码 6 5.6 图片识别 6 5.7 摄像头识别 6 5.8 天气识别 6 6 系统测试 6 6.1 测试目的 6 6.2 测试内容 6 6.3 测试总结 6

    083ssm-vue汉服文化平台网站.zip(可运行源码+数据库文件+文档)

    本L文主要论述了如何使用JAVA语言开发一个汉服文化平台网站 ,本系统将严格按照软件开发流程进行各个阶段的工作,采用B/S架构,面向对象编程思想进行项目开发。在引言中,作者将论述汉服文化平台网站的当前背景以及系统开发的目的,后续章节将严格按照软件开发流程,对系统进行各个阶段分析设计。 汉服文化平台网站的主要使用者分为管理员和用户,实现功能包括管理员:首页、个人中心、汉服知识管理、服装展示管理、服装类别管理、用户相册管理、论坛交流、系统管理、订单管理,用户:首页、个人中心、用户相册管理、论坛交流、我的收藏管理、订单管理,前台首页;首页、汉服知识、服装展示、用户相册、论坛交流、个人中心、后台管理、购物车、在线客服等功能。由于本网站的功能模块设计比较全面,所以使得整个汉服文化平台网站信息管理的过程得以实现。 本系统的使用可以实现汉服文化平台网站管理的信息化,可以方便管理员进行更加方便快捷的管理,可以提高管理人员的工作效率。 关键词:汉服文化平台网站 JAVA语言;MYSQL数据库;SSM 框架

    HTML5浪漫爱心表白动画在线演示程序

    HTML5浪漫爱心表白动画在线演示程序

    node-v13.12.0-linux-armv7l.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    实验3-关系运算设计(c语言编程).doc

    实验3-关系运算设计(c语言编程).doc

    对京东网站的分析(ppt文档).ppt

    对京东网站的分析(ppt文档).ppt

    C#本科毕业设计基于Unity3D引擎的网络角色扮演游戏设计与实现源代码.zip

    高分设计源码,详情请查看资源内容中使用说明 高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明

    2021数学建模美赛C题代码.zip

    最全的数学建模美赛C题和代码、大量刷题题库、逻辑清晰易于学习

    基于MATLAB的PCA算法人脸识别项目源码+GUI界面+说明文档.zip

    详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;

    上海交通大学-通用PPT模板我给母校送模板作品.pptx

    PPT模板,答辩PPT模板,毕业答辩,学术汇报,母校模板,我给母校送模板作品,周会汇报,开题答辩,教育主题模板下载。PPT素材下载。

    办公自动化(OA)是面向组织的日常运作和管理,员工及管理者使用频率最高的应用系统,极大提高公司的办公效率.zip

    springboot框架 一、Spring Boot基础应用 Spring Boot特征 概念: 约定优于配置,简单来说就是你所期待的配置与约定的配置一致,那么就可以不做任何配置,约定不符合期待时才需要对约定进行替换配置。 特征: 1. SpringBoot Starter:他将常用的依赖分组进行了整合,将其合并到一个依赖中,这样就可以一次性添加到项目的Maven或Gradle构建中。 2,使编码变得简单,SpringBoot采用 JavaConfig的方式对Spring进行配置,并且提供了大量的注解,极大的提高了工作效率,比如@Configuration和@bean注解结合,基于@Configuration完成类扫描,基于@bean注解把返回值注入IOC容器。 3.自动配置:SpringBoot的自动配置特性利用了Spring对条件化配置的支持,合理地推测应用所需的bean并自动化配置他们。 4.使部署变得简单,SpringBoot内置了三种Servlet容器,Tomcat,Jetty,undertow.我们只需要一个Java的运行环境就可以跑SpringBoot的项目了

    市政交通信号工程检验批质量验收记录.doc

    市政交通信号工程检验批质量验收记录.doc

    浙江农林大学-答辩通用PPT模板我给母校送模板作品.pptx

    PPT模板,答辩PPT模板,毕业答辩,学术汇报,母校模板,我给母校送模板作品,周会汇报,开题答辩,教育主题模板下载。PPT素材下载。

    工程监理企业信息化解决方案.doc

    工程监理企业信息化解决方案.doc

    工总承包企业特级资质标准信息化考评表.doc

    工总承包企业特级资质标准信息化考评表.doc

Global site tag (gtag.js) - Google Analytics