[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没有提供这 ...
随机推荐
- maven工程导入eclipse后报错
原因:需要重新部署下tomcat环境 解决方式: 右击->属性:
- VMware S/4 HANA OP 1511虚拟机下载,64G内存限制解决方案
http://www.itpub.net/thread-2057212-1-1.html S4 HANA OP 1511 Scale Out
- WP之样式
1.定义资源 <Window.Resources> <!--下面用样式--> <Style x:Key="BigFontButtonStyle"> ...
- 利用URL重写隐藏复杂的URL
第一步:模拟映射页面 我们想在一个页面上点击guid.html链接,跳转到比较复杂URL的guid_{492f3e0b-848e-11da-9550-00e08161165f}.html页面.即定义一 ...
- 文档公式编辑神器-Snip
最近在重新学习统计学的一些基础知识,整理笔记的时候需要输入一些数学公式.从学校毕业之后,就没有在文档中插入过公式了.按照以前的经验,我把输入公式的方式分成两类. 所见即所得的方式,常见的就是微软wor ...
- [Xcode 实际操作]七、文件与数据-(11)数据持久化存储框架CoreData的使用:创建CoreData实体并插入数据
目录:[Swift]Xcode实际操作 本文将演示[CoreData]数据持久化存储框架的使用. 点击[Create a new Xcode project]创建一个新的项目 ->[Single ...
- IT兄弟连 JavaWeb教程 AJAX定义以及解决的问题
Ajax是"Asynchronous JavaScript And XML"的缩写(即:异步的JavaScript和XML),是一种实现无页面刷新获取服务器数据的混合技术,Ajax ...
- Python小世界:彻底搞懂Python一切皆对象!!!
前言 犹记得当初学习Python的时候,对于Python一切皆对象很是懵逼,因为Python是面向对象的动态型语言,而在函数及高阶函数的应用中,如若对于一切皆对象不是有很透彻的了解,基础不是那么牢固的 ...
- JS中substr与substring的区别
js中substr和substring都是截取字符串中子串,非常相近,可以有一个或两个参数. 语法:substr(start [,length]) 第一个字符的索引是0,start必选 length可 ...
- 黑马旅游网 ajax实现html页面共享