利用Visual C++实现系统托盘程序.docx
- 文档编号:8049004
- 上传时间:2023-01-28
- 格式:DOCX
- 页数:10
- 大小:21.30KB
利用Visual C++实现系统托盘程序.docx
《利用Visual C++实现系统托盘程序.docx》由会员分享,可在线阅读,更多相关《利用Visual C++实现系统托盘程序.docx(10页珍藏版)》请在冰豆网上搜索。
利用VisualC++实现系统托盘程序
利用VisualC++实现系统托盘程序
这些程序运行时不显示运行窗口,只在任务栏上显示一个图标,表示程序正在运行,用户可以通过鼠标与应用程序交互,程序开发人员有时也需要编制一些仅在后台运行的类似程序,为了不干扰前台程序的运行界面和不显示不必要的窗口,应使程序运行时的主窗口不可见。
同时将一个图标显示在任务栏右端静态通告区中并响应用户的鼠标动作。
本实例就介绍VisualC++开发这类程序的设计方法,该程序编译运行后,如果双击托盘图标,程序会弹出一个消息列表窗口,只要鼠标在托盘图标上移动或点击(无论是左右键的单击或双击),产生的消息都会显示在这个窗口里;当鼠标光标移到托盘图标上时,在图标附近会显示提示信息;单击右键时弹出上下文菜单,这个菜单中应包含打开属性页的命令或者打开与图标相关的其它窗口的命令,另外,该程序还可以动态的改变托盘的图标。
参照这个例子,相信读者能轻松自如地在自己的程序中应用系统托盘。
一、实现方法
为了实现拖盘程序,首先要使程序的主窗口不可见,这点实现起来十分容易,只要调用ShowWindow(SW_HIDE)就可以了,本实例采用的就是这种方法,还有一种思路是通过分别设置主边框窗口的风格和扩展风格来隐藏主框架:
BOOLCMainFrame:
:
PreCreateWindow(CREATESTRUCT&cs)
{
cs.style=WS_POPUP;//使主窗口不可见;
cs.dwExStyle=WS_EX_TOOLWINDOW;//不显示任务按钮;
returnCFrameWnd:
:
PreCreateWindow(cs);
}
在任务条上显示图标是利用系统API函数Shell_NotifyIcon()来将一个图标显示在任务栏的通告区中。
该函数的原型为:
BOOLShell_NotifyIcon(DWORDdwMessage,PNOTIFYICONDATApnid);
该函数的第一个参数dwMessage类型为DWORD,表示要进行的动作,它可以是下面的值之一:
NIM_ADD:
添加一个图标到任务栏。
NIM_MODIFY:
修改状态栏区域的图标。
NIM_DELETE:
删除状态栏区域的图标。
NIM_SETFOCUS:
将焦点返回到任务栏通知区域。
当完成用户界面操作时,任务栏图标必须用此消息。
例如,如果任务栏图标正显示上下文菜单,但用户按下"ESCAPE"键取消操作,这时就必须用此消息将焦点返回到任务栏通知区域。
NIM_SETVERSION:
指示任务栏按照相应的动态库版本工作。
第二个参数pnid是NOTIFYICONDATA结构的地址,其内容视dwMessage的值而定。
这个结构在SHELLAPI.H文件中定义如下:
typedefstruct_NOTIFYICONDATA{
DWORDcbSize;//结构大小(sizeofstruct),必须设置
HWNDhWnd;//发送通知消息的窗口句柄
UINTuID;//图标ID(由回调函数的WPARAM指定)
UINTuFlags;
UINTuCallbackMessage;//消息被发送到此窗口过程
HICONhIcon;//任务栏图标句柄
CHARszTip[64];//提示文本
}NOTIFYICONDATA;
该结构中uFlags的值分别为:
#defineNIF_MESSAGE0x1//表示uCallbackMessage有效
#defineNIF_ICON0x2//表示hIcon有效
#defineNIF_TIP0x4//表示szTip有效
在该结构的成员中,cbSize为该结构所占的字节数,hWnd为接受该图标所发出的消息的窗口的句柄(鼠标在任务栏上程序图标上动作时图标将发出消息,这个消息用户要自己定义),uID为被显示图标的ID,uFlags指明其余的几个成员(hIcon、uCallBackMessage和szTip)的值是否有效,uCallbackMessage为一个用户自定义的消息,当用户在该图标上作用一些鼠标动作时,图标将向应用程序的主框架窗口(hWnd成员中指定的窗口)发出该消息,为了使程序的主框架得到该通知消息,需要设置NOTIFYICONDATA结构的flag成员的值为NIF_MESSAGE。
hIcon为将在任务栏上显示的图标句柄,szTip鼠标停留在该图标上时显示的提示字符串。
尽管Shell_NotifyIcon函数简单实用,但它毕竟是个Win32API,为此本实例将它封装在了一个C++类中,这个类叫做CTrayIcon,有了它,托盘编程会更加轻松自如,因为它隐藏了NOTIFYICONDATA、消息代码、标志以及一些繁琐的细节。
二、编程步骤
1、启动VisualC++6.0,生成一个单文档的应用程序TrayTest,取消文档视图支持;
2、在CMainFrame类中添加自定义消息#defineWM_MY_TRAY_NOTIFICATIONWM_USER+0,并在该类中为此自定义消息手动添加消息映射ON_MESSAGE(WM_MY_TRAY_NOTIFICATION,OnTrayNotification)和消息响应函数afx_msgLRESULTOnTrayNotification(WPARAMwp,LPARAMlp);
3、设计二个图标添加到项目中,其ID标志分别为"IDI_MYICON"、"IDI_MYICON2",作为托盘显示时的图标;
4、在CMainFrame类中添加下述变量:
CTrayIconm_trayIcon(用来操作图标的类对象)、CEditm_wndEdit(编辑框用来显示所跟踪到的鼠标消息)、intm_iWhichIcon(决定当前托盘使用哪个图标)、BOOLm_bShutdown(是否关闭当前拖盘程序标志)、BOOLm_bShowTrayNotifications(是否显示托盘消息标志);
5、为程序的IDR_MAINFRAME添加处理菜单项和托盘的上下文菜单IDI_TRAYICON(具体的菜单项的标题和ID标志符参见代码部分),然后使用ClassWizard为各个菜单项添加处理函数;
6、添加代码,编译运行程序。
///////////////////////////////////////////////CTrayIcon类的头文件;
#ifndef_TRAYICON_H
#define_TRAYICON_H
classCTrayIcon:
publicCCmdTarget{
protected:
DECLARE_DYNAMIC(CTrayIcon)
NOTIFYICONDATAm_nid;//structforShell_NotifyIconargs
public:
CTrayIcon(UINTuID);
~CTrayIcon();
//Callthistoreceivetraynotifications
voidSetNotificationWnd(CWnd*pNotifyWnd,UINTuCbMsg);
BOOLSetIcon(UINTuID);//mainvariantyouwanttouse
BOOLSetIcon(HICONhicon,LPCSTRlpTip);
BOOLSetIcon(LPCTSTRlpResName,LPCSTRlpTip)
{returnSetIcon(lpResName?
AfxGetApp()->LoadIcon(lpResName):
NULL,lpTip);}
BOOLSetStandardIcon(LPCTSTRlpszIconName,LPCSTRlpTip)
{returnSetIcon(:
:
LoadIcon(NULL,lpszIconName),lpTip);}
virtualLRESULTOnTrayNotification(WPARAMuID,LPARAMlEvent);
};
#endif
///////////////////////////////////////////////////CTrayIcon类的.CPP文件
#include"stdafx.h"
#include"trayicon.h"
#include//forAfxLoadString
IMPLEMENT_DYNAMIC(CTrayIcon,CCmdTarget)
CTrayIcon:
:
CTrayIcon(UINTuID)
{
memset(&m_nid,0,sizeof(m_nid));//InitializeNOTIFYICONDATA
m_nid.cbSize=sizeof(m_nid);
m_nid.uID=uID;//neverchangesafterconstruction
AfxLoadString(uID,m_nid.szTip,sizeof(m_nid.szTip));
//Useresourcestringastipifthereisone
}
CTrayIcon:
:
~CTrayIcon()
{
SetIcon(0);//removeiconfromsystemtray
}
voidCTrayIcon:
:
SetNotificationWnd(CWnd*pNotifyWnd,UINTuCbMsg)
{
//Setnotificationwindow.Itmustcreatedalready.
ASSERT(pNotifyWnd==NULL :
:
IsWindow(pNotifyWnd->GetSafeHwnd()));
m_nid.hWnd=pNotifyWnd->GetSafeHwnd();
ASSERT(uCbMsg==0 uCbMsg>=WM_USER);
m_nid.uCallbackMessage=uCbMsg;
}
BOOLCTrayIcon:
:
SetIcon(UINTuID)
{
//SetsboththeiconandtooltipfromresourceID,Toremovetheicon,callSetIcon(0)
HICONhicon=NULL;
if(uID){
AfxLoadString(uID,m_nid.szTip,sizeof(m_nid.szTip));
hicon=AfxGetApp()->LoadIcon(uID);
}
returnSetIcon(hicon,NULL);
}
BOOLCTrayIcon:
:
SetIcon(HICONhicon,LPCSTRlpTip)
{
//CommonSetIconforalloverloads.
UINTmsg;
m_nid.uFlags=0;
if(hicon){
//Settheicon
msg=m_nid.hIcon?
NIM_MODIFY:
NIM_ADD;
m_nid.hIcon=hicon;//Addorreplaceiconinsystemtray
m_nid.uFlags =NIF_ICON;
}else{
if(m_nid.hIcon==NULL)//removeiconfromtray
returnTRUE;//alreadydeleted
msg=NIM_DELETE;
}
if(lpTip)//Usethetip,ifany
strncpy(m_nid.szTip,lpTip,sizeof(m_nid.szTip));
if(m_nid.szTip[0])
m_nid.uFlags =NIF_TIP;
if(m_nid.uCallbackMessage&&m_nid.hWnd)//Usecallbackifany
m_nid.uFlags =NIF_MESSAGE;
BOOLbRet=Shell_NotifyIcon(msg,&m_nid);//Doit
if(msg==NIM_DELETE !
bRet)
m_nid.hIcon=NULL;//failed
returnbRet;
}
LRESULTCTrayIcon:
:
OnTrayNotification(WPARAMwID,LPARAMlEvent)
{
if(wID!
=m_nid.uID (lEvent!
=WM_RBUTTONUP&&lEvent!
=WM_LBUTTONDBLCLK))
return0;
CMenumenu;//装载上下文菜单;
if(!
menu.LoadMenu(m_nid.uID))
return0;
CMenu*pSubMenu=menu.GetSubMenu(0);
if(!
pSubMenu)
return0;
if(lEvent==WM_RBUTTONUP){//设置第一个菜单项为默认菜单项目
:
:
SetMenuDefaultItem(pSubMenu->m_hMenu,0,TRUE);
//将当前菜单作为上下文菜单;
CPointmouse;
GetCursorPos(&mouse);
:
:
SetForegroundWindow(m_nid.hWnd);
:
:
TrackPopupMenu(pSubMenu->m_hMenu,0,mouse.x,mouse.y,0,m_nid.hWnd,NULL);
}else//doubleclick:
executefirstmenuitem
:
:
SendMessage(m_nid.hWnd,WM_COMMAND,pSubMenu->GetMenuItemID(0),0);
return1;
}
/////////////////////////////////MainFrm.h:
interfaceoftheCMainFrameclass
#if!
defined(AFX_MAINFRM_H__9ED70A69_C975_4F20_9D4E_B2877E3575D0__INCLUDED_)
#defineAFX_MAINFRM_H__9ED70A69_C975_4F20_9D4E_B2877E3575D0__INCLUDED_
#if_MSC_VER>1000
#pragmaonce
#endif//_MSC_VER>1000
#include"trayicon.h"
classCMainFrame:
publicCFrameWnd
{
public:
CMainFrame();
protected:
DECLARE_DYNAMIC(CMainFrame)
//Attributes
public:
//Overrides
//ClassWizardgeneratedvirtualfunctionoverrides
//{{AFX_VIRTUAL(CMainFrame)
//}}AFX_VIRTUAL
//Implementation
public:
virtual~CMainFrame();
#ifdef_DEBUG
virtualvoidAssertValid()const;
virtualvoidDump(CDumpContext&dc)const;
#endif
protected:
//controlbarembeddedmembers
CStatusBarm_wndStatusBar;
CTrayIconm_trayIcon;//mytrayicon
CEditm_wndEdit;//todisplaytraynotifications
intm_iWhichIcon;//whichHICONtouse
BOOLm_bShutdown;//OKtoterminateTRAYTEST
BOOLm_bShowTrayNotifications;//displayinfoinmainwindow
//Generatedmessagemapfunctions
protected:
//{{AFX_MSG(CMainFrame)
afx_msgLRESULTOnTrayNotification(WPARAMwp,LPARAMlp);
afx_msgintOnCreate(LPCREATESTRUCTlpCreateStruct);
afx_msgvoidOnToggleIcon();
afx_msgvoidOnViewClear();
afx_msgvoidOnViewNotifications();
afx_msgvoidOnUpdateViewClear(CCmdUI*pCmdUI);
afx_msgvoidOnUpdateViewNotifications(CCmdUI*pCmdUI);
afx_msgvoidOnClose();
afx_msgvoidOnAppOpen();
afx_msgvoidOnAppSuspend();
//NOTE-theClassWizardwilladdandremovememberfunctionshere.
//DONOTEDITwhatyouseeintheseblocksofgeneratedcode!
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
///////////////////////////////////////////////CMainFrm.cpp
#include"stdafx.h"
#include"TrayTest.h"
#include"MainFrm.h"
#ifdef_DEBUG
#definenewDEBUG_NEW
#undefTHIS_FILE
staticcharTHIS_FILE[]=__FILE__;
#endif
LRESULTCTrayIcon:
:
OnTrayNotification(WPARAMwID,LPARAMlEvent)
{
if(wID!
=m_nid.uID (lEvent!
=WM_RBUTTONUP&&lEvent!
=WM_LBUTTONDBLCLK))
return0;
CMenumenu;//装载上下文菜单;
if(!
menu.LoadMenu(m_nid.uID))
return0;
CMenu*pSubMenu=menu.GetSubMenu(0);
if(!
pSubMenu)
return0;
if(lEvent==WM_RBUTTONUP){//设置第一个菜单项为默认菜单项目
:
:
SetMenuDefaultItem(pSubMenu->m_hMenu,0,TRUE);
//将当前菜单作为上下文菜单;
CPointmouse;
GetCursorPos(&mouse);
:
:
SetForegroundWindow(m_nid.hWnd);
:
:
TrackPopupMenu(pSubMenu->m_hMenu,0,mouse.x,mouse.y,0,m_nid.hWnd,NULL);
}else//doubleclick:
executefirstmenuitem
:
:
SendMessage(m_nid.hWnd,WM_COMMAND,pSubMenu->GetMenuItemID(0),0);
return1;
}
/////////////////////////////////MainFrm.h:
interfaceoftheCMainFrameclass
#if!
defined(AFX_MAINFRM_H__9ED70A69_C975_4F20_9D4E_B2877E3575D0__INCLUDED_)
#defineAFX_MAINFRM_H__9ED70A69_C975_4F20_9D4E_B2877E3575D0__INCLUDED_
#if_MSC_VER>1000
#pragmaonce
#endif//_MSC_VER>1000
#include"trayicon.h"
classCMainFrame:
publicCFrameWnd
{
public:
CMainFrame();
protected:
DECLARE_DYNAMIC(CMainFrame)
//Attributes
public:
//Overrides
//ClassWizardgeneratedvirtualfunctionoverrides
//{{AFX_VIRTUAL(CMainFrame)
//}}AFX_VIRTUAL
//Implementation
public:
virtual~CMainFrame();
#ifdef_DEBUG
virtualvoidAssertValid()const;
virtualvoidDump(CDumpContext&dc)const;
#endif
protected:
//controlbarembeddedmem
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 利用Visual C+实现系统托盘程序 利用 Visual C+ 实现 系统托盘 程序