;运行效果
;win32汇编环境,窗口程序中创建托盘示例二
;像QQ来新消息时一样,让托盘图标交替显示,需要加个定时器,准备2个不同的图标,然后在需要的时机,启动定时器,让图标交替显示。
;直接抄进RadAsm可编译运行。重要部分加备注。
;下面为asm文件
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.386
.model flat,stdcall
option casemap:none
include windows.inc
include user32.inc
include kernel32.inc
include shell32.inc ;添加必需的头文件
includelib user32.lib
includelib kernel32.lib
includelib shell32.lib ;添加必需的库文件
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
WinMain proto :DWORD,:DWORD,:DWORD,:DWORD
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;Equ 等值定义
MAINDIALOG equ 1
ICO_MAIN equ 1000 ;图标
WM_SHELLNOTIFY equ WM_USER + 9 ;自定义私人消息,用来处理托盘图标方面的反应
IDI_TRAY equ 2
IDM_RESTORE equ 100
IDM_EXIT equ 101
ID_TIMER1 equ 201
ButtonID equ 1002
.DATA
ClassName db "SimpleWinClass",0
AppName db "窗口程序的模版",0
szSTClassName db "static",0
szSTCaption db "点击最化小按钮则会缩为右下角的托盘",0
szButtonClassName db "button",0
szButtonTitle db "让托盘图标交替显示",0
szFileIocn01 db "Main01.ico",0 ;图标文件名,在当前文件夹下
szFileIocn02 db "Main02.ico",0
szAppName db "我在这里",0 ;当鼠标在其上面时,显示的提示
szRestoreString db "恢复窗口",0
szExitString db "退出程序",0
.DATA?
hInstance HINSTANCE ?
CommandLine LPSTR ?
Snote NOTIFYICONDATA <> ;定义包含系统需要在通知区域中显示通知的信息的结构
hPopupMenu dd ?
hIco01 dd ?
hIco02 dd ?
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.CODE
start:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke GetCommandLine
mov CommandLine,eax
invoke WinMain, hInstance,NULL,CommandLine, 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
mov wc.lpfnWndProc, OFFSET WndProc
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,NULL
push hInstance
pop wc.hInstance
mov wc.hbrBackground,COLOR_WINDOW
mov wc.lpszMenuName,NULL
mov wc.lpszClassName,OFFSET ClassName
invoke LoadImage,hInstance,addr szFileIocn01,IMAGE_ICON,0,0,LR_LOADFROMFILE
mov wc.hIcon,eax
mov wc.hIconSm,eax
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax
invoke RegisterClassEx, addr wc
invoke CreateWindowEx,NULL, ADDR ClassName,ADDR AppName,WS_OVERLAPPEDWINDOW,100,100,400,200, NULL,NULL,hInst, NULL
mov hwnd,eax
invoke ShowWindow, hwnd,CmdShow
invoke UpdateWindow, hwnd
.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 CreateWindowEx,NULL,ADDR szSTClassName,ADDR szSTCaption, WS_CHILD + WS_VISIBLE,60, 40, 300, 20,hWnd,NULL,NULL,NULL
invoke CreateWindowEx,NULL,ADDR szButtonClassName,ADDR szButtonTitle, WS_TABSTOP OR WS_VISIBLE OR WS_CHILD OR BS_DEFPUSHBUTTON ,100,90,180,25,hWnd,ButtonID,NULL,NULL ;创建按钮控件
invoke CreatePopupMenu ;创建弹出式菜单
mov hPopupMenu,eax
invoke AppendMenu,hPopupMenu,MF_STRING,IDM_RESTORE,addr szRestoreString ;给创建的弹出式菜单增加项目
invoke AppendMenu,hPopupMenu,MF_STRING,IDM_EXIT,addr szExitString
invoke LoadImage,hInstance,addr szFileIocn01,IMAGE_ICON,0,0,LR_LOADFROMFILE ;加载图标
mov hIco01,eax
invoke LoadImage,hInstance,addr szFileIocn02,IMAGE_ICON,0,0,LR_LOADFROMFILE
mov hIco02,eax
mov Snote.cbSize,sizeof NOTIFYICONDATA ;NOTIFYICONDATA此结构的大小
push hWnd
pop Snote.hwnd ;把相关联的主窗口句柄给这个结构变量
mov Snote.uID,IDI_TRAY ;任务栏图标的应用程序定义标识符,就是其ID,这个用来区分你点了哪个不同的托盘图标
mov Snote.uFlags,NIF_ICON+NIF_MESSAGE+NIF_TIP ;指出在这个NOTIFYICONDATA结构中,哪些成员有效。这里指uCallbackMessage成员,hIcon成员,szTip成员有效
mov Snote.uCallbackMessage,WM_SHELLNOTIFY ;告诉NOTIFYICONDATA结构,当有消息在系统图标时,去找 WM_SHELLNOTIFY 这个私人消息处理
push hIco01
pop Snote.hIcon ;把图标给这个NOTIFYICONDATA结构
invoke lstrcpy,addr Snote.szTip,addr szAppName ;当鼠标停留在托盘图标上面时,显示的字符串
invoke Shell_NotifyIcon,NIM_ADD,addr Snote ;调用Shell_NotifyIcon函数,把前面塞满内容的NOTIFYICONDATA结构当作参数给它.并告诉电脑,将图标添加消息发送到右下角的任务栏的状态区域
.elseif uMsg == WM_SIZE ;WM_SIZE消息是当窗口大小或位置发生变化时捕获的消息
.if wParam == SIZE_MINIMIZED ;当窗口最小化时,则
invoke ShowWindow,hWnd,SW_HIDE ;把主窗口隐藏
.endif
.elseif uMsg == WM_SHELLNOTIFY ;处理自定义消息
.if wParam == IDI_TRAY ;如果是这个程序的托盘图标,则
.if lParam == WM_RBUTTONDOWN ;如果鼠标单击右键,则
invoke GetCursorPos,addr pt ;得到当前鼠标的坐标并将X值及Y值给坐标结构 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 ;发送WM_COMMAND消息,即后面的命令消息给主窗口,其wParam值是IDM_RESTORE,其lParam值是0
.endif
.endif
.elseif uMsg == WM_COMMAND
mov eax,wParam
.if ax == IDM_RESTORE ;如果是恢复主窗口,则恢复
invoke ShowWindow,hWnd,SW_RESTORE
invoke SetForegroundWindow ,hWnd ;激活并让窗口显示在所在窗口前面
.elseif ax == IDM_EXIT
invoke Shell_NotifyIcon,NIM_DELETE,addr Snote ;删除图标
invoke DestroyWindow,hWnd
.elseif ax == ButtonID ;这是偷懒写法,如果控件多,则需分清各自的wParam与lParam值,不清楚的可以看入门教程里面相关的解释
invoke SetTimer,hWnd,ID_TIMER1,1000,NULL ;设置定时器,1000即1秒
.endif
.elseif uMsg == WM_TIMER ;处理定时器消息
mov eax,wParam
.if eax == ID_TIMER1
mov ebx,Snote.hIcon
.if ebx == hIco01
push hIco02
pop Snote.hIcon
invoke Shell_NotifyIcon,NIM_MODIFY,addr Snote ;修改托盘图标
.else
push hIco01
pop Snote.hIcon
invoke Shell_NotifyIcon,NIM_MODIFY,addr Snote ;修改托盘图标
.endif
.endif
.elseif uMsg == WM_DESTROY
invoke KillTimer,hWnd,ID_TIMER1 ;离开时记得清除定时器
invoke Shell_NotifyIcon,NIM_DELETE,addr Snote ;删除托盘图标
invoke DestroyMenu,hPopupMenu ;退出时清除创建的菜单
invoke PostQuitMessage,NULL
.else
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.endif
xor eax,eax
ret
WndProc endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
end start