44 [原创][基础][MFC篇][C++程序系统托盘与运行实例唯一实现] - 雪炭网

[原创][基础][MFC篇][C++程序系统托盘与运行实例唯一实现]2014-10-10 22:40:20

( 5人已投票,[高质量] )
分享:
31.3K

程序都要实现系统托盘功能,最小化到右下角的托盘是不是很酷,像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)

[原创][基础][MFC篇][C++程序系统托盘与运行实例唯一实现] TestTray.rar [登录雪炭网后可见]



原文在CSDN,我搬过来了,尊重原创,转载需注明出处,可以随便分享哦,好东西大家分享^-^。






头像

snowcoal
  • C++
  • 系统托盘
  • 运行唯一实例

收藏到我的私密空间

标题:[原创][基础][MFC篇][C++程序系统托盘与运行实例唯一实现]

作者:花花世界

你暂未登录,请登录后才可收藏至您的私密空间 确认取消
雪炭网

键盘操作 更便捷 -雪炭网雪中送炭-乐趣无限

如果本站的内容有幸帮助到了您,建议您了解一下当页的广告内容哦,我们的进步离不开您的支持,Thank you~