📄 sinstance.cpp
字号:
void CInstanceChecker::ReleaseLock()
{
if (m_pExecuteLock)
{
delete m_pExecuteLock;
m_pExecuteLock = NULL;
}
}
// Track the first instance of our App.
// return TRUE on success, else FALSE
BOOL CInstanceChecker::TrackFirstInstanceRunning()
{
//If a previous instance is running, just return prematurely
if (PreviousInstanceRunning())
return FALSE;
//If this is the first instance then copy in our info into the shared memory
//First create the MMF
int nMMFSize = sizeof(CWindowInstance);
instanceData.hInstanceData = ::CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, nMMFSize, GetMMFFilename());
if (instanceData.hInstanceData == NULL)
{
TRACE(_T("Failed to create the MMF even though this is the first instance, you might want to consider overriding GetMMFFilename()\n"));
return FALSE;
}
//Open the MMF
CWindowInstance* pInstanceData = static_cast<CWindowInstance*>(::MapViewOfFile(instanceData.hInstanceData, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, nMMFSize));
ASSERT(pInstanceData != NULL); //Opening the MMF should work
// Lock the data prior to updating it
CSingleLock dataLock(&m_instanceDataMutex, TRUE);
pInstanceData->hMainWnd = GetWindowToTrack();
::UnmapViewOfFile(pInstanceData);
//Since this will be the last function that will be called
//when this is the first instance we can release the lock
ReleaseLock();
return TRUE;
}
// Returns TRUE if a previous instance of the App is running.
BOOL CInstanceChecker::PreviousInstanceRunning()
{
//Try to open the MMF first to see if we are the second instance
HANDLE hPrevInstance = ::OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, GetMMFFilename());
BOOL bPreviousInstance = (hPrevInstance != NULL);
if (hPrevInstance)
CloseHandle(hPrevInstance);
return bPreviousInstance;
}
CString CInstanceChecker::GetMMFFilename()
{
CString sMMF(_T("CInstanceChecker_MMF_"));
sMMF += m_sName;
return sMMF;
}
HWND CInstanceChecker::GetWindowToTrack()
{
//By default the window tracked will be the standard AfxGetMainWnd()
ASSERT(AfxGetMainWnd() != NULL); //Did you forget to set up the mainfrm in InitInstance ?
return AfxGetMainWnd()->GetSafeHwnd();
}
// Activate the Previous Instance of our Application.
HWND CInstanceChecker::ActivatePreviousInstance(LPCTSTR lpCmdLine, DWORD dwCopyDataItemData)
{
//Try to open the previous instances MMF
HANDLE hPrevInstance = ::OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, GetMMFFilename());
if (hPrevInstance)
{
// Open up the MMF
int nMMFSize = sizeof(CWindowInstance);
CWindowInstance* pInstanceData = static_cast<CWindowInstance*>(::MapViewOfFile(hPrevInstance, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, nMMFSize));
if (pInstanceData != NULL) //Opening the MMF should work
{
//Lock the data prior to reading from it
CSingleLock dataLock(&m_instanceDataMutex, TRUE);
//activate the old window
ASSERT(pInstanceData->hMainWnd); //Something gone wrong with the MMF
HWND hWindow = pInstanceData->hMainWnd;
if (hWindow)
{
CWnd wndPrev;
wndPrev.Attach(hWindow);
CWnd* pWndChild = wndPrev.GetLastActivePopup();
//Restore the focus to the previous instance and bring it to the foreground
if (wndPrev.IsIconic())
wndPrev.ShowWindow(SW_RESTORE);
if (pWndChild)
pWndChild->SetForegroundWindow();
if (lpCmdLine)
{
//Send the current apps command line to the previous instance using WM_COPYDATA
COPYDATASTRUCT cds;
cds.dwData = dwCopyDataItemData;
DWORD dwCmdLength = static_cast<DWORD>(_tcslen(lpCmdLine) + 1);
cds.cbData = dwCmdLength * sizeof(TCHAR);
TCHAR* pszLocalCmdLine = new TCHAR[dwCmdLength]; //We use a local buffer so that we can specify a constant parameter
//to this function
#if (_MSC_VER >= 1400)
_tcscpy_s(pszLocalCmdLine, dwCmdLength, lpCmdLine);
#else
_tcscpy(pszLocalCmdLine, lpCmdLine);
#endif
cds.lpData = pszLocalCmdLine;
CWnd* pMainWindow = AfxGetMainWnd();
HWND hSender = NULL;
if (pMainWindow)
hSender = pMainWindow->GetSafeHwnd();
//Send the message to the previous instance
wndPrev.SendMessage(WM_COPYDATA, reinterpret_cast<WPARAM>(hSender), reinterpret_cast<LPARAM>(&cds));
//Tidy up the heap memory we have used
delete [] pszLocalCmdLine;
}
//Detach the CWnd we were using
wndPrev.Detach();
}
//Unmap the MMF we were using
::UnmapViewOfFile(pInstanceData);
//Close the file handle now that we
::CloseHandle(hPrevInstance);
//When we have activate the previous instance, we can release the lock
ReleaseLock();
//return the Window handle of the previous instance
return hWindow;
}
//Close the file handle now that we
::CloseHandle(hPrevInstance);
//When we have activate the previous instance, we can release the lock
ReleaseLock();
}
return NULL;
}
void CInstanceChecker::QuitPreviousInstance(int nExitCode)
{
//Try to open the previous instances MMF
HANDLE hPrevInstance = ::OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, GetMMFFilename());
if (hPrevInstance)
{
// Open up the MMF
int nMMFSize = sizeof(CWindowInstance);
CWindowInstance* pInstanceData = static_cast<CWindowInstance*>(::MapViewOfFile(hPrevInstance, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, nMMFSize));
if (pInstanceData != NULL) //Opening the MMF should work
{
// Lock the data prior to reading from it
CSingleLock dataLock(&m_instanceDataMutex, TRUE);
//activate the old window
ASSERT(pInstanceData->hMainWnd); //Something gone wrong with the MMF
HWND hWindow = pInstanceData->hMainWnd;
//Ask it to exit
if (hWindow)
PostMessage(hWindow, WM_QUIT, nExitCode, 0);
}
//Close the file handle now that we
::CloseHandle(hPrevInstance);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -