【转】MFC 禁止多实例

Windows是多进程操作系统,框架生成的应用程序可以多次运行,形成多个运行实例。但在有些情况下为保证应用程序的安全运行,要求程序只能运行一个实例,比如程序要使用只能被一个进程单独使用的特殊硬件(例如调制解调器)时,必须限制程序只运行一个实例。
        这里涉及两个基本的问题,一是在程序的第二个实例启动时,如何发现该程序已有一个实例在运行,而是如何将第一个实例激活,而第二个实例退出。

对于第一个问题,可以通过给应用程序设置信号量,实例启动时首先检测该信号量,如已存在,则说明程序已运行一个实例。第二个问题的难点是获取第一个实例的主窗对象指针或句柄,然后便可用SetForegroundWindow来激活。虽然FindWindow函数能寻找正运行着的窗口,但该函数要求指明所寻找窗口的标题或窗口类名,不是实现通用方法的途径。我们可以用Win 32 SDK函数SetProp来给应用程序主窗设置一个特有的标记。用GetDesktopWindow可以获取Windows系统主控窗口对象指针或句柄,所有应用程序主窗都可看成该窗口的子窗口,即可用GetWindow函数来获得它们的对象指针或句柄。用Win 32 SDK函数GetProp查找每一应用程序主窗是否包含有我们设置的特定标记便可确定它是否我们要寻找的第一个实例主窗。使第二个实例退出很简单,只要让其应用程序对象的InitInstance函数返回FALSE即可。此外,当主窗口退出时,应用RemoveProp函数删除我们为其设置的标记。

下面的InitInstance、OnCreate和OnDestroy函数代码将实现上述的操作:
BOOL CEllipseWndApp::InitInstance()
{
    // 用应用程序名创建信号量
    HANDLE hSem = CreateSemaphore(NULL, 1, 1, m_pszExeName);

// 信号量已存在?
    // 信号量存在,则程序已有一个实例运行
    if (GetLastError() == ERROR_ALREADY_EXISTS)
    {
        // 关闭信号量句柄
        CloseHandle(hSem);

// 寻找先前实例的主窗口
        HWND hWndPrevious = ::GetWindow(::GetDesktopWindow(), GW_CHILD);
        while (::IsWindow(hWndPrevious))
        {
            // 检查窗口是否有预设的标记?
            // 有,则是我们寻找的主窗
            if (::GetProp(hWndPrevious, m_pszExeName))
            {

      if (!::IsWindowVisible(hWndPrevious)){ ShowWindow(hWndPrevious, SW_SHOW); }
                // 主窗口已最小化,则恢复其大小
                if (::IsIconic(hWndPrevious))
                    ::ShowWindow(hWndPrevious, SW_RESTORE);
                // 将主窗激活
                ::SetForegroundWindow(hWndPrevious);
                // 将主窗的对话框激活
                ::SetForegroundWindow(::GetLastActivePopup(hWndPrevious));
                // 退出本实例
                return FALSE;
            }

// 继续寻找下一个窗口
            hWndPrevious = ::GetWindow(hWndPrevious, GW_HWNDNEXT);
        }

// 前一实例已存在,但找不到其主窗
        // 可能出错了
        // 退出本实例
        return FALSE;
    }

AfxEnableControlContainer();

// Standard initialization
    // If you are not using these features and wish to reduce the size
    // of your final executable, you should remove from the following
    // the specific initialization routines you do not need.

#ifdef _AFXDLL
Enable3dControls(); // Call this when using MFC in a shared DLL
#else
Enable3dControlsStatic();// Call this when linking to MFC statically
#endif

CEllipseWndDlg dlg;
    m_pMainWnd = &dlg;
    int nResponse = dlg.DoModal();
    if (nResponse == IDOK)
    {
        // TOD Place code here to handle when the dialog is
        // dismissed with OK
    }
    else if (nResponse == IDCANCEL)
    {
        // TOD 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;
}

int CEllipseWndDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CDialog::OnCreate(lpCreateStruct) == -1)
        return -1;

// 设置寻找标记
    ::SetProp(m_hWnd, AfxGetApp()->m_pszExeName, (HANDLE)1);
    return 0;
}

void CEllipseWndDlg::OnDestroy()
{
    CDialog::OnDestroy();

// 删除寻找标记
    ::RemoveProp(m_hWnd, AfxGetApp()->m_pszExeName);
}

时间: 2024-12-27 22:37:15

【转】MFC 禁止多实例的相关文章

转:MFC创建多线程实例

作者:http://blog.csdn.net/wangningyu/article/details/4404134 平时在MFC里使用多线程时其实是很方面的,因为微软提供了一个API让我们很方面的去创建线程:下面是MSDN中关于CreateThread的函数原型: 1.函数原型声明: [cpp] view plain copy print? CreateThread The CreateThread function creates a thread to execute within the

mfc一个多线程实例

在卷积神经网络的训练中,因为多个卷积核做卷积的时候互不干扰,可以并行. 直观的方法是采用多线程做卷积,每个线程负责一个featureMap的卷积计算. 在本人的程序中,多线程训练比单线程训练大约要快3倍. 工程名Dlg.cpp  (CCNN2Dlg.cpp)文件中,写好线程函数,第几个featureMap做卷积通过参数LPVOID lpPara指定. DWORD WINAPI ConvolFun1(LPVOID lpPara) { int i,j,ii,jj,k; k = (int)lpPara

用QT 还是MFC ? (转)

我曾经使用过QT和MFC来开发过软件,我想和大家分享我使用他们时所体会的不同之处. 我并非一个职业作家,这篇文章可能看起来不如专业的杂志和网站上的那么条理清晰.但是,我在这里是用我自己的语言来表达我自己的经验,希望能和你分享.英语比不是我的母语,所以可能会有一些用词古怪,词句错误之处,请发信给我,我可以改正他们. 本文不想假装客观公正,我只想表述我使用的经验.文中不会逐条的列举Qt和MFC各自的优缺点.我在使用MFC之前就已经使用Qt这个事实可能影响了我的客观性. 文章从实用主义的观点出发:我的

MFC和QT的区别

MFC(微软基础类库)是专门为windows设计的一个用于开发图形用户界面的类库.MFC或多或少使用了面向对象的方法包装了Win32的API,正因如此,这些API有时是C++,有时是C,甚至是C和C++的混合体. Qt这个C++的图形库由Trolltech在1994年左右开发.它可以运行在Windows,Mac OS X, Unix,还有像Sharp Zaurus这类嵌入式系统中.Qt是完全面向对象的. Document/View model: MFC编程需要使用Document/View模式以

MFC的定时器OnTimer

本文总结来源出自鸡啄米,感谢鸡啄米.来源:http://www.jizhuomi.com/software/232.html 定时器简介 定时器,可以帮助开发者或者用户定时完成某项任务.在使用定时器时,我们可以给系统传入一个时间间隔数据,然后系统就会在每个此时间间隔后触发定时处理程序,实现周期性的自动操作.例如,我们可以在数据采集系统中,为定时器设置定时采集时间间隔为1个小时,那么每隔1个小时系统就会采集一次数据,这样就可以在无人操作的情况下准确的进行操作.  MFC定时器 VS2010编程中,

QT和MFC比较

在网上看到的,拿来和大家一起讨论下.文中不会逐条的列举Qt和MFC各自的优缺点. 我在使用MFC之前就已经使用Qt这个事实可能影响了我的客观性. (MFC效率较高,但大量的Windows API和消息机制使得其较难理解,不易用:QT封装较好,易用且跨平台,但效率较低) 文章从实用主义的观点出发:我的老板给我一份软件的规划说明,并且让我来开发.其中一些我用Qt来开发,而另外一些我使用MFC来开发. MFC(微软基础类库)是专门为windows设计的一个用于开发图形用户界面的类库.MFC或多或少使用

QT 与 MFC 的区别 .

MFC(微软基础类库)是专门为windows设计的一个用于开发图形用户界面的类库.MFC或多或少使用了面向对象的方法包装了Win32的API,正因如此,这些API有时是C++,有时是C,甚至是C和C++的混合体. Qt这个C++的图形库由Trolltech在1994年左右开发.它可以运行在Windows,Mac OS X, Unix,还有像Sharp Zaurus这类嵌入式系统中.Qt是完全面向对象的. Document/View model:MFC编程需要使用Document/View模式以及

VC++ 多线程编程,win32,MFC 例子(转)

一.问题的提出 编写一个耗时的单线程程序: 新建一个基于对话框的应用程序SingleThread,在主对话框IDD_SINGLETHREAD_DIALOG添加一个按钮,ID为IDC_SLEEP_SIX_SECOND,标题为“延时6秒”,添加按钮的响应函数,代码如下: void CSingleThreadDlg::OnSleepSixSecond() { Sleep(6000); //延时6秒 } 编译并运行应用程序,单击“延时6秒”按钮,你就会发现在这6秒期间程序就象“死机”一样,不在响应其它消

VC++/MFC(VC6)开发技术精品学习资料下载汇总

工欲善其事,必先利其器,VC开发MFC Windows程序,Visual C++或Visual Studio是必须的,恩,这里都给你总结好了,拿去吧:VC/MFC开发必备Visual C++.Visual Studio.MSDN等下载汇总,甭客气~  啊?还没有开始学C++?那你先学习C++语言基础吧,C/C++语言基础学习资料及视频教程请看这里. 史无前例的网络最全最强C/C++资料索引: C/C++编程语言学习资料尽收眼底 电子书+视频教程 VC++/MFC(VC6)开发技术精品学习资料下载