VC驿站

 找回密码
 加入驿站

QQ登录

只需一步,快速开始

有编程疑问吗?还请到提问专区发帖提问!
搜索
查看: 393|回复: 6

VC++高级班之窗口篇-[4]让程序只运行一个实例

[复制链接]
01_avatar_middle
online_admins admin 发表于 2018-2-23 00:48:42 | 显示全部楼层 |阅读模式
------------------------------------------ Begin ----------------------------------------
大家都看过或者使用过类似只运行一个实例的程序,比如:QQ游戏、部分浏览器 等等!
让一个程序只运行一个实例的方法有多种,但是原理都类似,也就是在程序创建后,有窗口的程序在窗口创建前,
检查系统中是否已经设置了某些特定标志,是否创建了一些全局唯一的东西,或者让程序的多个实例都能看到的东西,
如果有则说明已经有一个实例在运行了,则当前程序通知用户如何如何,然后程序退出,当然方法有很多种,各有各的优缺点!

①、创建互斥体 Mutex 法:
但是单纯的使用互斥体的话不能取得已经创建的实例窗口局柄,因此无法激活已经启动的实例窗口;
  1. HANDLE m_hMutex = ::CreateMutex(NULL, FALSE, _T("{6668BB0A-DE0C-499d-8520-79653FF9B2EB}"));
  2. if ( GetLastError() == ERROR_ALREADY_EXISTS )
  3. {
  4.         AfxMessageBox(_T("已经有一个实例正在运行中……"));
  5.         CloseHandle(m_hMutex);
  6.         m_hMutex = NULL;
  7.         return FALSE;
  8. }
  9. //其他代码,比如对话框的创建及弹出等等

  10. if (m_hMutex)
  11. {
  12.         CloseHandle(m_hMutex);
  13.         m_hMutex = NULL;
  14. }
复制代码


===================================================
②、通过 FindWindow 进行窗口的查找,若发现则说明已经运行过一个实例,并将其窗口激活:
  1. HWND hWnd = ::FindWindow(_T("#32770"), _T("DlgTest"));
  2. if (hWnd != NULL)
  3. {
  4.         AfxMessageBox(_T("已经有一个实例正在运行中……"));
  5.         ::ShowWindow(hWnd, SW_NORMAL);
  6.         ::SetForegroundWindow(hWnd);
  7.         return FALSE;
  8. }
复制代码

此种方法不是很好,如果窗口标题改变了或者每个窗口实例的标题不一样,就找不到了!

===================================================
③、设置窗口属性 SetProp + EnumWindows 法!
1、加入全局变量的定义及枚举窗口函数:
  1. TCHAR g_szPropName[] = _T("{12AA5160-5215-435b-AE3C-60C9E65615CE}");
  2. HANDLE g_hValue = (HANDLE)9527;

  3. BOOL CALLBACK EnumWndProc(HWND hwnd, LPARAM lParam)
  4. {
  5.         HANDLE hProp = GetProp(hwnd, g_szPropName);
  6.         if(hProp == g_hValue) {
  7.                 *(HWND *)lParam = hwnd;
  8.                 return FALSE;
  9.         }
  10.         return TRUE;
  11. }
复制代码


2、窗口的枚举以及属性的添加:
  1. //OnInitDialog() 中加入以下代码:
  2. HWND hPreWnd = NULL;
  3. ::EnumWindows(EnumWndProc, (LPARAM)&hPreWnd);
  4. if (hPreWnd != NULL) {
  5.         AfxMessageBox(_T("已经有一个实例正在运行中……"));
  6.         ::ShowWindow(hPreWnd, SW_NORMAL);
  7.         ::SetForegroundWindow(hPreWnd);
  8.         ExitProcess(0);
  9.         return FALSE;
  10. }
  11. ::SetProp(m_hWnd, g_szPropName, g_hValue);
复制代码


3、窗口属性的删除:
OnDestroy() 函数中加入以下代码:
::RemoveProp(m_hWnd, g_szPropName);

===================================================
④、使用全局共享变量的共享节法实现单实例运行;
1、新建共享节:
  1. #pragma data_seg("Shared")
  2. HWND hPreWnd = NULL;
  3. #pragma data_seg()
  4. #pragma comment(linker, "/Section:Shared,RWS")
复制代码


2、OnInitDialog() 函数中加入以下代码:
  1. if (hPreWnd == NULL) {
  2.         hPreWnd = m_hWnd;
  3. } else {
  4.         AfxMessageBox(_T("已经有一个实例正在运行中……"));
  5.         ::ShowWindow(hPreWnd, SW_NORMAL);
  6.         ::SetForegroundWindow(hPreWnd);
  7.         ExitProcess(0);
  8.         return FALSE;
  9. }
复制代码


===================================================
⑤、互斥体+自定义广播系统消息法;
1、系统消息的注册:
  1. #define REG_MSG (_T("{7510EF00-BADA-48de-A6CE-5FBC817616DD}"))
  2. UINT WM_ACTIVE_MSG = ::RegisterWindowMessage(REG_MSG);
复制代码


2、发现实例后,进行消息的广播:
InitInstance() 函数中添加如下代码:

  1. HANDLE m_hMutex = ::CreateMutex(NULL, FALSE, _T("{6668BB0A-DE0C-499d-8520-79653FF9B2EB}"));
  2. if ( GetLastError() == ERROR_ALREADY_EXISTS ){
  3.         AfxMessageBox(_T("已经有一个实例正在运行中……"));
  4.         CloseHandle(m_hMutex);
  5.         m_hMutex = NULL;

  6.         DWORD dwRecipients = BSM_APPLICATIONS;
  7.         ::BroadcastSystemMessage(BSF_NOHANG, &dwRecipients, WM_ACTIVE_MSG, 0, 0);

  8.         return FALSE;
  9. }
  10. //其他窗口创建之类的代码
  11. if (m_hMutex) {
  12.         CloseHandle(m_hMutex);
  13.         m_hMutex = NULL;
  14. }
复制代码


3、窗口类中全局变量的作用域扩展:
  1. extern UINT WM_ACTIVE_MSG;
复制代码


4、窗口类中自定义消息的响应:
  1. afx_msg LRESULT OnActiveMsg(WPARAM wParam, LPARAM lParam);
  2. ON_REGISTERED_MESSAGE(WM_ACTIVE_MSG, &CDlgTestDlg::OnActiveMsg)
  3. LRESULT CDlgTestDlg::OnActiveMsg(WPARAM wParam, LPARAM lParam)
  4. {
  5.         ::ShowWindow(m_hWnd, SW_NORMAL);
  6.         ::SetForegroundWindow(m_hWnd);
  7.         return TRUE;
  8. }
复制代码

------------------------------------- End -------------------------------------------

相关课程演示细节还请观看视频教程!
本套教程由VC驿站原创,提供视频教程+售后答疑服务!
教程介绍及详情请见:http://www.cctry.com/static/vip/index.html
VC驿站Vip会员详情请见:http://www.cctry.com/static/vip/index.html





上一篇:VC++高级班之窗口篇-[3]窗口的枚举与查找
下一篇:VC++高级班之窗口篇-[5]Windows消息的发送

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你已经在论坛发帖求助,并且从坛友或者管理的回复中解决了问题,请编辑帖子并把分类改成【已解决】

如何回报帮助你解决问题的坛友?可以给对方加【热心】【驿站币】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

51_avatar_middle
在线会员 954624 发表于 2018-2-23 16:02:29 | 显示全部楼层
这是?把以前的教程再介绍一遍?

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你已经在论坛发帖求助,并且从坛友或者管理的回复中解决了问题,请编辑帖子并把分类改成【已解决】

如何回报帮助你解决问题的坛友?可以给对方加【热心】【驿站币】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

回复 支持 反对

使用道具 举报

01_avatar_middle
ico_lz  楼主| admin 发表于 2018-2-23 22:57:46 | 显示全部楼层
954624 发表于 2018-2-23 16:02
这是?把以前的教程再介绍一遍?


嗯,再介绍一下,做下宣传推广,也更好的让搜索引擎收录下!

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你已经在论坛发帖求助,并且从坛友或者管理的回复中解决了问题,请编辑帖子并把分类改成【已解决】

如何回报帮助你解决问题的坛友?可以给对方加【热心】【驿站币】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

回复 支持 反对

使用道具 举报

51_avatar_middle
在线会员 954624 发表于 2018-2-25 07:51:40 | 显示全部楼层
admin 发表于 2018-2-23 22:57
嗯,再介绍一下,做下宣传推广,也更好的让搜索引擎收录下!

有没有打算做个自绘的教程啊

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你已经在论坛发帖求助,并且从坛友或者管理的回复中解决了问题,请编辑帖子并把分类改成【已解决】

如何回报帮助你解决问题的坛友?可以给对方加【热心】【驿站币】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

回复 支持 反对

使用道具 举报

01_avatar_middle
ico_lz  楼主| admin 发表于 2018-2-26 00:09:52 | 显示全部楼层
954624 发表于 2018-2-25 07:51
有没有打算做个自绘的教程啊

《VC++基础班》最后一课有给大家讲解如何自绘ListCtrl 控件,算是以这个为例子给大家讲解了自绘的原理。

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你已经在论坛发帖求助,并且从坛友或者管理的回复中解决了问题,请编辑帖子并把分类改成【已解决】

如何回报帮助你解决问题的坛友?可以给对方加【热心】【驿站币】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

回复 支持 反对

使用道具 举报

51_avatar_middle
在线会员 954624 发表于 2018-2-26 12:45:17 | 显示全部楼层
admin 发表于 2018-2-26 00:09
《VC++基础班》最后一课有给大家讲解如何自绘ListCtrl 控件,算是以这个为例子给大家讲解了自绘的原理。

使用GDI、GDI+  自绘界面那样

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你已经在论坛发帖求助,并且从坛友或者管理的回复中解决了问题,请编辑帖子并把分类改成【已解决】

如何回报帮助你解决问题的坛友?可以给对方加【热心】【驿站币】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 加入驿站 qq_login

本版积分规则

关闭

站长提醒上一条 /1 下一条

QQ
QQ在线咨询
联系电话
13591366679
手机扫一扫 关注本站精彩内容
wxqrcode

QQ|小黑屋|手机版|VC驿站 ( 辽ICP备09019393号tongdun|网站地图wx_jqr

GMT+8, 2018-10-20 17:46

Powered by Discuz! X3.4

© 2009-2018 cctry.com

快速回复 返回顶部 返回列表