系统托盘在我们使用的程序中很普遍,下面我们来看一个很不错的例子,使用Win32 API实现,对理解系统托盘有些帮助。
001 |
#include
<windows.h> |
002 |
#define
IDR_PAUSE 12 |
003 |
#define
IDR_START 13 |
004 |
/* |
005 |
#include
<shellapi.h> |
006 |
#pragma
comment(lib, "shell32.lib") |
007 |
*/ |
008 |
LPCTSTR szAppName
= TEXT("服务程序"); |
009 |
LPCTSTR szWndName
= TEXT("服务程序"); |
010 |
HMENU hmenu;//菜单句柄 |
011 |
012 |
LRESULT CALLBACK
WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAMlParam) |
013 |
{ |
014 |
NOTIFYICONDATA
nid; |
015 |
UINT WM_TASKBARCREATED; |
016 |
POINT
pt;//用于接收鼠标坐标 |
017 |
int xx;//用于接收菜单选项返回值 |
018 |
019 |
//
不要修改TaskbarCreated,这是系统任务栏自定义的消息 |
020 |
WM_TASKBARCREATED
= RegisterWindowMessage(TEXT("TaskbarCreated")); |
021 |
switch (message) |
022 |
{ |
023 |
case WM_CREATE://窗口创建时候的消息. |
024 |
nid.cbSize
= sizeof(nid); |
025 |
nid.hWnd
= hwnd; |
026 |
nid.uID
= 0; |
027 |
nid.uFlags
= NIF_ICON | NIF_MESSAGE | NIF_TIP; |
028 |
nid.uCallbackMessage
= WM_USER; |
029 |
nid.hIcon
= LoadIcon(NULL, IDI_APPLICATION); |
030 |
lstrcpy(nid.szTip,
szAppName); |
031 |
Shell_NotifyIcon(NIM_ADD,
&nid); |
032 |
hmenu=CreatePopupMenu();//生成菜单 |
033 |
AppendMenu(hmenu,MF_STRING,IDR_PAUSE,"暂停服务");//为菜单添加两个选项 |
034 |
AppendMenu(hmenu,MF_STRING,IDR_START,"恢复服务"); |
035 |
break; |
036 |
case WM_USER://连续使用该程序时候的消息. |
037 |
if (lParam
== WM_LBUTTONDOWN) |
038 |
MessageBox(hwnd,
TEXT("Win32
API 实现系统托盘程序,双击托盘可以退出!"),
szAppName, MB_OK); |
039 |
if (lParam
== WM_LBUTTONDBLCLK)//双击托盘的消息,退出. |
040 |
SendMessage(hwnd,
WM_CLOSE, wParam, lParam); |
041 |
if (lParam
== WM_RBUTTONDOWN) |
042 |
{ |
043 |
GetCursorPos(&pt);//取鼠标坐标 |
044 |
::SetForegroundWindow(hwnd);//解决在菜单外单击左键菜单不消失的问题 |
045 |
EnableMenuItem(hmenu,IDR_PAUSE,MF_GRAYED);//让菜单中的某一项变灰 |
046 |
xx=TrackPopupMenu(hmenu,TPM_RETURNCMD,pt.x,pt.y,NULL,hwnd,NULL);//显示菜单并获取选项ID |
047 |
if(xx==IDR_PAUSE)
MessageBox(hwnd, TEXT("111"),
szAppName, MB_OK); |
048 |
if(xx==IDR_START)
MessageBox(hwnd, TEXT("222"),
szAppName, MB_OK); |
049 |
if(xx==0)
PostMessage(hwnd,WM_LBUTTONDOWN,NULL,NULL); |
050 |
//MessageBox(hwnd,
TEXT("右键"), szAppName, MB_OK); |
051 |
} |
052 |
break; |
053 |
case WM_DESTROY://窗口销毁时候的消息. |
054 |
Shell_NotifyIcon(NIM_DELETE,
&nid); |
055 |
PostQuitMessage(0); |
056 |
break; |
057 |
default: |
058 |
/* |
059 |
*
防止当Explorer.exe 崩溃以后,程序在系统系统托盘中的图标就消失 |
060 |
* |
061 |
*
原理:Explorer.exe 重新载入后会重建系统任务栏。当系统任务栏建立的时候会向系统内所有 |
062 |
*
注册接收TaskbarCreated 消息的顶级窗口发送一条消息,我们只需要捕捉这个消息,并重建系 |
063 |
*
统托盘的图标即可。 |
064 |
*/ |
065 |
if (message
== WM_TASKBARCREATED) |
066 |
SendMessage(hwnd,
WM_CREATE, wParam, lParam); |
067 |
break; |
068 |
} |
069 |
return DefWindowProc(hwnd,
message, wParam, lParam); |
070 |
} |
071 |
072 |
int WINAPI
WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, |
073 |
LPSTR szCmdLine, int iCmdShow) |
074 |
{ |
075 |
HWND hwnd; |
076 |
MSG
msg; |
077 |
WNDCLASS
wndclass; |
078 |
079 |
HWND handle
= FindWindow(NULL, szWndName); |
080 |
if (handle
!= NULL) |
081 |
{ |
082 |
MessageBox(NULL,
TEXT("Application
is already running"),
szAppName, MB_ICONERROR); |
083 |
return 0; |
084 |
} |
085 |
086 |
wndclass.style
= CS_HREDRAW | CS_VREDRAW; |
087 |
wndclass.lpfnWndProc
= WndProc; |
088 |
wndclass.cbClsExtra
= 0; |
089 |
wndclass.cbWndExtra
= 0; |
090 |
wndclass.hInstance
= hInstance; |
091 |
wndclass.hIcon
= LoadIcon(NULL, IDI_APPLICATION); |
092 |
wndclass.hCursor
= LoadCursor(NULL, IDC_ARROW); |
093 |
wndclass.hbrBackground
= (HBRUSH)GetStockObject(WHITE_BRUSH); |
094 |
wndclass.lpszMenuName
= NULL; |
095 |
wndclass.lpszClassName
= szAppName; |
096 |
097 |
if (!RegisterClass(&wndclass)) |
098 |
{ |
099 |
MessageBox(NULL,
TEXT("This
program requires Windows NT!"),
szAppName, MB_ICONERROR); |
100 |
return 0; |
101 |
} |
102 |
103 |
//
此处使用WS_EX_TOOLWINDOW 属性来隐藏显示在任务栏上的窗口程序按钮 |
104 |
hwnd
= CreateWindowEx(WS_EX_TOOLWINDOW, |
105 |
szAppName,
szWndName, |
106 |
WS_POPUP, |
107 |
CW_USEDEFAULT, |
108 |
CW_USEDEFAULT, |
109 |
CW_USEDEFAULT, |
110 |
CW_USEDEFAULT, |
111 |
NULL,
NULL, hInstance, NULL); |
112 |
113 |
ShowWindow(hwnd,
iCmdShow); |
114 |
UpdateWindow(hwnd); |
115 |
116 |
while (GetMessage(&msg,
NULL, 0, 0)) |
117 |
{ |
118 |
TranslateMessage(&msg); |
119 |
DispatchMessage(&msg); |
120 |
} |
121 |
return msg.wParam; |
122 |
} |
本文介绍了一个使用Win32API实现系统托盘程序的例子,详细展示了如何通过注册消息、创建菜单等步骤来完成系统托盘图标的显示与交互。包括了创建窗口、响应消息、显示上下文菜单等功能。
1724

被折叠的 条评论
为什么被折叠?



