托盘图标使用函数 Shell_NotifyIcon 创建、修改和删除,参数主要使用 NOTIFYICONDATA 结构。

任务栏启动时会给所有顶层窗口发送 TaskbarCreated 消息,由于不同系统消息标识不一样,所以需要使用 RegisterWindowMessage 向系统获取消息标识。

程序在VS2015 Win32编译通过,XP SP3测试通过。Win10气泡无反应,或者我该用 NOTIFYICON_VERSION_4 ?希望哪位能告知一二……

最后发现Win10需要打开操作中心,并且允许应用通知,Win10已把气泡消息整合到里面去了。可怜偶调试了三天……

下面是简介和本人被坑过的地方,其他可查看VS自带帮助。

一、定义:(概览\(^o^)/)

BOOL Shell_NotifyIcon(
_In_ DWORD dwMessage,
_In_ PNOTIFYICONDATA lpdata
);

其中 dwMessage 常用的选项如下:(其他略\(^o^)/)

NIM_ADD

 添加托盘图标。

NIM_MODIFY

 修改图标,也可弹出气泡图标。

NIM_DELETE

删除图标,应在整个程序结束时也调用一次。

第二个参数为指向 NOTIFYICONDATA 的指针,常用参数如下:(其他再略\(^o^)/)

 cbSize 

 NOTIFYICONDATA 占用的空间大小,要注意一定要先判断 Shell32.dll 版本号(除非你不想用于多个版本的系统),来对其赋值,具体见例程。

 hWnd 

窗口句柄。

 uID 

创建的图标标识,与 hWnd 组合定位托盘图标。

 hIcon 

图标句柄,一般使用 LoadIcon(hInst, MAKEINTRESOURCE(IDI_WIN32TEST)) 赋予。

 uVersion 

版本,Win2000后一般使用 NOTIFYICON_VERSION 保证兼容性,注意它与 uTimeout 共享内存(union), NOTIFYICON_VERSION_4 适用于Vista以后的系统。

 uTimeout 

气泡自动消失的时间,Vista无效(VC2015帮助原文:【This member is deprecated as of Windows Vista. Notification display times are now based on system accessibility settings.】,我以前在Win7+VS2008测试时有效,所以不确定Win7以上是否无效)

 uCallbackMessage 

托盘图标
响应消息

当 uVersion = NOTIFYICON_VERSION :wParam为图标 uID lParam为具体事件(如 WM_LBUTTONDOWN )。
当 uVersion = NOTIFYICON_VERSION_4 : HIWORD(lParam) 为图标 uID (16位), LOWORD(lParam) 为具体事件, GET_X_LPARAM(wParam) 、 GET_Y_LPARAM(wParam) 为事件响应时的坐标。
 uFlags 

标识,指出有效的成员并且指出托盘图标显示的方式, NIF_MESSAGE 使 uCallbackMessage 有效, NIF_ICON 使 hIcon 有效, NIF_TIP 使 szTip 有效, NIF_INFO 使 szInfo 、 szInfoTitle 、 dwInfoFlags 、 uTimeout 有效。

szTip

 鼠标指向托盘图标时显示的提示消息,注意长度。

szInfo

 气泡提示内容,注意长度。

szInfoTitle

 气泡标题,为空时 dwInfoFlags 无效,注意长度。

dwInfoFlags

 气泡图标,NIIF_NONE 表示无图标,NIIF_INFO 表示【提示】,NIIF_WARNING 表示【警告】,NIIF_ERROR 表示【错误】。(其他略\(^o^)/)

二、例程:(还是概览\(^o^)/)

头文件

class CTrayIcon
{
public:
CTrayIcon();
~CTrayIcon(); BOOL CreateTray(HWND, HICON, UINT, LPCTSTR = _T(""));
BOOL ChangeTray(LPCTSTR, UINT = 3000);
BOOL DeleteTray(); private:
ULONGLONG GetVersion(LPCTSTR);
DWORD GetSize_NotifyIconData(); NOTIFYICONDATA m_Notify;
};

获取cbsize,这里要特别注意,具体可参考《关于NOTIFYICONDATA的一些新特性》和《正确使用DllGetVersion》:

ULONGLONG CTrayIcon::GetVersion(LPCTSTR lpszDllName)
{
HINSTANCE hinstDll;
ULONGLONG dwVersion = 0; hinstDll = LoadLibrary(lpszDllName); if (hinstDll)
{
DLLGETVERSIONPROC pDllGetVersion;
pDllGetVersion = (DLLGETVERSIONPROC)GetProcAddress(hinstDll, "DllGetVersion"); if (pDllGetVersion)
{
DLLVERSIONINFO dvi;
HRESULT hr; ZeroMemory(&dvi, sizeof(dvi));
dvi.cbSize = sizeof(dvi); hr = (*pDllGetVersion)(&dvi); if (SUCCEEDED(hr))
{
dwVersion = MAKEDLLVERULL(dvi.dwMajorVersion, dvi.dwMinorVersion,
dvi.dwBuildNumber, dvi.dwPlatformID);
}
}
FreeLibrary(hinstDll);
}
return dwVersion;
} DWORD CTrayIcon::GetSize_NotifyIconData()
{
TCHAR lpszDllName[128]; GetWindowsDirectory(lpszDllName, _TRUNCATE);
_tcsncat_s(lpszDllName, _T("\\System32\\Shell32.dll"), _TRUNCATE); ULONGLONG NIDdllVer = GetVersion(lpszDllName); // before windows 2000
if (NIDdllVer < MAKEDLLVERULL(5, 0, 0, 0)) {
return NOTIFYICONDATA_V1_SIZE;
}
// Windows 2000
else if (NIDdllVer < MAKEDLLVERULL(6, 0, 0, 0)) {
return NOTIFYICONDATA_V2_SIZE;
}
// Windows XP or 2003
else if (NIDdllVer < MAKEDLLVERULL(6, 0, 6000, 0)) {
return NOTIFYICONDATA_V3_SIZE;
}
// Windows Vista and later
else {
return sizeof(NOTIFYICONDATA);
}
}

创建:

BOOL CTrayIcon::CreateTray(HWND hWnd, HICON hIcon, UINT uCallbackMessage, LPCTSTR szTitle)
{
m_Notify.cbSize = GetSize_NotifyIconData();
m_Notify.hIcon = hIcon;
m_Notify.hWnd = hWnd;
m_Notify.uCallbackMessage = uCallbackMessage;
m_Notify.uVersion = NOTIFYICON_VERSION;
m_Notify.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
m_Notify.uID = 1; _tcscpy_s(m_Notify.szTip, szTitle); return Shell_NotifyIcon(NIM_ADD, &m_Notify);
}

气泡:

BOOL CTrayIcon::ChangeTray(LPCTSTR msg, UINT uTimeout)
{
m_Notify.uFlags = NIF_INFO;
m_Notify.dwInfoFlags = NIIF_NONE;
// m_Notify.uTimeout = uTimeout; _tcscpy_s(m_Notify.szInfo, msg); return Shell_NotifyIcon(NIM_MODIFY, &m_Notify);
}

删除:

BOOL CTrayIcon::DeleteTray() {
return Shell_NotifyIcon(NIM_DELETE, &m_Notify);
}

定义托盘图标响应消息:

#define WM_ICON_NOTIFY WM_USER+1001

注册 TaskbarCreated 消息:

const UINT WM_TASKBARCREATED = ::RegisterWindowMessage(_T("TaskbarCreated"));

消息处理&调用(Win32):

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
// Restore the tray-icon after the explorer's recreation
if (message == WM_TASKBARCREATED) {
if (!IsWindowVisible(hWnd))
trayIcon.CreateTray(hWnd, LoadIcon(hInst, MAKEINTRESOURCE(IDI_WIN32TEST)), WM_ICON_NOTIFY, szTitle);
return DefWindowProc(hWnd, message, wParam, lParam);
} switch (message)
{
case WM_SIZE:
switch (wParam)
{
case SIZE_RESTORED: // Restore the window and delete the tray-icon
ShowWindow(hWnd, SW_SHOW);
trayIcon.DeleteTray();
break;
case SIZE_MINIMIZED: // Hide the window and create the tray-icon
ShowWindow(hWnd, SW_HIDE);
trayIcon.CreateTray(hWnd, LoadIcon(hInst, MAKEINTRESOURCE(IDI_WIN32TEST)), WM_ICON_NOTIFY, szTitle);
break;
default:
break;
}
return DefWindowProc(hWnd, message, wParam, lParam); case WM_COMMAND:
// ...
break;
case WM_PAINT:
// ...
break;
case WM_ICON_NOTIFY:
switch (lParam)
{
case WM_LBUTTONDOWN:
SendMessage(hWnd, WM_SYSCOMMAND, SC_RESTORE, lParam);
SetForegroundWindow(hWnd);
break;
default:
break;
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}

托盘图标、气泡以及任务栏崩溃后的自动添加——Shell_NotifyIcon的更多相关文章

  1. Excel小tips - 如何设置表格输入数字后末尾自动添加%

    选中一列——鼠标右键——设置单元格格式——数字——自定义——0% 按照以上操作完成后,点击确定,就大功告成了.

  2. notepad++崩溃后文件内容变为NUL的解决方法

    毫无疑问,notepad++是一款非常优秀的文本编辑器,但是notepad++有时候会崩溃,之后文件内容就会全部变成NUL 当你打文件看到自己辛辛苦苦的成果全都变成NUL是不是有想哭的感觉?" ...

  3. [转]使用 Minidumps 和 Visual Studio .NET 进行崩溃后调试

    本文关键字:Minidumps, Windows, SEH, VisualC, .NET 摘要 本文讲述了 minidumps 是怎样工作的.当你的程序崩溃的时候应该如何生成它们.以及如何在 Visu ...

  4. 结合程序崩溃后的core文件分析bug

    引言     在<I/O的效率比较>中,我们在修改图1程序的BUF_SIZE为8388608时,运行程序出现崩溃,如下图1:          图1. 段错误     一般而言,导致程序段 ...

  5. Flutter - TabBar导航栏切换后,状态丢失

    上一篇讲到了 Flutter - BottomNavigationBar底部导航栏切换后,状态丢失 里面提到了TabBar,这儿专门再写一下吧,具体怎么操作,来不让TabBar的状态丢失.毕竟大家99 ...

  6. Windows系统崩溃后快速恢复Oracle数据库的妙招

    Windows系统崩溃后快速恢复Oracle数据库,以下是操作步骤 假设oracle数据安装在d:\\oracle文件夹中,数据库名称orcl 1>将崩溃的数据库安装目录"d:\\or ...

  7. Go -- 通过GOTRACEBACK生成程序崩溃后core文件的方法(gcore gdb)

    写一个错误的c程序   package dlsym import "testing" func Test_intercept(t *testing.T) { Intercept(& ...

  8. 程序异常崩溃后用windbg辅助调试解决的经验 以及 堆栈问题调试经验

    1,程序异常崩溃后用windbg辅助调试解决的经验  状况:我的程序调用别人的库做 文件写入工作. 在这一过程中出现异常,程序崩溃. 经反复检查,认为自己的程序没有错,但无法判断在别人库里哪里有错. ...

  9. android双进程守护,让程序崩溃后一定可以重启

    由于我们做的是机器人上的软件,而机器人是24小时不间断服务的,这就要求我们的软件不能退出到系统桌面.当然最好是能够做到程序能够不卡顿,不崩溃,自己不退出.由于我们引用了很多第三方的开发包,也不能保证他 ...

随机推荐

  1. 过多if-else分支的优化

    http://www.udpwork.com/item/9294.html 我想谈一谈这个话题是因为我的上一篇博客在ITEye上有一些朋友回复,说if-else过多的分支可以使用switch或者责任链 ...

  2. 用extern关键字使程序更加清晰

    一.基础研究 之前基于tcc.tlink实现一个新的编译连接工具cc.exe,用到的文件有cs.lib.c0s.obj.main.obj,其中main.obj是我们自己加入的文件,它可以实现开始显示彩 ...

  3. 实现一个基于tcc/tlink的简单的编译链接工具

    一.基础研究 在这里我们需要提供一套新的c语言开发工具cc,它支持的c程序不是从main开始运行而是从CMain开始运行. 书上已经对该工具程序进行了需求分析:(1)要在屏幕中间显示彩色的字符串:(2 ...

  4. oracle中的日期加减法

    --加法 ) from dual; --加1年 ) from dual; --加1月 ,'yyyy-mm-dd HH24:MI:SS') from dual; --加1星期 ,'yyyy-mm-dd ...

  5. Android AlarmManager实现不间断轮询服务

    在消息的获取上是选择 轮询还是推送得根据实际的业务需要来技术选型,例如对消息实时性比较高的需求,比如微博新通知或新闻等那就最好是用推送了.但如果只是一般的消息检测比如 更新检查,可能是半个小时或一个小 ...

  6. 【转】Android 带checkbox的listView 实现多选,全选,反选 -- 不错

    原文网址:http://blog.csdn.net/onlyonecoder/article/details/8687811 Demo地址(0分资源):http://download.csdn.net ...

  7. 【模拟】HDU 5762 Teacher Bo

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5762 题目大意: 给n个点,坐标范围0~m(n,m<=105),求是否存在2个点对满足哈夫曼距 ...

  8. CSU 1111 有三户人家共拥有一座花园,每户人家的太太均需帮忙整理花园。A 太太工作了5 天,B 太太则工作了4 天,才将花园整理完毕。C 太太因为正身怀六甲无法加入她们的行动,所以就打算出90元钱

    题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=82974#problem/D 解题思路:本题的意思就是三位均出90,然后AB按做 ...

  9. 铁通、长宽网络支付时“签名失败”问题分析及解决方案  [88222001]验证签名异常:FAIL[20131101100002-142]

    原文地址:http://bbs.tenpay.com/forum.php?mod=viewthread&tid=13723&highlight=%CC%FA%CD%A8 如果你的是铁通 ...

  10. C#经典系列-跨语言

    VS是个大平台,当C#不好实现的时候,可以想想是否可以引用下其他语言下面的方法,或许你有大收获~ 如何判断“a”是不是数字类型. 1.在C#中我们可能会用TryParse来判断当前的”a“是否为整数. ...