[原创][基础][MFC篇][C++程序系统托盘与运行实例唯一实现]2014-10-10 22:40:20
( 5人已投票,[高质量] )
程序都要实现系统托盘功能,最小化到右下角的托盘是不是很酷,像QQ等软件
还有的程序只允许运行一个,防止重复运行也是C++开发中经常用到的内容,
再次运行时会提示已经运行,是不是很友好的呢?
下面就实现这两个功能:
一:实现实例唯一
托盘一般只用在类testApp中设置一个互斥对象就可以满足
首先在App类中添加一个成员变量HANDLE m_hMutex;并在构造中初始化m_hMutex = NULL;
在InitInstance()中把代码替换成如下代码就可达到目的,
代码我就随便上了,底部的下无包中有完整的代码,都是经过我测试的。
AfxEnableControlContainer(); // Standard initialization // If you are not using these features and wish to reduce the size // of your final executable, you should remove from the following // the specific initialization routines you do not need. m_hMutex = ::CreateMutex(NULL, FALSE, _T("abc"));//创建互斥对象 //判断互斥量是否存在 if (GetLastError() == ERROR_ALREADY_EXISTS) { AfxMessageBox("应用程序已经运行。"); return FALSE; } AfxEnableControlContainer(); #ifdef _AFXDLL Enable3dControls(); // Call this when using MFC in a shared DLL #else Enable3dControlsStatic(); // Call this when linking to MFC statically #endif CTestTrayDlg dlg; m_pMainWnd = &dlg; int nResponse = dlg.DoModal(); if (nResponse == IDOK) { } else if (nResponse == IDCANCEL) { } return FALSE;
二:实现托盘功能
托盘功能比较麻烦,首先在Dlg中定义变量
NOTIFYICONDATA m_Nid;也初化为NULL //OnInitDlg中添加 m_Nid.cbSize = sizeof(NOTIFYICONDATA); m_Nid.hWnd = m_hWnd; m_Nid.uID = 100; m_Nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP; m_Nid.uCallbackMessage = WM_NOTIFYICON; m_Nid.hIcon = (HICON)LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_MAINFRAME), IMAGE_ICON, 16, 16, NULL); StrCpy(m_Nid.szTip, _T("TrayName"));
对话框上添加按纽IDC_TEST,双击添加事件改名叫OnTest添加如下代码
ShowWindow(SW_HIDE); //在任务栏中添加图标 Shell_NotifyIcon(NIM_ADD, &m_Nid); //在头上定义 #define WM_NOTIFYICONWM_USER+1 定义一个常量,呆会映射到响应函数上 //把下面代码与原消息映射比较添加 BEGIN_MESSAGE_MAP(CDemoDlg, CDialog) //{{AFX_MSG_MAP(CDemoDlg) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_TEST, OnTest) ON_MESSAGE(WM_NOTIFYICON, OnNotifyIcon)//响应托盘点击响应函数 ON_COMMAND(ID_SHOW, OnShow)//显示 ON_COMMAND(ID_EXIT, OnExit)//退出 //}}AFX_MSG_MAP END_MESSAGE_MAP() //下面afx_msg知道添加在哪不,在.h的声明文件里, //你会发现有类似这样的地方就添进去就行了(其实定义函数也一样, //afx_msg只是让向导用的,对编译器来说没太大的意义,上下两步很重要, //不然你会收到明明定义的却说没定义) afx_msg void OnTest(); afx_msg void OnNotifyIcon(WPARAM wParam, LPARAM lParam); afx_msg void OnShow(); afx_msg void OnExit();
三个小函数的实现
void CDemoDlg::OnTest(){ //点击界面按纽时触发 //隐藏窗口 ShowWindow(SW_HIDE); //在任务栏中添加图标 Shell_NotifyIcon(NIM_ADD, &m_Nid); } void CDemoDlg::OnShow(){//点击显示后显示 //删除任务栏中的图标 Shell_NotifyIcon(NIM_DELETE , &m_Nid); //显示窗口 ShowWindow(SW_SHOWNORMAL); UpdateWindow(); } void CDemoDlg::OnExit()//点右下角退出后退出 {//删除任务栏中的图标 Shell_NotifyIcon(NIM_DELETE, &m_Nid); //关闭窗口 SendMessage(WM_CLOSE); } //最后添加一个托盘响应函数 void CtestDlg::OnNotifyIcon(WPARAM wParam, LPARAM lParam) {//CtestDlg改成你相同的名字 if (wParam == 100){ //初始化时已经把ID设为100了 if (lParam == WM_LBUTTONDBLCLK){ //删除任务栏中的图标 Shell_NotifyIcon(NIM_DELETE, &m_Nid); //显示窗口 ShowWindow(SW_SHOWNORMAL); UpdateWindow(); } else if ((lParam == WM_LBUTTONDOWN) || (lParam == WM_RBUTTONDOWN)){ //左右键都能弹出菜单 //显示快捷子菜单 CMenu menu; if (!menu.LoadMenu(IDR_MENU)){ //去资源里添加个IDR_MENU //添加两个项,显示,退出ID为ID_EXIT and ID_SHOW return; } CPoint point; GetCursorPos(&point); SetForegroundWindow(); CMenu* pSubMenu = menu.GetSubMenu(0); if (pSubMenu == NULL){ return; } pSubMenu->TrackPopupMenu(TPM_LEFTBUTTON | TPM_RIGHTBUTTON, point.x, point.y, this, NULL); //PostMessage(WM_NULL, 0, 0); //这句空消息可发可不发 } } }
还有一点,若说StrCpy未定义,添加#include "Shlwapi.h"
最后说一点:出错没事,你要跟着错误一点点改,这样你也能学到东西,多用脑子,你要能把这些都解决了,以后对你的成长有很大的作用,不会的也可以给我留言
也可以看看我做的,很粗糙但功能实现了
排版有点不忍直视,哈哈,将就着看吧,东西不少
C++最小化到托盘+运行唯一实例源码包下载(MFC)
TestTray.rar [登录雪炭网后可见]
原文在CSDN,我搬过来了,尊重原创,转载需注明出处,可以随便分享哦,好东西大家分享^-^。
版权声明:
作者信息(Author) :雪炭网 : 花花世界
原文链接(Hyperlink):https://snowcoal.com/article/406.html
原创内容,尊重版权,转载需注明出处;商业及其他特殊用途转载需原作者同意。
原文链接(Hyperlink):https://snowcoal.com/article/406.html
原创内容,尊重版权,转载需注明出处;商业及其他特殊用途转载需原作者同意。
上一篇:未来IT发展科幻大揭秘
确实是好东西,博主辛苦了,非常感谢您的无私~