只有一个...






4.69/5 (9投票s)
限制应用程序为单个实例。
引言
在阅读 Joseph Newcomer 关于此问题的文章时,我心想一定有一种更简单的方法来做到这一点。因此,基于他过去几年的优秀工作,我投入了所有时间研究这个理论。与此同时,我从未见过阳光,并且失去了所有的朋友(只是开玩笑';)...
但经过长时间的研究,并保密了太久,我终于拿出成果,只是为了确保像这样重要的发现不会在历史中消失... 嗯...
那么我们开始吧
- 我们需要一个注册的消息,我们的应用程序将响应它。使这个消息在你的应用程序中全局可用。
static const UINT WM_CHECK_ITS_ME = RegisterWindowMessage("MY_UNIQUE_GUID");
- 现在我们在程序的开始处创建一个互斥锁
HANDLE hMutexOneInstance = CreateMutex( NULL, FALSE, _T("MY_UNIQUE_GUID"));
- 检查最后一个错误,看看发生了什么
bool AlreadyRunning = ( GetLastError() == ERROR_ALREADY_EXISTS || GetLastError() == ERROR_ACCESS_DENIED);
- 然后我们向所有顶级窗口发送一条消息,以确保它弹出并成为活动窗口。这里的技巧是使用 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... }
- 已经运行的应用程序需要响应注册的窗口消息,因此我们在应用程序中添加一个消息处理程序。
如果你使用的是 MFC,请编辑你的消息映射ON_REGISTERED_MESSAGE( WM_CHECK_ITS_ME, OnCheckItsMe )
或者 WTLMESSAGE_HANDLER(WM_CHECK_ITS_ME, OnCheckItsMe)
或者纯 Windows APILRESULT CALLBACK MyWindowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) { if (msg == WM_CHECK_ITS_ME) { ... return 0; } .... return ...; }
- 现在在处理程序的这个消息中,我们只需确保此应用程序成为前台和活动状态。
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; }
- 这应该可以工作!