Bring an application at foreground
Hi all,
I'm trying to hava only one cpy of my app running at once, to do that i get the sample code on "Hello World" generated app on embedded C++ 4.0
| |
bool ActivatePreviousInstance() { bool activated =false; int cTries; HANDLE hMutex = NULL; cTries = 5; while(cTries > 0) { hMutex = CreateMutex(NULL, FALSE, TEXT("myMutex") );// NOTE: We don't want to own the object. if(GetLastError() == ERROR_ALREADY_EXISTS) { HWND hwnd; CloseHandle(hMutex); hMutex = NULL; // There is already an instance of this app // running. Try to bring it to the foreground. hwnd = ::FindWindow(TEXT("Dialog"), TEXT("WinTelecopie") ); if(NULL == hwnd) { // It's possible that the other window is in the process of being created... Sleep(500); hwnd = ::FindWindow(TEXT("Dialog"), TEXT("WinTelecopie") ); } if(NULL != hwnd) { // Set the previous instance as the foreground window // The "| 0x01" in the code below activates // the correct owned window of the // previous instance's main window. ::SetForegroundWindow((HWND) (((ULONG) hwnd) | 0x01)); // We are done. activated = true; break; } // It's possible that the instance we found isn't coming up, // but rather is going down. Try again. cTries--; } else { // We were the first one to create the mutex // so that makes us the main instance. 'leak' // the mutex in this function so it gets cleaned // up by the OS when this instance exits. break; } } return activated; }
|
This works, but it takes near 10/15 seconds to display the existing app
I trace windows messages :
| | WM_GETTEXT WM_SETFOCUS WM_IME_NOTIFY WM_IME_SETCONTEXT WM_ACTIVATE WM_QUERYNEWPALETTE WM_NCACTIVATE WM_WINDOWPOSCHANGED ** ** 15 secondebreak ** ** WM_CTLCOLORDLG WM_ERASEBCKGND WM_PAINT/////// From heere i can see my dialog boxe and other msgs...
|
The probleme is that i'm not using any of these msgs so i guess, Windows take a lot of time to bring my dilaog box to the foreground :o(
As it work on "Hello World" sample i guess i make a mistake but in can't see where.
Thanks for replies
[3022 byte] By [
lmussier] at [2008-2-27]
The following is what we do in Whidbey MFC (winmain.cpp), let me know if that work for you also.
#ifdef _WIN32_WCE
int aygshellUIModel = AfxGetAygshellUIModel();
if (aygshellUIModel == PocketPC || aygshellUIModel == Smartphone)
{
// only one application instance can be run
wchar_t szTempFileName[MAX_PATH], szModuleFileName[MAX_PATH];
int nFileNameLen = ::GetModuleFileName(NULL, szModuleFileName, MAX_PATH);
int idxTempFileName = 0;
for (int idxModuleFileName = 0; idxModuleFileName < nFileNameLen; idxModuleFileName++)
{
if (szModuleFileName[idxModuleFileName] == L'\\')
{
szTempFileName[idxTempFileName++] = L'/';
}
else
{
szTempFileName[idxTempFileName++] = szModuleFileName[idxModuleFileName];
}
}
szTempFileName[idxTempFileName] = L'\0';
HANDLE hMutex = ::CreateMutex(NULL, FALSE, szTempFileName);
if (hMutex != NULL)
{
if (::GetLastError() == ERROR_ALREADY_EXISTS)
{
BOOL bGoAway = FALSE;
MODULEINFO moduleInfo;
ZeroMemory(&moduleInfo, sizeof(MODULEINFO));
moduleInfo.pszModuleFileName = szModuleFileName;
int nThreadPriority = pThread->GetThreadPriority();
// Retry for 10 seconds (40 * 250 millisecons = 10000 milliseconds)
for (int i = 0; i < 40; ++i)
{
::EnumWindows(_AfxFindModuleInfoProc, (LPARAM)&moduleInfo);
if (moduleInfo.hwnd)
{
::SetForegroundWindow((HWND)(((DWORD)moduleInfo.hwnd) | 0x00000001));
bGoAway = TRUE;
break;
}
// wait for other app to finish starting or stopping
pThread->SetThreadPriority(THREAD_PRIORITY_IDLE);
Sleep(250); // sleep for one quarter second (arbitrary)
pThread->SetThreadPriority(nThreadPriority);
}
if (bGoAway)
{
::ReleaseMutex(hMutex);
goto InitFailure;
}
}
::ReleaseMutex(hMutex);
}
}
#endif
The helper function _AfxFindModuleInfoProc was defined below (in the same file)
#ifdef _WIN32_WCE
typedef struct ModuleInfo
{
wchar_t *pszModuleFileName;
HWND hwnd;
}
MODULEINFO, *PMODULEINFO;
BOOL CALLBACK _AfxFindModuleInfoProc(HWND hwnd, LPARAM lParam)
{
DWORD dwProcessID;
PMODULEINFO pModuleInfo = (PMODULEINFO)lParam;
::GetWindowThreadProcessId(hwnd, &dwProcessID);
if (!dwProcessID)
{
return TRUE;
}
wchar_t szModuleFileName[MAX_PATH];
if (!::GetModuleFileName((HMODULE)dwProcessID, szModuleFileName, MAX_PATH))
{
return TRUE;
}
if (!::wcsicmp(szModuleFileName, pModuleInfo->pszModuleFileName))
{
pModuleInfo->hwnd = hwnd;
return FALSE;
}
return TRUE;
}
#endif // _WIN32_WCE