VC编程之vc+窗口篇[4]---让程序只运行一个实例
小标 2018-09-04 来源 : 阅读 777 评论 0

摘要:本文主要向大家介绍了VC编程之vc+窗口篇[4]---让程序只运行一个实例,通过具体的内容向大家展示,希望对大家学习VC编程有所帮助。

本文主要向大家介绍了VC编程之vc+窗口篇[4]---让程序只运行一个实例,通过具体的内容向大家展示,希望对大家学习VC编程有所帮助。            

大家都看过或者使用过类似只运行一个实例的程序,比如:QQ游戏、部分浏览器 等等!
让一个程序只运行一个实例的方法有多种,但是原理都类似,也就是在程序创建后,有窗口的程序在窗口创建前,
检查系统中是否已经设置了某些特定标志,是否创建了一些全局唯一的东西,或者让程序的多个实例都能看到的东西,
如果有则说明已经有一个实例在运行了,则当前程序通知用户如何如何,然后程序退出,当然方法有很多种,各有各的优缺点!
 
①、创建互斥体 Mutex 法:
但是单纯的使用互斥体的话不能取得已经创建的实例窗口局柄,因此无法激活已经启动的实例窗口;
HANDLE m_hMutex = ::CreateMutex(NULL, FALSE, _T("{6668BB0A-DE0C-499d-8520-79653FF9B2EB}"));
if ( GetLastError() == ERROR_ALREADY_EXISTS ){
 AfxMessageBox(_T("已经有一个实例正在运行中……"));
 CloseHandle(m_hMutex);
 m_hMutex = NULL;
 return FALSE;
}
//其他代码,比如对话框的创建及弹出等等
 
if (m_hMutex) {
 CloseHandle(m_hMutex);
 m_hMutex = NULL;
}
 
===================================================
②、通过 FindWindow 进行窗口的查找,若发现则说明已经运行过一个实例,并将其窗口激活:
HWND hWnd = ::FindWindow(_T("#32770"), _T("DlgTest"));
if (hWnd != NULL) {
 AfxMessageBox(_T("已经有一个实例正在运行中……"));
 ::ShowWindow(hWnd, SW_NORMAL);
 ::SetForegroundWindow(hWnd);
 return FALSE;
}
此种方法不是很好,如果窗口标题改变了或者每个窗口实例的标题不一样,就找不到了!
 
===================================================
③、设置窗口属性 SetProp + EnumWindows 法!
1、加入全局变量的定义及枚举窗口函数:
TCHAR g_szPropName[] = _T("{12AA5160-5215-435b-AE3C-60C9E65615CE}");
HANDLE g_hValue = (HANDLE)9527;
 
BOOL CALLBACK EnumWndProc(HWND hwnd, LPARAM lParam)
{
 HANDLE hProp = GetProp(hwnd, g_szPropName);
 if(hProp == g_hValue) {
  *(HWND *)lParam = hwnd;
  return FALSE;
 }
 return TRUE;
}
 
2、窗口的枚举以及属性的添加:
//OnInitDialog() 中加入以下代码:
HWND hPreWnd = NULL;
::EnumWindows(EnumWndProc, (LPARAM)&hPreWnd);
if (hPreWnd != NULL) {
 AfxMessageBox(_T("已经有一个实例正在运行中……"));
 ::ShowWindow(hPreWnd, SW_NORMAL);
 ::SetForegroundWindow(hPreWnd);
 ExitProcess(0);
 return FALSE;
}
::SetProp(m_hWnd, g_szPropName, g_hValue);
 
3、窗口属性的删除:
OnDestroy() 函数中加入以下代码:
::RemoveProp(m_hWnd, g_szPropName);
 
===================================================
④、使用全局共享变量的共享节法实现单实例运行;
1、新建共享节:
#pragma data_seg("Shared")
HWND hPreWnd = NULL;
#pragma data_seg()
#pragma comment(linker, "/Section:Shared,RWS")
 
2、OnInitDialog() 函数中加入以下代码:
if (hPreWnd == NULL) {
 hPreWnd = m_hWnd;
} else {
 AfxMessageBox(_T("已经有一个实例正在运行中……"));
 ::ShowWindow(hPreWnd, SW_NORMAL);
 ::SetForegroundWindow(hPreWnd);
 ExitProcess(0);
 return FALSE;
}
 
===================================================
⑤、互斥体+自定义广播系统消息法;
1、系统消息的注册:
#define REG_MSG (_T("{7510EF00-BADA-48de-A6CE-5FBC817616DD}"))
UINT WM_ACTIVE_MSG = ::RegisterWindowMessage(REG_MSG);
 
2、发现实例后,进行消息的广播:
InitInstance() 函数中添加如下代码:
 
HANDLE m_hMutex = ::CreateMutex(NULL, FALSE, _T("{6668BB0A-DE0C-499d-8520-79653FF9B2EB}"));
if ( GetLastError() == ERROR_ALREADY_EXISTS ){
 AfxMessageBox(_T("已经有一个实例正在运行中……"));
 CloseHandle(m_hMutex);
 m_hMutex = NULL;
 
 DWORD dwRecipients = BSM_APPLICATIONS;
 ::BroadcastSystemMessage(BSF_NOHANG, &dwRecipients, WM_ACTIVE_MSG, 0, 0);
 
 return FALSE;
}
//其他窗口创建之类的代码
if (m_hMutex) {
 CloseHandle(m_hMutex);
 m_hMutex = NULL;
}
 
3、窗口类中全局变量的作用域扩展:
extern UINT WM_ACTIVE_MSG;
 
4、窗口类中自定义消息的响应:
afx_msg LRESULT OnActiveMsg(WPARAM wParam, LPARAM lParam);
ON_REGISTERED_MESSAGE(WM_ACTIVE_MSG, &CDlgTestDlg::OnActiveMsg)
LRESULT CDlgTestDlg::OnActiveMsg(WPARAM wParam, LPARAM lParam)
{
 ::ShowWindow(m_hWnd, SW_NORMAL);
 ::SetForegroundWindow(m_hWnd);
 return TRUE;
}
------------------------------------- End -------------------------------------------

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标编程语言VC/MFC频道!

本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 1 不喜欢 | 0
看完这篇文章有何感觉?已经有1人表态,100%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程