用VC++实现控制程序运行唯一实例

wxl我爱罗

wxl我爱罗

2016-02-19 19:05

岁数大了,QQ也不闪了,微信也不响了,电话也不来了,但是图老师依旧坚持为大家推荐最精彩的内容,下面为大家精心准备的用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相同;

(本文来源于图老师网站,更多请访问https://m.tulaoshi.com/bianchengyuyan/)

  最后不要忘记了用CWnd:: SetForegroundWindow()函数将弹出窗口设置为桌面的最前端。

  有了上面的知识,我们就可以修改程序中应用程序类的InitInstance()函数,如果程序已经运行,也即是可以发现相应的程序窗口,那么就显示该窗口,InitInstance()函数就返回False,程序提前退出,否则就正常运行。

(本文来源于图老师网站,更多请访问https://m.tulaoshi.com/bianchengyuyan/)

  二、 编程步骤

  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变量的值来判断是否程序已经运行了。

展开更多 50%)
分享

猜你喜欢

用VC++实现控制程序运行唯一实例

编程语言 网络编程
用VC++实现控制程序运行唯一实例

VC++6.0中控制运行唯一实例

C语言教程 C语言函数
VC++6.0中控制运行唯一实例

s8lol主宰符文怎么配

英雄联盟 网络游戏
s8lol主宰符文怎么配

控制程序的流程

编程语言 网络编程
控制程序的流程

Access使用宏控制程序

编程语言 网络编程
Access使用宏控制程序

lol偷钱流符文搭配推荐

英雄联盟 网络游戏
lol偷钱流符文搭配推荐

用Java Swing作一个日历控制程序

编程语言 网络编程
用Java Swing作一个日历控制程序

两步制作音量控制程序

设计软件 平面设计软件 广告设计软件
两步制作音量控制程序

lolAD刺客新符文搭配推荐

英雄联盟
lolAD刺客新符文搭配推荐

完全保护Access 2000数据库的安全

完全保护Access 2000数据库的安全

如何设置启动Excel时自动打开文件

如何设置启动Excel时自动打开文件
下拉加载更多内容 ↓