最近有个VC程序急切希望具有windows 通知区域图标的功能,从CSDN上参考了几篇文章,但改的效果并不是很理想,于是自己开始思考此问题,并找到源自MS的例子源码。
在MSDN中查找Shell_NotifyIcon,可以看到有个例子连接http://technet.microsoft.com/zh-cn/office/dd940367,但该页面上提示的代码下载链接已不能使用,于是考虑下载该页面中提到的windows 7 SDK。后确定了下载页面为:http://www.microsoft.com/en-us/download/details.aspx?id=8442,(Microsoft Windows SDK for Windows 7 and .NET Framework 4 (ISO)),下载后可单独安装其实例程序,然后可得到NotificationIcon示例程序。现对该过程做简单介绍。
- 创建SystemTray图标
BOOL AddNotificationIcon(HWND hwnd)
{
NOTIFYICONDATA nid = {sizeof(nid)};
nid.hWnd = hwnd;
// add the icon, setting the icon, tooltip, and callback message.
// the icon will be identified with the GUID
nid.uFlags = NIF_ICON | NIF_TIP | NIF_MESSAGE | NIF_SHOWTIP | NIF_GUID;
nid.guidItem = __uuidof(PrinterIcon);
nid.uCallbackMessage = WMAPP_NOTIFYCALLBACK;
LoadIconMetric(g_hInst, MAKEINTRESOURCE(IDI_NOTIFICATIONICON), LIM_SMALL, &nid.hIcon);
LoadString(g_hInst, IDS_TOOLTIP, nid.szTip, ARRAYSIZE(nid.szTip));
Shell_NotifyIcon(NIM_ADD, &nid);
// NOTIFYICON_VERSION_4 is prefered
nid.uVersion = NOTIFYICON_VERSION_4;
return Shell_NotifyIcon(NIM_SETVERSION, &nid);
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HWND s_hwndFlyout = NULL;
static BOOL s_fCanShowFlyout = TRUE;
switch (message)
{
case WM_CREATE:
// add the notification icon
if (!AddNotificationIcon(hwnd))
{
MessageBox(hwnd,
L"Please read the ReadMe.txt file for troubleshooting",
L"Error adding icon", MB_OK);
return -1;
}
break;
...
}
在主窗口的WM_CREATE消息中,创建了通知区域图标。
- 删除SystemTray图标
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HWND s_hwndFlyout = NULL;
static BOOL s_fCanShowFlyout = TRUE;
switch (message)
{
case WM_DESTROY:
DeleteNotificationIcon();
PostQuitMessage(0);
break;
...
}
}
BOOL DeleteNotificationIcon()
{
NOTIFYICONDATA nid = {sizeof(nid)};
nid.uFlags = NIF_GUID;
nid.guidItem = __uuidof(PrinterIcon);
return Shell_NotifyIcon(NIM_DELETE, &nid);
}
- 通知区域鼠标右键响应
通知区域的消息是通过添加图标是由应用程序定义的自定义消息传回。
case WMAPP_NOTIFYCALLBACK:
switch (LOWORD(lParam))
{
case NIN_SELECT:
// for NOTIFYICON_VERSION_4 clients, NIN_SELECT is prerable to listening to mouse clicks and key presses
// directly.
if (IsWindowVisible(s_hwndFlyout))
{
HideFlyout(hwnd, s_hwndFlyout);
s_hwndFlyout = NULL;
s_fCanShowFlyout = FALSE;
}
else if (s_fCanShowFlyout)
{
s_hwndFlyout = ShowFlyout(hwnd);
}
break;
case NIN_BALLOONTIMEOUT:
RestoreTooltip();
break;
case NIN_BALLOONUSERCLICK:
RestoreTooltip();
// placeholder for the user clicking on the balloon.
MessageBox(hwnd, L"The user clicked on the balloon.", L"User click", MB_OK);
break;
case WM_CONTEXTMENU:
{
POINT const pt = { LOWORD(wParam), HIWORD(wParam) };
ShowContextMenu(hwnd, pt);
}
break;
}
break;
...
void ShowContextMenu(HWND hwnd, POINT pt)
{
HMENU hMenu = LoadMenu(g_hInst, MAKEINTRESOURCE(IDC_CONTEXTMENU));
if (hMenu)
{
HMENU hSubMenu = GetSubMenu(hMenu, 0);
if (hSubMenu)
{
// our window must be foreground before calling TrackPopupMenu or the menu will not disappear when the user clicks away
SetForegroundWindow(hwnd);
// respect menu drop alignment
UINT uFlags = TPM_RIGHTBUTTON;
if (GetSystemMetrics(SM_MENUDROPALIGNMENT) != 0)
{
uFlags |= TPM_RIGHTALIGN;
}
else
{
uFlags |= TPM_LEFTALIGN;
}
TrackPopupMenuEx(hSubMenu, uFlags, pt.x, pt.y, hwnd, NULL);
}
DestroyMenu(hMenu);
}
}
- 在图标区域显示出弹出通知
BOOL ShowLowInkBalloon()
{
// Display a low ink balloon message. This is a warning, so show the appropriate system icon.
NOTIFYICONDATA nid = {sizeof(nid)};
nid.uFlags = NIF_INFO | NIF_GUID;
nid.guidItem = __uuidof(PrinterIcon);
// respect quiet time since this balloon did not come from a direct user action.
nid.dwInfoFlags = NIIF_WARNING | NIIF_RESPECT_QUIET_TIME;
LoadString(g_hInst, IDS_LOWINK_TITLE, nid.szInfoTitle, ARRAYSIZE(nid.szInfoTitle));
LoadString(g_hInst, IDS_LOWINK_TEXT, nid.szInfo, ARRAYSIZE(nid.szInfo));
return Shell_NotifyIcon(NIM_MODIFY, &nid);
}
BOOL ShowNoInkBalloon()
{
// Display an out of ink balloon message. This is a error, so show the appropriate system icon.
NOTIFYICONDATA nid = {sizeof(nid)};
nid.uFlags = NIF_INFO | NIF_GUID;
nid.guidItem = __uuidof(PrinterIcon);
nid.dwInfoFlags = NIIF_ERROR;
LoadString(g_hInst, IDS_NOINK_TITLE, nid.szInfoTitle, ARRAYSIZE(nid.szInfoTitle));
LoadString(g_hInst, IDS_NOINK_TEXT, nid.szInfo, ARRAYSIZE(nid.szInfo));
return Shell_NotifyIcon(NIM_MODIFY, &nid);
}
BOOL ShowPrintJobBalloon()
{
// Display a balloon message for a print job with a custom icon
NOTIFYICONDATA nid = {sizeof(nid)};
nid.uFlags = NIF_INFO | NIF_GUID;
nid.guidItem = __uuidof(PrinterIcon);
nid.dwInfoFlags = NIIF_USER | NIIF_LARGE_ICON;
LoadString(g_hInst, IDS_PRINTJOB_TITLE, nid.szInfoTitle, ARRAYSIZE(nid.szInfoTitle));
LoadString(g_hInst, IDS_PRINTJOB_TEXT, nid.szInfo, ARRAYSIZE(nid.szInfo));
LoadIconMetric(g_hInst, MAKEINTRESOURCE(IDI_NOTIFICATIONICON), LIM_LARGE, &nid.hBalloonIcon);
return Shell_NotifyIcon(NIM_MODIFY, &nid);
}