大家都看过或者使用过类似只运行一个实例的程序,比如: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 实现程序只运行一个实例,并激活已运行的程序
转载:http://blog.sina.com.cn/s/blog_4b44e1c00100bh69.html 进程的互斥运行:CreateMutex函数实现只运行一个程序实例 正常情况下,一个进程的 ...
- VC程序只运行一个实例,并在打开多个时激活原窗口
(一)单文档应用程序 1.在应用程序类C~~App::InitInstance()函数中判断是否已有一个应用程序实例正在运行 BOOL C~~App::InitInstance() { . ...
- [VC]在VC++中实现让程序只运行一个实例的方法且实现该实例
方法一: 有时候在开发应用程序时,希望控制程序运行唯一的实例.例如,最常用的mp3播放软 件Winamp,由于它需要独占计算机中的音频设备,因此该程序只允许自身运行唯一的一个例程.在Visual C+ ...
- 让程序只运行一个实例(Delphi篇)(三种方法,其中使用全局原子的方法比较有意思)
Windows 下一个典型的特征就是多任务,我们可以同时打开多个窗口进行操作,也可以同时运行程序的多个实例,比如可以打开许多个资源管理器进行文件的移动复制操作.但有时出于某种考虑(比如安全性),我们要 ...
- vc++高级班之多线程篇[6]---线程间的同步机制①
①.线程同步的必要性: int g_Num = 0; UINT __cdecl ThreadProc(LPVOID lpParameter) { for (int idx = 0; idx &l ...
- vc++高级班之多线程篇[7]---线程间的同步机制②
//示例代码: CStringArray g_ArrString; UINT __cdecl ThreadProc(LPVOID lpParameter) { int startIdx = (int ...
- VC只运行一个程序实例
方法有很多,以下只是提供一种用的多的 一. 单文档程序 在程序App类的InitInstance中添加如下代码 BOOL CDDZApp::InitInstance() { /*只运行一个实例*/ / ...
- C#cmd执行命令隐藏窗口,并保持程序一直运行
把要执行的cmd命令放入一个bat文件里,然后执行: //Process p = Process.Start(bPath); Process pro = new Process();pro.Start ...
- 深入浅出话VC++(1)——Windows程序内部运行机制
一.引言 要想熟练掌握Windows应用程序的开发,首先需要理解Windows平台下程序运行的内部机制,然而在.NET平台下,创建一个Windows桌面程序,只需要简单地选择Windows窗体应用程序 ...
随机推荐
- vue表单校验提交报错TypeError: Cannot read property 'validate' of undefined
TypeError: Cannot read property 'validate' of undefined at VueComponent.submitForm (plat_users.html: ...
- vue中v-show与v-if的区别
v-show 手段:通过设置DOM元素的display样式属性控制显隐: 编译过程:v-show只是简单的基于css切换: 编译条件:v-show是在任何条件下(首次条件是否为真)都被编译,然后被缓存 ...
- bootstrap实现checkbox全选、取消全选
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <!-- 最新版本的 ...
- 细说shiro之七:缓存
官网:https://shiro.apache.org/ 一. 概述 Shiro作为一个开源的权限框架,其组件化的设计思想使得开发者可以根据具体业务场景灵活地实现权限管理方案,权限粒度的控制非常方便. ...
- Python Thrift 简单示例
本文基于Thrift-0.10,使用Python实现服务器端,使用Java实现客户端,演示了Thrift RPC调用示例.Java客户端提供两个字符串参数,Python服务器端计算这两个字符串的相似度 ...
- java使用类数组 报错Exception in thread "main" java.lang.NullPointerException
源代码如下: Point[] points=new Point[n];//Point是一个类 for(int i=0;i<n;i++) { System.out.print("请输入x ...
- python随机数random模块
需要 import random x=random.random() 产生 0 到 1 之间的随机浮点数 结果 0.005570080000840916 x=random.randint(1 ...
- 推荐前端框架 & 模板
BootStrap Semantic UI Pure Amazeui(前后端都有,很丰富) amazeui http://tpl.amazeui.org AdminLTE AdminLTE https ...
- 关于vmvawe的光驱,iso镜像,挂载,卸载
勾选这个使用iso镜像文件,就相当于真实的环境下,将一张光盘插进了光驱里,然后再勾选启动时连接,那么在linux开机后,/dev/cdrom或者/dev/sr0(前者是后者的软连接)就表示这个硬件设备 ...
- react——获取数据ajax()、$.ajax()、fetch()、axios
ajax() import React from 'react'; import ReactDom from 'react-dom'; import ajax from './tool.js'; cl ...