[VC]在VC++中实现让程序只运行一个实例的方法且实现该实例
方法一:
有时候在开发应用程序时,希望控制程序运行唯一的实例。例如,最常用的mp3播放软 件Winamp,由于它需要独占计算机中的音频设备,因此该程序只允许自身运行唯一的一个例程。在Visual C++的开发实践中,对于16位的Windows系统,应用程序的hPrevInstance句柄保存了应用程序上一个运行的实例,可以用该值来检查是否 有实例运行;然而在32位Windows系统下,这个值总是NULL,所以无法利用该值来实现程序运行唯一实例。本实例给出了解决这个问题的简单办法,只 要将程序中稍微改动一下就可以了。
一、 实现方法
对于具有窗口的应用程序,可以用静态函数CWnd::FindWindow()查找固定窗口,来判断程序是否已经运行。函数原型为:
CWnd* PASCAL FindWindow( LPCTSTR lpszClassName, LPCTSTR lpszWindowName );
这个函数有两个参数,第一个是要找的窗口的类,第二个是要找的窗口的标题。在搜索的时候不一定两者都知道,但至少要知道其中的一个。有的窗口的标题是比
较容易得到的,如"计算器",所以搜索时应使用标题进行搜索。但有的软件的标题不是固定的,如"记事本",如果打开的文件不同,窗口标题也不同,这时使用
窗口类搜索就比较方便。如果找到了满足条件的窗口,这个函数返回该窗口的指针,否则返回值为NULL。
考虑到程序的健壮性,我们还需要判断窗口是否处于最小化状态、是否有弹出式子窗口,这就需要使用CWnd:: GetLastActivePopup()、CWnd::IsIconic()函数,它们的原型分别为:
CWnd* GetLastActivePopup( )
该函数返回一个指定父窗口中最近激活过的弹出式窗口的指针。如果窗口本身是刚刚激活的,或窗口不包含任何弹出窗口,那么该函数返回指向父窗口自身的指针。
BOOL IsIconic( )
该函数用来判断当前窗口是否处于最小化状态,如果窗口处于最小化状态,函数返回值为True,否则返回Flase。
对于处于最小化状态的窗口,可以调用CWnd::ShowWindow( int nCmdShow )恢复窗口的正常状态,该函数的原型为:
BOOL ShowWindow( int nCmdShow )
如窗口之前是可见的,函数调用后返回True,否则返回False。参数nCmdShow的值可以为以下任意个常数:
SW_HIDE:隐藏窗口,活动状态给令一个窗口;
SW_MINIMIZE:最小化窗口,活动状态给另一个窗口;
SW_RESTORE:用原来的大小和位置显示一个窗口,同时令其进入活动状态;
SW_SHOW:用当前的大小和位置显示一个窗口,同时令其进入活动状态;
SW_SHOWMAXIMIZED:最大化窗口,并将其激活;
SW_SHOWMINIMIZED:最小化窗口,并将其激活;
SW_SHOWMINNOACTIVE:最小化一个窗口,同时不改变活动窗口;
SW_SHOWNA:用当前的大小和位置显示一个窗口,不改变活动窗口;
SW_SHOWNOACTIVATE:用最近的大小和位置显示一个窗口,不改变活动窗口;
SW_SHOWNORMAL:与SW_RESTORE相同;
最后不要忘记了用CWnd:: SetForegroundWindow()函数将弹出窗口设置为桌面的最前端。
有了上面的知识,我们就可以修改程序中应用程序类的InitInstance()函数,如果程序已经运行,也即是可以发现相应的程序窗口,那么就显示该窗口,InitInstance()函数就返回False,程序提前退出,否则就正常运行。
二、 编程步骤
1、 启动Visual C++6.0,生成一个基于对话框的应用程序,程序命名为"Instance";
2、 修改程序的InitInstance()函数;
3、 添加代码,编译运行程序;
三、 程序代码
/////////////////////////////////////////////////////////////////////////////
// CInstanceApp initialization
BOOL CInstanceApp::InitInstance()
{
if (!FirstInstance())
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
CInstanceDlg dlg;
m_pMainWnd = &dlg;
int nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
// TODO: Place code here to handle when the dialog is
// dismissed with OK
}
else if (nResponse == IDCANCEL)
{
// TODO: Place code here to handle when the dialog is
// dismissed with Cancel
}
// Since the dialog has been closed, return FALSE so that we exit the
// application, rather than start the application's message pump.
return FALSE;
}
BOOL CInstanceApp::FirstInstance()
{
CWnd *pWndPrev, *pWndChild;
// Determine if another window with our class name and Window title exists...
// The title "Instance " is set up latter, in the InitDialog function.
if (pWndPrev = CWnd::FindWindow(NULL, "Instance "))
{
pWndChild = pWndPrev- >GetLastActivePopup();
// if so, does it have any popups?
if (pWndPrev- >IsIconic())
pWndPrev- >ShowWindow(SW_RESTORE);
// If iconic, restore the main window
pWndChild- >SetForegroundWindow();
// Bring the window to the foreground
return FALSE;
}
else
return TRUE; // First instance. Proceed as normal.
}
四、 小结
上述方法虽然实现起来很简单,但是它对于无窗口的应用程序却无能为力。为了解决这个问题,可以通过动态连接库DLL实现更通用的控制程序运行的方法。在
DLL中使用#pragma data_seg指令实现共享数据段,在该数据段中定义一个变量long
m_nRun,并设置其初始值为-1,同时还要在DLL的入口点函数DllMain返回成功值的语句前添加语句m_nRun++,意思是在应用程序启动连
接DLL成功时对已经运行的实例进行计数,然后在DLL中导出一个函数来返回该变量的值。最后将应用程序的工程设置为依赖于该DLL的工程,在应用程序根
据DLL中的m_nRun变量的值来判断是否程序已经运行了。
方法二:
#define UNIQE_NAME "{1AB792D6-EAF2-3267-9A84-9135681127A4}"
#define GIS_MSG "{D48CA993-4925-41cb-8F59-ABAAAFCEF797}"
const UINT ID_GIS_INSTANCE = ::RegisterWindowMessage(GIS_MSG); //注册消息
// 确保程序只有一个实例在运行
m_hOneInstance = ::CreateMutex(NULL, FALSE, UNIQE_NAME);
if (GetLastError() == ERROR_ALREADY_EXISTS )//如果存在前一个
{
//发送消息,激活实例
DWORD dwRecipients = BSM_APPLICATIONS;
::BroadcastSystemMessage(BSF_NOHANG, &dwRecipients,
ID_GIS_INSTANCE, // registered window message
0, 0); // user defined parameters
return FALSE;
}
ON_REGISTERED_MESSAGE(ID_GIS_INSTANCE, OnGISInstance)
LRESULT CMainFrame::OnGISInstance(WPARAM wParam, LPARAM lParam)
{
theApp.m_pMainWnd->ShowWindow(SW_SHOWMAXIMIZED);
theApp.m_pMainWnd->SetForegroundWindow();
::AfxMessageBox("本程序已经有一个实例在运行了。");
return 0;
}
[VC]在VC++中实现让程序只运行一个实例的方法且实现该实例的更多相关文章
- [转]Delphi中,让程序只运行一次的方法
program onlyRunOne; uses Forms,Windows,SysUtils, Dialogs, Unit1 in 'Unit1.pas' {Form1}; {$R *.res} v ...
- vc++高级班之窗口篇[4]---让程序只运行一个实例
大家都看过或者使用过类似只运行一个实例的程序,比如:QQ游戏.部分浏览器 等等! 让一个程序只运行一个实例的方法有多种,但是原理都类似,也就是在程序创建后,有窗口的程序在窗口创建前, 检查系统中是 ...
- VC 实现程序只运行一个实例,并激活已运行的程序
转载:http://blog.sina.com.cn/s/blog_4b44e1c00100bh69.html 进程的互斥运行:CreateMutex函数实现只运行一个程序实例 正常情况下,一个进程的 ...
- 如何让Windows程序只运行一个程序实例?
要实现VC++或者MFC只运行一个程序实例,一般采用互斥量来实现,即首先用互斥量封装一个只运行一个程序实例的函数接口: HANDLE hMutex = NULL; void MainDlg::RunS ...
- C#让应用程序只运行一个实例的几种方法
一 判断是否有相同的实例已经运行 1 根据“Mutex”判断是否有相同的实例在运行 /// <returns>已有实例运行返回true,否则为false</returns>pu ...
- VC程序只运行一个实例,并在打开多个时激活原窗口
(一)单文档应用程序 1.在应用程序类C~~App::InitInstance()函数中判断是否已有一个应用程序实例正在运行 BOOL C~~App::InitInstance() { . ...
- Winform(C#)限制程序只运行一个实例
C#控制只运行开启一个程序 在这个例子中不需要调用ReleaseMutex,mutex会在程序结束时自动释放.为了防止mutex过早释放,在程序的最后调用下GC.KeepAlive (mutex). ...
- 让程序只运行一个实例(Delphi篇)(三种方法,其中使用全局原子的方法比较有意思)
Windows 下一个典型的特征就是多任务,我们可以同时打开多个窗口进行操作,也可以同时运行程序的多个实例,比如可以打开许多个资源管理器进行文件的移动复制操作.但有时出于某种考虑(比如安全性),我们要 ...
- Java程序只运行一个实例[转]
如果希望你的Java程序只能存在一个实例,可以参考下面的用法. 原文链接:http://blog.csdn.net/yaerfeng/article/details/7264729 Java没有提供这 ...
随机推荐
- JAVA学习笔记——(一)
今日内容介绍 1.Java开发环境搭建 2.HelloWorld案例 3.注释.关键字.标识符 4.数据(数据类型.常量) 01java语言概述 * A: java语言概述 * a: Java是sun ...
- CRC原理总结
CRC常用于判断文件在传输过程中文件内容是否被更改以及其他的一些加密算法,在Java中,CRC32 工具类提供给我们使用. 1.CRC校验具体原理如下: 在要发送的数据帧后面附加一个数(这个就是用来校 ...
- GridView 中RowDataBound 获取绑定后的各个字段的值
protected void GridView_dept_RowDataBound(object sender, GridViewRowEventArgs e) { if (e.Row.RowType ...
- LayUI 子父窗体的交互
---恢复内容开始--- 收到的工作是将一个ERP的窗体程序改为网页实现,所以就肯定需要弹框来选择(如:物料编码.部门.业务员等等) 本文采取的前段框架是LayUI. layUI的官网API网址:ht ...
- tcpkill工作原理分析
此文已由作者张耕源授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 日常工作生活中大家在维护自己的服务器.VPS有时会碰到这样的情况:服务器上突然出现了许多来自未知ip的网络连 ...
- QMYSQL driver not loaded 的原理和解决办法
转:http://blog.csdn.net/m15814478834/article/details/49902077 最近使用Qt遇到了"QMYSQL driver not loaded ...
- Unity5 AssetBundle资源管理架构设计
http://blog.csdn.net/qq_19399235/article/details/51702964 1:Unity5 资源管理架构设计(2017.4.22版本) 2:Android 热 ...
- [Swift]LeetCode1081. 不同字符的最小子序列 | Smallest Subsequence of Distinct Characters
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...
- 爬虫基础(1):urllib库
urllib库 urllib库是python中的一个基本网络请求库.用于模拟浏览器的行为,向指定服务器发送请求,并接收返回的数据. 在python3中所有的网络请求相关函数都集中在urllib.req ...
- JPA @MappedSuperclass注解的使用说明(转)
(2011-11-07 11:37:30) 转载▼ http://blog.sina.com.cn/s/blog_7085382f0100uk4p.html 标签: 杂谈 基于代码复用和模型分离的 ...