方法太多了单实例运行方案 方案一: 查找窗口类 方案二: 设置窗口属性 方案三: 使用文件映像 方案四: 使用原子 方案五: 使用同步对象
方案一: 使用注册类查找的方法实现单实例运行 例: ①C???App::InitInstance BOOL C???App::InitInstance()
{
if (!FirstInstance())
return FALSE;
beRegisted=TRUE; m_pMainWnd =new CMainWnd();
m_pMainWnd->CreateEx(0,"fmdmainwnd",
_T("CodeHelper"),WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,NULL);
m_pMainWnd->ShowWindow(SW_SHOW);
m_pMainWnd->UpdateWindow();
return TRUE;
}其中beRegisted为C???App成员 public:
BOOL beRegisted;②C???App::FirstInstance BOOL CMainApp::FirstInstance()
{
CWnd *PrevCWnd, *ChildCWnd; // Determine if another window with our class name exists...
if (PrevCWnd = CWnd::FindWindow("fmdmainwnd",NULL))
{
// if so, does it have any popups?
ChildCWnd=PrevCWnd->GetLastActivePopup(); // Bring the main window to the top.
PrevCWnd->BringWindowToTop(); // If iconic, restore the main window.
if (PrevCWnd->IsIconic())
PrevCWnd->ShowWindow(SW_RESTORE); // If there was an active popup, bring it along too
if (PrevCWnd != ChildCWnd)
ChildCWnd->BringWindowToTop(); // Return FALSE. This isn't the first instance
// and you finished activating the previous one.
return FALSE;
}
else
return TRUE; // First instance. Proceed as normal.
}③C???App::InitApplication BOOL CMainApp::InitApplication()
{
CWinApp::InitApplication(); WNDCLASS wndcls;
//注册自定义类
memset(&wndcls, 0, sizeof(WNDCLASS));
//窗口基本类型
wndcls.style=CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
wndcls.lpfnWndProc=::DefWindowProc;
wndcls.hInstance=AfxGetInstanceHandle();
wndcls.hIcon=LoadIcon(IDR_MAIN);
wndcls.hCursor=LoadStandardCursor(IDC_ARROW);
wndcls.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
wndcls.lpszMenuName=MAKEINTRESOURCE(IDR_MAIN);
wndcls.lpszClassName="fmdmainwnd";
return AfxRegisterClass(&wndcls);
}④C???App::ExitInstance int CMainApp::ExitInstance()
{
// TODO: Add your specialize code here and/or call the base class
if(beRegisted)
::UnregisterClass("fmdmainwnd", AfxGetInstanceHandle());
return CWinApp::ExitInstance();
}
方案二:设置窗口附加属性 int C???Dlg::OnCreate(LPCREATESTRUCT lpCreateStruct) {
......
::SetProp(m_hWnd, AfxGetApp()->m_pszExeName, (HANDLE)1);
......
}
void C???Dlg::OnDestroy()
{
......
::RemoveProp(m_hWnd, AfxGetApp()->m_pszExeName);
......
}
BOOL CEllipseWndApp::InitInstance()
{
// Create a Semaphore with a name of application exename
HANDLE hSem = CreateSemaphore(NULL, 1, 1, m_pszExeName);
if (GetLastError() == ERROR_ALREADY_EXISTS)
{
// close the semaphore handle
CloseHandle(hSem); // find the provious instance main window
HWND hWndPrevious = ::GetWindow(::GetDesktopWindow(), GW_CHILD);
while (::IsWindow(hWndPrevious))
{
// if the window has our tag?
if (::GetProp(hWndPrevious, m_pszExeName))
{
if (::IsIconic(hWndPrevious))
::ShowWindow(hWndPrevious, SW_RESTORE);
::SetForegroundWindow(hWndPrevious);
::SetForegroundWindow(::GetLastActivePopup(hWndPrevious));
return FALSE;
} // continue find next window
hWndPrevious = ::GetWindow(hWndPrevious, GW_HWNDNEXT);
} // the previous instance is exist, but can not be found
// somthing wrong?
return FALSE;
}
C????Dlg dlg;
m_pMainWnd = &dlg; int nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
// TODO: Place code here to handle when the dialog is
// dismissed with OK
}
else if (nResponse == IDCANCEL)
{
// TODO: Place code here to handle when the dialog is
// dismissed with Cancel
}
return FALSE;
}
方案三:使用文件映像 参见《精彩例程》 方案四:使用原子 BOOL C???App::InitInstance()
{
.....
if(GlobalFindAtom("AdBreaker")) //找原子
return false;
ATOM GlobalAtom=GlobalAddAtom("AdBreaker"); //添加原子 CAdBreakerDlg dlg;
m_pMainWnd = &dlg;
int nResponse = dlg.DoModal();
.....
GlobalDeleteAtom(GlobalAtom);
return FALSE;
}方案五:使用同步对象 InitInstance中 HANDLE m_hMutex =
CreateMutex(NULL,TRUE,m_pszAppName);
if (GetLastError()==ERROR_ALREADY_EXISTS){
return FALSE;
}
方案一: 使用注册类查找的方法实现单实例运行 例: ①C???App::InitInstance BOOL C???App::InitInstance()
{
if (!FirstInstance())
return FALSE;
beRegisted=TRUE; m_pMainWnd =new CMainWnd();
m_pMainWnd->CreateEx(0,"fmdmainwnd",
_T("CodeHelper"),WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,NULL);
m_pMainWnd->ShowWindow(SW_SHOW);
m_pMainWnd->UpdateWindow();
return TRUE;
}其中beRegisted为C???App成员 public:
BOOL beRegisted;②C???App::FirstInstance BOOL CMainApp::FirstInstance()
{
CWnd *PrevCWnd, *ChildCWnd; // Determine if another window with our class name exists...
if (PrevCWnd = CWnd::FindWindow("fmdmainwnd",NULL))
{
// if so, does it have any popups?
ChildCWnd=PrevCWnd->GetLastActivePopup(); // Bring the main window to the top.
PrevCWnd->BringWindowToTop(); // If iconic, restore the main window.
if (PrevCWnd->IsIconic())
PrevCWnd->ShowWindow(SW_RESTORE); // If there was an active popup, bring it along too
if (PrevCWnd != ChildCWnd)
ChildCWnd->BringWindowToTop(); // Return FALSE. This isn't the first instance
// and you finished activating the previous one.
return FALSE;
}
else
return TRUE; // First instance. Proceed as normal.
}③C???App::InitApplication BOOL CMainApp::InitApplication()
{
CWinApp::InitApplication(); WNDCLASS wndcls;
//注册自定义类
memset(&wndcls, 0, sizeof(WNDCLASS));
//窗口基本类型
wndcls.style=CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
wndcls.lpfnWndProc=::DefWindowProc;
wndcls.hInstance=AfxGetInstanceHandle();
wndcls.hIcon=LoadIcon(IDR_MAIN);
wndcls.hCursor=LoadStandardCursor(IDC_ARROW);
wndcls.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
wndcls.lpszMenuName=MAKEINTRESOURCE(IDR_MAIN);
wndcls.lpszClassName="fmdmainwnd";
return AfxRegisterClass(&wndcls);
}④C???App::ExitInstance int CMainApp::ExitInstance()
{
// TODO: Add your specialize code here and/or call the base class
if(beRegisted)
::UnregisterClass("fmdmainwnd", AfxGetInstanceHandle());
return CWinApp::ExitInstance();
}
方案二:设置窗口附加属性 int C???Dlg::OnCreate(LPCREATESTRUCT lpCreateStruct) {
......
::SetProp(m_hWnd, AfxGetApp()->m_pszExeName, (HANDLE)1);
......
}
void C???Dlg::OnDestroy()
{
......
::RemoveProp(m_hWnd, AfxGetApp()->m_pszExeName);
......
}
BOOL CEllipseWndApp::InitInstance()
{
// Create a Semaphore with a name of application exename
HANDLE hSem = CreateSemaphore(NULL, 1, 1, m_pszExeName);
if (GetLastError() == ERROR_ALREADY_EXISTS)
{
// close the semaphore handle
CloseHandle(hSem); // find the provious instance main window
HWND hWndPrevious = ::GetWindow(::GetDesktopWindow(), GW_CHILD);
while (::IsWindow(hWndPrevious))
{
// if the window has our tag?
if (::GetProp(hWndPrevious, m_pszExeName))
{
if (::IsIconic(hWndPrevious))
::ShowWindow(hWndPrevious, SW_RESTORE);
::SetForegroundWindow(hWndPrevious);
::SetForegroundWindow(::GetLastActivePopup(hWndPrevious));
return FALSE;
} // continue find next window
hWndPrevious = ::GetWindow(hWndPrevious, GW_HWNDNEXT);
} // the previous instance is exist, but can not be found
// somthing wrong?
return FALSE;
}
C????Dlg dlg;
m_pMainWnd = &dlg; int nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
// TODO: Place code here to handle when the dialog is
// dismissed with OK
}
else if (nResponse == IDCANCEL)
{
// TODO: Place code here to handle when the dialog is
// dismissed with Cancel
}
return FALSE;
}
方案三:使用文件映像 参见《精彩例程》 方案四:使用原子 BOOL C???App::InitInstance()
{
.....
if(GlobalFindAtom("AdBreaker")) //找原子
return false;
ATOM GlobalAtom=GlobalAddAtom("AdBreaker"); //添加原子 CAdBreakerDlg dlg;
m_pMainWnd = &dlg;
int nResponse = dlg.DoModal();
.....
GlobalDeleteAtom(GlobalAtom);
return FALSE;
}方案五:使用同步对象 InitInstance中 HANDLE m_hMutex =
CreateMutex(NULL,TRUE,m_pszAppName);
if (GetLastError()==ERROR_ALREADY_EXISTS){
return FALSE;
}
BOOL CBookSqlApp::InitInstance()
{ HWND FirsthWnd,FirstChildhWnd;
static char *title="书店信息管理系统"; if(FirsthWnd = FindWindow(NULL,title))
{
MessageBox(NULL,"您已经启动的书店信息管理系统程序 ! ","提示 ",MB_ICONINFORMATION);
FirstChildhWnd=GetLastActivePopup(FirsthWnd);
BringWindowToTop(FirsthWnd); if(FirsthWnd != FirstChildhWnd)
BringWindowToTop(FirstChildhWnd); ShowWindow(FirsthWnd,SW_SHOWNA);
return(FALSE);
} ...
}
#pragma data_seg(".OnlyOne")
long 1Count=-1;
#pragma data_seg()用DEF文件定义共享属性
SECTIONS
.OnlyOne READ WRITE SHARED在初始化阶段,如InitInstance开始处,加入
BOOL bFirstInit=(InterlockedIncrement($1InstanceCount)==0)
if(!bFirstInit)
{
AfxMessageBox("该程序已经运行",MB_OK|MB_ICONSTOP);
InterlockedDecrement($1InstanceCount);
return FALSE;
}
程序结束后,调用:
InterlockedDecrement(&1InstanceCount);
对于一般程序在ExitInstance中调用InterlockedDecrement(&1InstanceCount);
对话框程序在InitInstance最后调用本方法再无窗口函数中也适用