windows系统托盘程序(转)

更新时间:2023-05-24 05:12:32 阅读: 评论:0

windows系统托盘程序(转)
系统托盘应⽤作为⼀种极具吸引⼒的UI深受⼴⼤⽤户的喜爱。使⽤系统托盘UI的Windows应⽤程序数不胜数,⽐如"⾦⼭词霸"、"Winamp"、"RealPlayer"等等。那么如何编写⾃⼰的托盘应⽤呢?本⽂是系列⽂章中的第⼀篇,这些⽂章将⽐较系统地描述托盘应⽤的编程。并创建⾃⼰的C++类来增强系统托盘应⽤的特性。读完这些⽂章,再参照例⼦,相信读者能轻松⾃如地在⾃⼰的程序中应⽤系统托盘。
解除合同协议
⼤家知道,MFC框架没有提供任何现成的类应⽤于系统托盘UI,那么如何将表⽰应⽤程序的图标添加到任务栏中呢?⽅法很简单,只⽤到⼀个API函数,它就是Shell_NotifyIcon。这个函数本⾝也相当容易理解和使⽤。看看它的原型就知道了:
1.BOOL Shell_NotifyIcon(
2.    DWORD dwMessage,
3.    PNOTIFYICONDATApnid
4.);
第⼀个参数dwMessage类型为DWORD,表⽰要进⾏的动作,它可以是下⾯的值之⼀:
1.NIM_ADD:添加⼀个图标到任务栏。
2.NIM_MODIFY:修改状态栏区域的图标。
3.NIM_DELETE:删除状态栏区域的图标。
4.NIM_SETFOCUS:将焦点返回到任务栏通知区域。当完成⽤户界⾯操作时,任务栏图标必须⽤此消息。例如,如果任务栏图标正
5.                显⽰上下⽂菜单,但⽤户按下"ESCAPE"键取消操作,这时就必须⽤此消息将焦点返回到任务栏通知区域。
6.NIM_SETVERSION:指⽰任务栏按照相应的动态库版本⼯作。
第⼆个参数pnid是NOTIFYICONDATA结构的地址,其内容视dwMessage的值⽽定。这个结构在SHELLAPI.H⽂件中定义如下:
02.  DWORDcbSize;          // 结构⼤⼩(sizeof struct),必须设置
03.  HWNDhWnd;            // 发送通知消息的窗⼝句柄
04.  UINT uID;              //  图标ID ( 由回调函数的WPARAM指定)
05.  UINTuFlags;
06.  UINT uCallbackMessage;    // 消息被发送到此窗⼝过程
07.  HICONhIcon;            // 图标句柄
08.  CHARszTip[64];          // 提⽰⽂本
09.} NOTIFYICONDATA;
10.uFlags的值:
11.#define NIF_MESSAGE0x1  // 表⽰uCallbackMessage 有效
12.#define NIF_ICON    0x2  // 表⽰hIcon 有效
13.#defineNIF_TIP    0x4  // 表⽰szTip 有效
有关Shell_NotifyIcon函数的详细使⽤细节请参考MSDN。
NOTIFYICONDATA结构中的 hWnd 是"拥有" 图标的窗⼝句柄。uID可以是任何标⽰托盘图标的ID(如果有多个图标),⼀般使⽤资
源ID。HIcon可以是任何图标的句柄,包括预定义的系统图标,如IDI_HAND、IDI_QUESTION、IDI_EXCLAMATION、或者Windows的徽标IDI_WINLOGO。
图标的显⽰并不难,关键是事件的处理。当⽤户将⿏标移到图标上或者在图标上单击⿏标时,为了得到通知消息,你可以将⾃⼰的消息ID赋给uCallbackMessage,并设置NIF_MESSAGE标志。当⽤户在图标上移动或单击⿏标时,Windows将⽤hWnd指定的窗⼝句柄调⽤你建⽴的窗⼝过程;消息ID在uCallbackMessage中指定,uID的值即为wParam,lParam为⿏标事件,如WM_LBUTTONDOWN等。
尽管Shell_NotifyIcon函数简单实⽤。但它毕竟是个Win32 API,为此我将它封装在了⼀个C++类中,这个类叫做CTrayIcon,有了它,托盘编程会更加轻松⾃如,因为它隐藏了NOTIFYICONDATA、消息代码、标志以及所有那些你必须要看MSDN才能搞掂的繁琐细
节。CTrayIcon的定义以及实现细节请下载源代码参考。CTrayIcon为程序员提供了⼀个更加友好的托盘编程接⼝,它除了
对Shell_NotifyIcon函数进⾏打包之外,它还是⼀个迷你框架呢!之所以这么说,是因为按照Windows系统应⽤软件界⾯指南所提倡的原则(这个指南可以在MSDN中找到),这个类增强了托盘图标的⽤户界⾯⾏为。以下便是CTrayIcon最终实现的UI特性:
1、托盘图标应该有信息提⽰,也就是ToolTips。
2、单击右键应该弹出上下⽂菜单,这个菜单中应包含打开属性页的命令或者打开与图标相关的其它窗⼝的命令。
3、单击左键应该显⽰进⼀步的信息或者控制图标所代表的对象,例如,当左键单击声⾳图标时进⾏⾳量控制。如果没有进⼀步的信息或控制,则不要有任何动作。
口吃是什么原因
CTrayIcon对上⾯的特性进⾏了全⾯的封装。为了⽰范CTrayIcon的⼯作原理,本⽂提供⼀个例⼦程序TrayTest1,图⼀是运⾏程序后显⽰的⼀个对话框:
/Public/Uploads/images/39/1330592662.jpg
图⼀ TrayTest1运⾏后显⽰的对话框
当把图标安装到系统托盘之后,如果双击托盘图标,程序会弹出⼀个消息列表窗⼝,只要你的⿏标在
托盘图标上移动或点击(⽆论是左右键的单击或双击),产⽣的消息都会显⽰在这个窗⼝⾥,如图⼆:
/Public/Uploads/images/92/1330592663.jpg
图⼆消息显⽰窗⼝
当⿏标光标移到托盘图标上时,在图标附近会显⽰提⽰信息,如图三:
图三显⽰Tooltip
为了正确使⽤CTrayIcon,⾸先你必须在程序的某个地⽅实例化CTrayIcon,例⼦程序是在主框架中创建CTrayIcon实例的。
1.Class MainFrame  public CFrameWnd {protected:  CTrayIconm_trayIcon;                  // my tray icon
2.…….
3.};
然后,你必须提供⼀个ID。这是在图标⽣命期内的唯⼀标⽰,即便以后你修改了要显⽰的图标。这个I
D也是⿏标事件发⽣时你将获得的ID。它不⼀定必须是图标的资源ID,例⼦程序中这个ID为IDR_TRAYICON,由框架的构造函数CMainFrame通过成员初始化列表对m_trayIcon进⾏初始化:
1.CMainFrame::CMainFrame() : m_trayIcon(IDR_TRAYICON){
2.……
3.}
为了添加图标,必须根据具体情况调⽤下列的 SetIcon 函数之⼀:
1.m_trayIcon.SetIcon(IDI_MYICON);        //资源 ID
2.m_trayIcon.SetIcon("myicon");          //资源名
3.m_trayIcon.SetIcon(hicon);            //HICON
4.m_trayIcon.SetStandardIcon(IDI_WINLOGO);//系统图标
除了SetIcon(UINT uID)之外,这些函数都有⼀个LPCSTR类型的可选参数⽤于指定提⽰⽂本。SetIcon(UINT uID)使⽤ID与uID相同的串资源作为提⽰⽂本。例如,TrayTest1有⼀⾏代码是这样的:
1.// (在mainframe.cpp⽂件中)
2.m_trayIcon.SetIcon(IDI_MYICON);
这⾏代码也设置了提⽰信息,因为TrayTest1有⼀个串资源,其ID也是IDI_MYICON。这在TRAYTEST.RC⽂件中可以看到:
1.STRINGTABLE PRELOAD DISCARDABLE
2.BEGIN
3.    IDI_MYICON "双击图标激活 TRAYTEST."
4.END
如果你想改变图标,可以⽤不同的ID或者HICON再次调⽤SetIcon函数之⼀。CTrayTest便会⽤NIM_MODIFY⽽不是NIM_ADD来改变图标。相同的函数甚⾄可以⽤于删除图标,如:
1.m_trayIcon.SetIcon(0); //删除图标
CTrayIcon将此代码解释成NIM_DELETE。你已经看到,所有这些表⽰⾏为的编码,标志都被⼀个使
⽤⽅便的函数所替代:这都归功
于C++!现在,我们来看看如何处理通知消息以及前⾯提到的所有UI特性。通知消息的处理必须要设置图标之前,但是要在创建窗⼝之后调⽤CTrayIcon::SetNotificationWnd,做这件事情的最佳场所是在OnCreate处理例程中,TrayTest就是在这⾥处理的:
01.// 注册⽤于托盘的⾃定义消息
02.#define WM_MY_TRAY_NOTIFICATION WM_USER+0
名贵树种03.int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
04.{
05.……
06.  // 请通知我
07.  m_trayIcon.SetNotificationWnd(this,
08.                        WM_MY_TRAY_NOTIFICATION);
09.                          m_trayIcon.SetIcon(IDI_MYICON);
10.  return 0;
11.}
消息⼀旦注册,接下来你便可以⽤通常的消息映射⽅式处理托盘通知消息。
01.BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
02.  ON_MESSAGE(WM_MY_TRAY_NOTIFICATION,
03.            OnTrayNotification)
04.            //(or ON_REGISTERED_MESSAGE)
知名网店05.END_MESSAGE_MAP()
06.
07.LRESULT
08.CMainFrame::OnTrayNotification(WPARAM wp, LPARAM lp)
09.{
10.……
11.      //显⽰消息
12.……
14.}
当消息处理器得到控制,WPARAM的值是在构造CTrayIcon时指定的ID;LPARAM为⿏标事件(如WM_LBUTTONDOWN)。当你得到通知消息后,可以做任何想做的的事情;例⼦程序TrayTest此时是显⽰通知信息,细节请参考源代码。完成消息的处理之后,调
任前谈话⽤CTrayIcon::OnTrayNotification进⾏缺省处理。此虚拟函数(所以你可以改写)实现我前⾯提到过的缺省的UI⾏为。尤其是处
理WM_LBUTTONDBLCLK和WM_RBUTTONUP。CTrayIcon寻找与图标ID相同的某个菜单(如IDR_TRAYICON),如果找到,则当⽤户右键单击图标时CTrayIcon显⽰这个菜单;当⽤户数双击图标时,CTrayIcon执⾏第⼀个菜单命令。只有两件事情需要进⼀步交待:
第⼀件事情是:在显⽰菜单之前,CTrayIcon让第⼀个菜单项为默认,所以它以⿊体显⽰。但如何⽤⿊体来显⽰某个菜单项呢?我
在\MSDEV\INCLUDE\*.H搜索了⼀番,发现了Get/SetMenuDefaultItem。这个函数没有相关的CMenu打包类,所以我必须直接调⽤它们。
1.// 让第⼀个菜单项为默认(⿊体):
2.::SetMenuDefaultItem(pSubMenu->m_hMenu, 0, TRUE);
这⾥0表⽰第⼀个菜单项,TRUE说明⽤位置表⽰菜单项的ID。为什么MFC没有打包Get/SetMenuDefaultItem函数呢?微软的家伙们解释那是因为这些函数(其它的还有::Get/SetMenuItemInfo, ::LoadImage等)还没有在最新的Windows版本中实现。⼀旦在最新的Windows版本中实现了,便会马上添加到MFC中。梦见掉钱
第⼆件事情是上下⽂菜单的显⽰:
1.::SetForegroundWindow(m_nid.hWnd); ::TrackPopupMenu(pSubMenu->m_hMenu,...);
为了让TrackPopupMenu在托盘的上下⽂中正确运⾏,你必须⾸先调⽤SetForegroundWindow,否则,当⽤户按下ESCAPE键或者在菜单之外单击⿏标时,菜单不会消失。为解决这个问题,我花费了数个⼩时,最后还是在MSDN上找到了解决⽅法。为了解详情,请参
考MSDN的Q135788。最让我哭笑不得的是我花了那么多时间来关注这个问题,最后微软的这帮家伙在MSDN上给你来了⼀个问题的结论是:“This behavior is ”真是⽓刹⼈也。
正如你所看到的,CTrayIcon使得托盘应⽤的编程变得易如反掌。TrayTest1要做的事情不外乎调⽤CTrayIcon::OnTrayNotification实现⼀个通知消息处理器,提供⼀个与图标ID相同的菜单。就这么简单。
01.// (TRAYTEST.RC⽂件)
02.IDR_TRAYICON MENU DISCARDABLE
03.BEGIN
04.    POPUP "托盘(&T)"愚人节的英文
05.    BEGIN
06.        MENUITEM "打开(&O)",                  ID_APP_OPEN
07.        MENUITEM "关于 TrayTest(&A)...",        ID_APP_ABOUT
08.        MENUITEM SEPARATOR
09.        MENUITEM "退出TrayTest 程序(&S)",      ID_APP_SUSPEND
10.    END
11.END
当⽤户在托盘图标上单击右键,CTrayIcon显⽰这个菜单,如图四所⽰。如果⽤户双击图标,CTrayIcon执⾏第⼀个菜单命令:“打开”,此时激活TrayTest(正常状态下是隐藏的)。为了终⽌TrayTest1,你必须选择"Suspend TRAYTEST"菜单项。如果你从“⽂件|退出”退出,或者关闭TrayTest1主窗⼝,TrayTest1不会真正关闭,它只是将⾃⼰隐藏起来。这个⾏为是TrayTest1改写了CMainframe::OnClo实现的。
图四 TRAYTEST1 托盘图标菜单
最后,我想说明⼀个很让⼈担⼼的问题,每个⼈在看到这个⼩图标后都想尽快的在⾃⼰的程序中加⼊托盘图标。作为程序员,这完全是可以理解的。当⾃⼰的程序中成功添加了托盘图标,在朋友们中间炫耀⼀番,那种感觉确实很好。但是要记住:并不是所有的应⽤都需要⽤托盘图标,如果不是必须就不要画蛇添⾜,否则托盘图标太多必然造成屏幕垃圾,看看下⾯图五吧:
/Public/Uploads/images/84/1330592663.gif
图五托盘图标程序“噩梦版”
看到这么多的托盘图标对于⽤户来说简直就是噩梦
我们讨论并⽰范了如何在⾃⼰的程序中应⽤系统托盘图标。通过使⽤⾃⼰创建的⼀个可重⽤的 C++ 类——CTrayIcon,我们可以轻松地实现托盘程序。不久以前我⽤这个类编写了⼀个程序,开始运⾏很正常,但是有⼀次不知什么原因Windows资源管理器死掉了,也就是说⾮正常关闭,重启资源管理器后,发现托盘程序仍然在运⾏,但托盘图标显⽰不出来,在任务栏中看不到托盘图标,只有重新启动机器才能重新显⽰出托盘图标,让⼈觉得⼼⾥很不舒服,有没有什么办法在这个时候不⽤重启机器⽽让Windows⾃动找回托盘图标并把它添加到任务栏呢?,也就是让它⾃动恢复托盘图标程序的⽤户界⾯,经过⼀番研究,终于有所收获。
实际上,如果你⽤的操作系统是Windows 98或者你安装了IE4.0的桌⾯。那么不论什么时候,只要IE4.0启动了任务栏,那么它就会向所有最顶层⽗窗⼝⼴播⼀个注册消息:TaskbarCreated。有了这个线索,你就可以重新创建图标。如果你⽤MFC编程,那么只要定义⼀个全程变量保存这个注册消息并实现ON_REGISTERED_MESSAGE消息处理例程即可:
02.    ::RegisterWindowMessage(_T("TaskbarCreated"));
03.
04.BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
05.    ON_REGISTERED_MESSAGE(WM_TASKBARCREATED,
06.                          OnTaskBarCreated)
07.END_MESSAGE_MAP(CMainFrame,CFrameWnd)
08.    The handler itlf should reinstall whatever icons youneed.
09.
10.LRESULT CMainFrame::OnTaskBarCreated(WPARAM wp, LPARAM lp)
11.{
12.    VERIFY(InstallIcons());
13.    return 0;
14.}
15.
16.BOOL CMainFrame::InstallIcons()
17.{
18.    NOTIFYICONDATA nid;
19.    //
20.    // 准备 nid 参数
21.    //
22.    return Shell_NotifyIcon(NIM_ADD, &nid);
难道就这么容易吗?当然不是,你必须单独实现InstallIcons函数,⽽不是直接从OnTaskBarCreated中调⽤Shell_NotifyIcon,因为⼀般来说,在应⽤程序启动的时候你也会调⽤它。
当我搞清楚TaskbarCreated的奥秘之后,我便回到本⽂第⼀部分中创建的那个CTrayIcon类,对它进⾏了修改和完善,改动不是很⼤。这个类管理的是单个的托盘图标(如果你有多个,那么为每个图标创建⼀个单独的实例吧)。使⽤CTrayIcon时,你只要在CMainFrame中创建⼀个实例m_trayIcon并象下⾯这样安装它即可:
1.// 在CMainFrame::OnCreate中
2.m_trayIcon.SetNotificationWnd(this,
3.    WM_MY_TRAY_NOTIFICATION);
4.m_trayIcon.SetIcon(IDI_MYICON);
WM_MY_TRAY_NOTIFICATION 是⾃⼰的私有消息,只在有事件发⽣时,托盘图标才发送此消息,如⽤户单击图标。对于托盘图标来说,你不⽤对它做什么处理,CTrayIcon全权负责。只是在构造CTrayIcon对象时,你给它⼀个资源ID就可以了。CTrayIcon⽤这个ID查找上下⽂菜单,如果找到的话,它便⾃动处理右键单击托盘图标事件,这时弹出上下⽂菜单。如果⽤户双击图标,CTrayIcon则执⾏第⼀个菜单项命令。所以你要做的全部⼯作只是创建⼀个菜单资源,将ID传递给构造函数,然后去驱动CTrayIcon就可以了。如果你想要⼀些⾮标准的例程,那么只需处理WM_MY_TRAY_NOTIFICATION即可。有关细节请参考源代码。
为了实现图标⾃动重建特性,我使⽤了以前很多⽂章中都⽤到的⼀个类CSubclassWnd,这个类在我的编程⽣涯中⼏乎⽆处不在。没有了它,我⼏乎⼨步难⾏;在我的所有编程诀窍中,它是最有⽤的⼀个类。⽤这个类可以截获Windows消息,并将它发送到另外⼀个窗⼝消息处理例程中处理,⽽不是发送到Windows⾃⼰默认的消息处理函数。CTrayIcon⽤它来截获TaskbarCreated消息,所以你就不必为此编写消息处理器——这个⽅法⾮常酷。CSubclassWnd通过安装它⾃⼰的窗⼝过程,从⽽先于MFC⼀步对消息进⾏处理。
当CMainFrame调⽤CTrayIcon::SetNotificationWnd时,CTrayIcon调⽤GetTopLevelParent以获取顶层⽗窗⼝,然后安装CSubclassWnd窗⼝过程,这相当于⼀个钩⼦,在消息传到任何顶层窗⼝之前,CSubclassWnd的窗⼝过程先将它处理掉。这⾥必须明⽩⼀点:Windows只
将TaskbarCreated消息发送到顶层⽗窗⼝。它有点象WM_QUERYNEWPALETTE、WM_SYSCOLORCHANGE消息以及其它顶层窗⼝消息。现在当Windows发送TaskbarCreated时,控制将⾸先被传递到CTrayIcon::CTrayHook::WindowProc。
CTrayIcon::OnTaskBarCreate是CTrayIcon类中新加的⼀个虚拟函数,其默认实现是在系统托盘中重新安装图标。如果你想做⼀些其它的事情,可以派⽣⼀个新类并改写此默认⾏为。实际的WindowProc代码⽐我在本⽂中描述的要稍微复杂⼀些,因为它还要处理托盘通知以驱动默认的菜单处理例程,以前,当获得WM_MY_TRAY_NOTIFICATION消息时,你必须⾃⼰调⽤OnTrayNotification。新的CTrayIcon实现请参考本⽂的源代码。
顺便提及⼀下,你想知道我是如何测试图标⾃动重建特性的吗?(如果是你,你⽤什么办法?),很容易。在Windows 98中,按
下Ctrl+Alt+Del,弹出任务管理器的任务清单。选择"资源管理器(Explorer)",然后选择"结束任务(End Task)"。此时会显⽰关机/重启对话框,此时按下"取消"按钮(不要按"关机"按钮)。然后,等待⼏秒钟,你得到消息显⽰"这个任务没有响应",这时你要⽤"结束任务"来回复。接下来Windows的资源管理器便⾮正常终⽌!然后它⼜会⾃动起来,这时向所有顶层⽗窗⼝⼴播TaskbarCreated消息。如果你的操作系统是Windows NT/2000/XP,并安装了IE4.0,如法炮制。当任务栏死掉后,从"开始"菜
单的"运⾏"对话框中敲⼊"explorer"启动器源管理器。不管是⽤什么操作系统,在杀掉任务栏之前,如果TrayTest程序处于运⾏状态,那么当资源管理器⾃⼰恢复状态时,TrayTest程序的托盘图标会⾃动创新安装。不信的话,你⽤本⽂第⼀部分的例⼦程序和本⽂提供的范例程序试⼀下就知道了。你会发现本⽂的例⼦程序会处
理TaskbarCreated消息,⽽另⼀个则完全不会
托盘程序的信息提⽰通常是将⿏标光标移到托盘图标上之后,Windows会发送消息给托盘程序,从⽽显⽰提⽰信息――Tooltip。但
在Windows XP中我们还看到有些系统托盘程序是⾃动显⽰ToolTips信息的,也就是说不⽤将⿏标光标移到托盘图标上便可显⽰ToolTips,在这是怎么实现的呢?本⽂将⽰范⼀种新奇的ToolTips风格,它叫做⽓球提⽰:Balloon Tips。
Windows中与托盘图标相关的提⽰有两类:⼀类是传统的信息提⽰⽅式,当光标移到图标上时显⽰;另⼀类是新式的信息提⽰即⽓球提⽰,它是由你的程序来控制显⽰。⽓球提⽰有点像连环漫画中的⽂字⽓球。如图⼀、图⼆分别为本⽂例⼦程序TrayTest3在Windows
2000和Windows XP中运⾏的画⾯:
在Windows2000中运⾏的⽓球提⽰,没有关闭按钮。
图⼀在Windows 2000运⾏
在WindowsXP中运⾏。
图⼆在 Windows XP中运⾏的TrayTest3
⽓球提⽰为托盘程序提供了⼀种⾮打扰式的⽅法通知⽤户发⽣了某件事情。但是如何让⽓球提⽰显⽰出来呢?所有的托盘图标⾏为都是通过⼀个单纯的API函数Shell_NotifyIcon来操作的。这个函数的⼀个参数是NOTIFYICONDATA结构,你可以利⽤这个结构来告诉Windows你想要做什么。下⾯是这个结构的定义的最新版本(For IE5.0+),其中已经加⼊了新的成员:
02.    DWORD cbSize;
含数字的四字成语03.    HWND hWnd;
04.    UINT uID;
05.    UINT uFlags;
06.    UINT uCallbackMessage;
07.    HICON hIcon;
08.    #if(_WIN32_IE < 0x0500)
09.        WCHAR  szTip[64];
10.    #el
11.        WCHAR  szTip[128];
12.    #endif
13.    #if (_WIN32_IE >= 0x0500)
14.        DWORD dwState;
15.        DWORD dwStateMask;
16.        WCHAR  szInfo[256];
17.        union {
18.            UINT  uTimeout;
19.            UINT  uVersion;
20.        } DUMMYUNIONNAME;
21.        WCHAR  szInfoTitle[64];
22.        DWORD dwInfoFlags;
23.    #endif
24.} NOTIFYICONDATA, *PNOTIFYICONDATA;
有关这个结构的详细信息和⽤法请参考本⽂前⾯的两个部分:
系统托盘编程完全指南(⼀)
系统托盘编程完全指南(⼆)
在NOTIFYICONDATA.uFlags中的标志之⼀是NIF_TIP,⽤它来设置传统的信息提⽰,即⿏标要移动到图标上。新的标志NIF_INFO(由
于_WIN32_IE >= 0x0500条件定义,因此在编译时,请注意包含最新版本的头⽂件shellapi.h,并保证链接最新版本的库⽂件shell32.lib,分发程序时⽤最新版本的运⾏时动态链接库shell32.dll)便是为显⽰⽓球提⽰所⽤的。也就是说,要显⽰⽓球提⽰,那么在调
⽤Shell_NotifyIcon函数时必须⽤NIF_INFO标志。提⽰⽂本填⼊szInfo域,标题⽂本填⼊szInfoTitle。你甚⾄可以
在NOTIFYICONDATA.uTimeout中设置⼀个超时时间,当经过指定的毫秒数之后,⽓球提⽰⾃动隐藏。

本文发布于:2023-05-24 05:12:32,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/89/926156.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:图标   托盘   消息   程序   处理
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图