这个问题应该是大多数程序员很熟知的问题,记录再此仅仅是作为备忘录,同时对于一些小的细节问题跟大家作一些探讨。这里仅仅针对window ce 6.0系统,其它平台未做过测试,这里不做讨论。
在开发手机应用程序时,如果应用程序已经在运行,再次运行该应用程序时,我们需要把该应用程序的窗口提到前面来,把新的命令行参数传递给第一个运行实例,而第二个实例退出。从问题可以看出,需要解决的问题有三个:
- 保证应用程序单实例运行。最简单办法就是创建一个命名的mutex,第二个实例运行时创建同名的mutex会失败,便认为当前运行实例不是第一个了。
- 将新的参数传递给第一个运行实例。这可以通过WM_COPYDATA消息来实现。
- 将正在运行的应用程序的窗口提到前面来。这个问题在网上看到的办法都是采用API BringWindowToTop,只是我在测试过程中发现该api并没起到作用,所以只得使用了另一个函数SetWindowPos。
下面是实例代码:
/**初始化代码**/
HANDLE h = CreateMutex( NULL,TRUE,L"PhoneAppMutex");
LPWSTR pstr = ::GetCommandLine();
if (h)
{
int err = GetLastError();
if (ERROR_ALREADY_EXISTS == err)
{
HWND hWnd = ::FindWindow(L"CPhoneMainWnd",NULL);
COPYDATASTRUCT cpd; /*给COPYDATASTRUCT结构赋值*/
cpd.dwData = 0;
cpd.cbData = wcslen(pstr) + 1;
cpd.lpData = (void*)pstr;
::SendMessage(hWnd,WM_COPYDATA,NULL,(LPARAM)&cpd);//发送!
PostQuitMessage(0);
return FALSE;
}
}
else
{
return FALSE;
}
m_hPhoneMutex = h; //保留句柄
--------------------------------------------------------------------------------------------
/**WM_COPYDATA消息处理**/
std::wstring str = (LPCWCHAR)pCopyDataStruct->lpData;
str.substr(0,pCopyDataStruct->cbData);
//MessageBox(NULL, str.c_str(), L"Phone", MB_OK);
//加入处理运行参数代码
//::BringWindowToTop( m_hWnd ); 奇怪的是该api无效,
//将窗口提到最前
::SetWindowPos(m_hWnd,HWND_TOPMOST,0,0,480,720,SWP_SHOWWINDOW);
总结:
步骤:
1、保证应用程序单实例运行。
最简单办法就是创建一个命名的mutex,第二个实例运行时创建同名的mutex会失败,便认为当前运行实例不是第一个了。
还可通过使用SetProp设置实例属性,在启动实例前查找是否存在该属性的程序,若存在则表示已运行。
2、将新的参数传递给第一个运行实例。
这可以通过WM_COPYDATA消息来实现。第二个实例在退出之前通过SendMessage发送消息,并在第一个实例中接收消息并处理。
3、将正在运行的应用程序的窗口提到前面来。
这个问题在网上看到的办法都是采用API BringWindowToTop,只是我在测试过程中发现该api并没起到作用,所以只得使用了另一个函数SetWindowPos。