我现在正在学,但有时我学习语言的时候再用VC++的集成开发环境,就会感到我所学的东西跟本都是一些没有用的东西。
但是有时我又按书上的例子做一些VC++的集成开发环境下的练习时,就又会感很莫名,因为一直点来点去的,好像跟语言没有关系一样,
更重要的是觉得它好像失去了C++语言的意义,感觉它跟就不能算是一种语言。我知道大家都一直都说C++是一种语言。而VC++只是一种集成开发环境。是一个工具。但我真的还是不明白。为什么我会感觉我好像跟本就不是在写C++程序呢。有时候我自己也问自己,我现在是在学习什么呢,做什么呢。我只能说我不知道、、真的不知道、、、、、、、、
mfc望上追溯,就是win32api和c++面向对象思想的结合了.个人意见.
我的网络安全老师说:真正的windows程序员高手是winApi高手
学VC也就是学MFC了,另外还有一些WinAPI.
VC++6.0中实现将应用程序的图标加入到Windows的系统托盘中
西安二炮工程学院
俞俊军 张 毅
摘要
本文对如何将应用程序的图标加入到Windows的系统托盘中做了较为详细的介绍,然后给出了一个C++类以方便的实现该功能,并在VC++6.0中给出了一个应用程序实例来体现其具体实现过程。同时该应用程序实例还讲解了如何在托盘中实现动画图标以及在程序中关闭计算机的技术。 关键词:系统托盘 动画图标 Windows98桌面的系统托盘位于任务栏的右侧,即Windows98桌面的右下方。它常用来显示一些系统的状态。如:系统时间,音量控制以及其它的一些图标(依个人机器安装的软件而不定),如下图为笔者的Windows98系统托盘。(图略) 常常能见到一些优秀的软件在运行后会将其应用程序图标加入到系统托盘中,如金山词霸。如果能将自己编写的应用程序的图标也加入到系统托盘中,将会使你的程序显得很有专业水准。 其实这并不困难,与系统托盘通信的函数只有一个: Shell_NotifyIcon (UINT message, NOTIFYICONDATA &m_nid); 首先看一下该函数的两个参数。 第一个参数message可以取以下值: NIM_ADD 向托盘中加入一个图标; NIM_MODIFY 修改托盘中的图标;NIM_DELETE 从托盘中删除一个图标。 第二个参数m_nid是NOTIFYICONDATA结构的一个引用。该结构的原型如下:typedef struct _NOTIFYICONDATA { DWORD cbSize;// 结构的大小,必须在程序中给出 HWND hWnd; //是你程序中将要接收托盘消息的窗口句柄 UINT uID; // 应用程序中定义的托盘图标ID,此参数用作标识 UINT uFlags; //设置属性,低三位有意义,0--7,如下: //第一位//#define NIF_MESSAGE 0x1 // uCallbackMessage参数有效 //第二位//#define NIF_ICON 0x2 // hIcon参数有效 //第三位//#define NIF_TIP 0x4 // szTip参数有效 UINT uCallbackMessage; // 自定义的消息ID值,一定不要与以有的消息ID相重。 HICON hIcon; //显示在系统托盘上的Icon的句柄,可以为系统的 IDI_WINLOGO等 CHAR szTip[64]; // 用于图标显示的提示字符串 } NOTIFYICONDATA; 为了接收到来自托盘的通知消息你可以将uCallbackMessage设定为你所定义的消息ID值,同时设定NIF_MESSAGE标志。这样当用户在你的托盘图标上移动或按下鼠标时,Windows将发出消息:该消息的 messageID是你在uCallbackMessage中定义的值;wParam是你定义的uID值;而lParam是鼠标事件(如WM_LBUTTONDOWN),这样你的应用程序就能响应该事件了。 因此,为了将自己的应用程序加入到系统托盘中,首先得建立一处理托盘通知消息的窗口对象,然后将窗口对象与你自己的托盘通知消息联系起来并建立相应的托盘通知消息映射机制,以便你的窗口对象能处理相应的事件。 可以看到结构体NOTIFYICONDATA中,其成员变量hWnd,uID,uFlags均用于在窗口对象与你自己的托盘通知消息之间建立联系,而成员变量uCallbackMessage则必须是对应于你的窗口对象的托盘通知消息ID值。 于是要完成的工作有: (1)建立一处理托盘通知消息的窗口对象;
(2)建立一结构体NOTIFYICONDATA变量,并给变量的相应域赋值以在托盘通知消息与窗口对象之间建立联系;
(3)建立相应的托盘通知消息映射机制;
(4)调用Shell_NotifyIcon函数以在系统托盘中加入、修改或删除图标;
(5)当然别忘了在你的窗口对象中编写相应的事件响应函数。 因此,可以编写一C++类来实现以上功能以简化编程同时提高代码的可重用性。以下为该类代码: class CTrayIcon : public CCmdTarget { protected: DECLARE_DYNAMIC(CTrayIcon) NOTIFYICONDATA m_nid; // Shell_NotifyIcon 函数中的结构参数 public: CTrayIcon(UINT uID); ~CTrayIcon(); // 通过调用该成员函数来接收托盘通知消息 void SetNotificationWnd(CWnd* pNotifyWnd, UINT uCbMsg); // SetIcon 函数用来在系统托盘中加入、改变及删除图标。 //要删除图标这样调用:SetIcon(0) BOOL SetIcon(UINT uID); BOOL SetIcon(HICON hicon, LPCSTR lpTip); BOOL SetIcon(LPCTSTR lpResName, LPCSTR lpTip) { return SetIcon(lpResName ? AfxGetApp()->LoadIcon(lpResName) : NULL, lpTip); } BOOL SetStandardIcon(LPCTSTR lpszIconName, LPCSTR lpTip) { return SetIcon(::LoadIcon(NULL, lpszIconName), lpTip); } virtual LRESULT OnTrayNotification (WPARAM uID, LPARAM lEvent); }; CTrayIcon::CTrayIcon(UINT uID) { //初始化NOTIFYICONDATA结构变量 memset(&m_nid, 0 , sizeof(m_nid)); m_nid.cbSize = sizeof(m_nid); m_nid.uID = uID; AfxLoadString(uID, m_nid.szTip, sizeof (m_nid.szTip)); } CTrayIcon::~CTrayIcon() { SetIcon(0); // 从系统托盘中删除图标 } // 设定通知窗口,该窗口必须已被创建void CTrayIcon::SetNotificationWnd (CWnd* pNotifyWnd, UINT uCbMsg) { ASSERT(pNotifyWnd==NULL || ::IsWindow (pNotifyWnd->GetSafeHwnd())); m_nid.hWnd = pNotifyWnd->GetSafeHwnd(); ASSERT(uCbMsg==0 || uCbMsg>=WM_USER); m_nid.uCallbackMessage = uCbMsg; } BOOL CTrayIcon::SetIcon(UINT uID) { HICON hicon=NULL; if (uID) { AfxLoadString(uID, m_nid.szTip, sizeof(m_nid.szTip)); hicon = AfxGetApp()->LoadIcon(uID); } return SetIcon(hicon, NULL); } BOOL CTrayIcon::SetIcon(HICON hicon, LPCSTR lpTip) { UINT msg; m_nid.uFlags = 0; // 设定图标 if (hicon) { // 判断是要在系统托盘中增加还是要删除图标 msg = m_nid.hIcon ? NIM_MODIFY : NIM_ADD; m_nid.hIcon = hicon; m_nid.uFlags |= NIF_ICON; } else { // 删除图标 if (m_nid.hIcon==NULL) return TRUE; //已被删除 msg = NIM_DELETE; } if (lpTip) 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) m_nid.uFlags |= NIF_MESSAGE; BOOL bRet = Shell_NotifyIcon(msg, &m_nid); if (msg==NIM_DELETE || !bRet) m_nid.hIcon = NULL; return bRet; }