65.9K
CodeProject 正在变化。 阅读更多。
Home

只有一个...

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.69/5 (9投票s)

2002年4月2日

CPOL

1分钟阅读

viewsIcon

124616

限制应用程序为单个实例。

引言

在阅读 Joseph Newcomer 关于此问题的文章时,我心想一定有一种更简单的方法来做到这一点。因此,基于他过去几年的优秀工作,我投入了所有时间研究这个理论。与此同时,我从未见过阳光,并且失去了所有的朋友(只是开玩笑';)...

但经过长时间的研究,并保密了太久,我终于拿出成果,只是为了确保像这样重要的发现不会在历史中消失... 嗯...

那么我们开始吧

  1. 我们需要一个注册的消息,我们的应用程序将响应它。使这个消息在你的应用程序中全局可用。
    static const UINT WM_CHECK_ITS_ME = RegisterWindowMessage("MY_UNIQUE_GUID");
  2. 现在我们在程序的开始处创建一个互斥锁
    HANDLE hMutexOneInstance = CreateMutex( NULL, FALSE, _T("MY_UNIQUE_GUID"));
  3. 检查最后一个错误,看看发生了什么
    bool AlreadyRunning = ( GetLastError() == ERROR_ALREADY_EXISTS || 
                               GetLastError() == ERROR_ACCESS_DENIED);
  4. 然后我们向所有顶级窗口发送一条消息,以确保它弹出并成为活动窗口。这里的技巧是使用 HWND_BROADCAST,它有点缺乏文档。
    if ( AlreadyRunning )
    {    
     DWORD result;
     LRESULT ok = SendMessageTimeout(HWND_BROADCAST,
                                           WM_CHECK_ITS_ME,
                                           0, 0, 
                                           SMTO_BLOCK |
                                           SMTO_ABORTIFHUNG,
                                           200,
                                           &result);
     return FALSE; // Here we quit this application
     // or exit(0);
     // or PostQuitMessage() ... etc...
    }
  5. 已经运行的应用程序需要响应注册的窗口消息,因此我们在应用程序中添加一个消息处理程序。

    如果你使用的是 MFC,请编辑你的消息映射
    ON_REGISTERED_MESSAGE( WM_CHECK_ITS_ME, OnCheckItsMe )
    或者 WTL
    MESSAGE_HANDLER(WM_CHECK_ITS_ME, OnCheckItsMe)
    或者纯 Windows API
    LRESULT CALLBACK MyWindowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
    {
      if (msg == WM_CHECK_ITS_ME)
      {
        ...
        return 0;
      }
      ....
      return ...;
    }
  6. 现在在处理程序的这个消息中,我们只需确保此应用程序成为前台和活动状态。
    LRESULT CMainFrame::OnCheckItsMe(...)
    {
    // If we are using Chris Maunder's CSystemTray it's handy
    
     m_SystemTray.MaximiseFromTray(this->m_hWnd); 
     
    // or else you can call all sorts of restore/maximise functions:
    
     - ShowWindow(SW_RESTORE);
     - SetForegroundWindow();
     - SetWindowPlacement(m_MyWindowPlacement);
    
     return WM_CHECK_ITS_ME;
    }
  7. 这应该可以工作!
© . All rights reserved.