方法一:

  有时候在开发应用程序时,希望控制程序运行唯一的实例。例如,最常用的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++中实现让程序只运行一个实例的方法且实现该实例的更多相关文章

  1. [转]Delphi中,让程序只运行一次的方法

    program onlyRunOne; uses Forms,Windows,SysUtils, Dialogs, Unit1 in 'Unit1.pas' {Form1}; {$R *.res} v ...

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

      大家都看过或者使用过类似只运行一个实例的程序,比如:QQ游戏.部分浏览器 等等! 让一个程序只运行一个实例的方法有多种,但是原理都类似,也就是在程序创建后,有窗口的程序在窗口创建前, 检查系统中是 ...

  3. VC 实现程序只运行一个实例,并激活已运行的程序

    转载:http://blog.sina.com.cn/s/blog_4b44e1c00100bh69.html 进程的互斥运行:CreateMutex函数实现只运行一个程序实例 正常情况下,一个进程的 ...

  4. 如何让Windows程序只运行一个程序实例?

    要实现VC++或者MFC只运行一个程序实例,一般采用互斥量来实现,即首先用互斥量封装一个只运行一个程序实例的函数接口: HANDLE hMutex = NULL; void MainDlg::RunS ...

  5. C#让应用程序只运行一个实例的几种方法

    一 判断是否有相同的实例已经运行 1 根据“Mutex”判断是否有相同的实例在运行 /// <returns>已有实例运行返回true,否则为false</returns>pu ...

  6. VC程序只运行一个实例,并在打开多个时激活原窗口

    (一)单文档应用程序   1.在应用程序类C~~App::InitInstance()函数中判断是否已有一个应用程序实例正在运行 BOOL C~~App::InitInstance() {     . ...

  7. Winform(C#)限制程序只运行一个实例

    C#控制只运行开启一个程序 在这个例子中不需要调用ReleaseMutex,mutex会在程序结束时自动释放.为了防止mutex过早释放,在程序的最后调用下GC.KeepAlive (mutex). ...

  8. 让程序只运行一个实例(Delphi篇)(三种方法,其中使用全局原子的方法比较有意思)

    Windows 下一个典型的特征就是多任务,我们可以同时打开多个窗口进行操作,也可以同时运行程序的多个实例,比如可以打开许多个资源管理器进行文件的移动复制操作.但有时出于某种考虑(比如安全性),我们要 ...

  9. Java程序只运行一个实例[转]

    如果希望你的Java程序只能存在一个实例,可以参考下面的用法. 原文链接:http://blog.csdn.net/yaerfeng/article/details/7264729 Java没有提供这 ...

随机推荐

  1. hdu1853 Cyclic Tour (二分图匹配KM)

    Cyclic Tour Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/65535 K (Java/Others)Total ...

  2. Redis使用的相关问题

    Redis用那些数据结构? 字符串类型String 字典Hash 列表List 集合Set 有序集合SortedSet HyperLogLog.Geo.Pub/Sub Redis Module.Blo ...

  3. Laravel框架的一些配置

    服务器的配置 1.在apache下的配置 配置httpd-conf:php5_module.rewrite_module.Listen 配置extra/httpd-vhost:端口.站点.域名.默认首 ...

  4. ue4-C++中加载一个蓝图类(二)-C++中绑定Blueprint武器

    editor中编辑好一个武器蓝图资源后,c++中create出这个武器,然后attach到一个人物身上. 思路:  写个c++基类,蓝图继承后编辑成武器或其他装备,然后c++用一个TSubclassO ...

  5. python translate maketrans 字符串替换

    string1='abcd-1234' print(string1.translate(string1.maketrans('abc','ABC'))) a='aeiou' b=' string2=' ...

  6. 大整数因子(高精mod)

    大整数的因子 总时间限制:  1000ms 内存限制:  65536kB 描述 已知正整数k满足2<=k<=9,现给出长度最大为30位的十进制非负整数c,求所有能整除c的k. 输入 一个非 ...

  7. VBA for AutoCAD

    Download the Microsoft Visual Basic for Applications Module (VBA) 2016 Downloads AutoCAD 2016 VBA mo ...

  8. Mac下通过homebrew安装maven

    1.安装Homebrew 将以下命令粘贴至终端 /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebr ...

  9. gui - tkinter 开发

    GUI 用户交互界面 tkinter 介绍 tkinter python自带的gui库,对图形图像处理库tk的封装 其他gui:pythonwin,wxpython,pyQT.. 概念介绍 组件:组成 ...

  10. C 语言实例 - 判断正数/负数

    C 语言实例 - 判断正数/负数 用户输入一个数字,判断该数字是正数还是负数或是零. 实例 #include <stdio.h> int main() { double number; p ...