当前位置: 首页 > news >正文

C++ MFC 只启动一个程序实例 唤醒之前的实例(完整源码)

初级代码游戏的专栏介绍与文章目录-CSDN博客

         很多时候我们希望只允许启动一个程序实例,如果再次运行,就唤醒之前的实例。

目录

1 概述

2 相关技术介绍

2.1 互斥对象

2.2 查找窗口

2.3 唤醒窗口


1 概述

        技术上并不难,涉及到以下几个技术细节:

  1. 使用互斥对象,确保检查程序是否已经启动时没有并发错误。
  2. 查找之前已经运行的程序,可以通过窗口名称查找,也可以通过共享文件交互
  3. 控制之前已经运行的程序,可以通过发送窗口消息,也可以通过共享文件交互

        窗口程序通过窗口机制,查找和发消息都是操作系统的标准功能,如果 使用了配置文件,通过文件来交互也是可以的,只不过要定时查询,实时性没有发消息好。

2 相关技术介绍

        下面介绍相关代码:

2.1 互斥对象

	HANDLE hOneInstance;hOneInstance = ::CreateMutex(NULL, FALSE, L"自定义的名字");if (GetLastError() == ERROR_ALREADY_EXISTS){//在这里处理已经存在的情形//查找窗口、唤醒窗口,然后退出}//正常启动

        互斥对象是系统对象,本例中我们并不需要更多功能,只要检测创建是否成功即可。因为,互斥对象所有句柄被释放后就会被销毁,程序不退出,下一个程序创建会失败,程序退出后下一个就可以成功创建。对于我们的目的而言锁定互斥对象是不必要的。

        CreateMutes原型如下:

HANDLE CreateMutexA([in, optional] LPSECURITY_ATTRIBUTES lpMutexAttributes,[in]           BOOL                  bInitialOwner,[in, optional] LPCSTR                lpName
);

        第一个参数涉及到权限,可以设置为NULL,第二个参数指示创建完成是不是要立即锁定,第三个参数是名字,可以不设置,设置的话不能和已经存在的内核对象同名,所有种类的内核对象共享同一个名字空间。

2.2 查找窗口

		HWND hWnd = FindWindow(NULL, TEXT("窗口标题"));if (IsWindow(hWnd)){//遍历处理所有同名窗口!!!while(IsWindow(hWnd)){//在这里处理窗口//查找下一个hWnd = FindWindowEx(NULL,hWnd,NULL,TEXT("窗口标题"));}}

        查找窗口的关键点是窗口标题必须正确,所以最好把窗口标题单独定义出来,并在窗口初始化里面专门设定一次,而且不要在程序里面修改窗口标题。这其实没法从技术上预防,程序的任何地方都可以随意修改窗口标题,如果没法掌控全部源代码,那就只好走文件控制的方式了。

        文件控制就是把窗口句柄写入文件,每次启动去文件里面读,读不到就是还没有程序实例在运行。

        这里写成循环是因为理论上可能有相同标题的窗口,需要这两个函数配合才能遍历所有同名窗口。

HWND FindWindowA([in, optional] LPCSTR lpClassName,[in, optional] LPCSTR lpWindowName
);

        FindWindow用窗口类名和/或窗口标题查找窗口,大部情况下我们只用窗口标题来查找。

HWND FindWindowExA([in, optional] HWND   hWndParent,[in, optional] HWND   hWndChildAfter,[in, optional] LPCSTR lpszClass,[in, optional] LPCSTR lpszWindow
);

        FindWindowEx查找子窗口。 

2.3 唤醒窗口

				// 显示if(!::ShowWindow(hWnd, SW_NORMAL)){//出错} // 激活if(!::SetForegroundWindow(hWnd)){//出错}

        这两句代码嵌入到之前查找窗口的循环里面即可将之前的实例的窗口显示到前端。

BOOL SetForegroundWindow([in] HWND hWnd
);

        这个函数的效果是把窗口放到前端并激活,输入焦点将设置到这个窗口中。

        如果想让窗口的标题栏闪烁,用这个API即可:

BOOL FlashWindow([in] HWND hWnd,[in] BOOL bInvert
);

        第二个参数为FALSE将保持之前的活动或非活动状态,为TRUE则切换状态。这个调用只闪烁一次,想多闪烁几次要用定时器来控制(不要用Sleep,会导致界面僵死)。

(这里是文档结束)

http://www.lryc.cn/news/327540.html

相关文章:

  • 2024多云管理平台CMP排名看这里!
  • MySQL 数据库的日志管理、备份与恢复
  • 一、Go开发环境搭建
  • 包子凑数(蓝桥杯,闫氏DP分析法)
  • Java八股文(JVM)
  • 云硬盘扩容后将空间增加到原有分区的解决方案
  • Tensorflow2.0笔记 - metrics做损失和准确度信息度量
  • LeetCode 面试经典150题 290.单词规律
  • 【CASS精品教程】CASS中计算四参数和七参数(以RTK数据为例)
  • 什么是RISC-V?开源 ISA 如何重塑未来的处理器设计
  • 展馆设计中展示有哪些要求
  • python实战之PyQt5桌面软件
  • Switch 和 PS1 模拟器:3000+ 游戏随心玩 | 开源日报 No.174
  • 免费翻译pdf格式论文
  • 3D产品可视化SaaS
  • 浙大版《C语言程序设计(第4版)》题目集-习题3-5 三角形判断
  • Java封装、继承、多态和抽象深度解析
  • 深度学习每周学习总结P3(天气识别)
  • 通过iOS网络抓包工具实现移动应用数据安全监控
  • Stable Diffusion WebUI 生成参数:脚本(Script)——提示词矩阵、从文本框或文件载入提示词、X/Y/Z图表
  • synchronized和volatile的原理及应用
  • Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单实战案例 之九 简单闪烁效果
  • 11 开源鸿蒙OpenHarmony轻量系统源码分析
  • 专题:一个自制代码生成器(嵌入式脚本语言)之应用实例
  • Appium设备交互API
  • Qlib-Server部署
  • CMC学习系列 (4):β段CMC可以作为一种中风治疗的生物标志物和治疗靶点
  • jmeter中参数加密
  • YOLOv8改进 | 检测头篇 | 2024最新HyCTAS模型提出SAttention(自研轻量化检测头 -> 适用分割、Pose、目标检测)
  • verilog设计-cdc:多比特信号跨时钟域(DMUX)