只运行一个实例.htm
来自「应用程序只运行一个实例」· HTM 代码 · 共 253 行 · 第 1/2 页
HTM
253 行
<TD width="52%">
<DIV align=left></DIV></TD>
<TD width="38%">
<DIV align=right><IMG height=14 src="只运行一个实例.files/dian.gif"
width=141></DIV></TD>
<TD width="10%"> </TD></TR></TBODY></TABLE></TD>
<TD bgColor=#2875e8 width=1></TD></TR>
<TR>
<TD bgColor=#caddfa height=20 vAlign=top width=144>
<DIV align=center><IMG height=3 src="只运行一个实例.files/line.gif"
width=120></DIV></TD>
<TD bgColor=#caddfa height=20 width=1></TD>
<TD height=20 width=50> </TD>
<TD height=20 width=314><IMG height=24 src="只运行一个实例.files/jishu.gif"
width=185></TD>
<TD height=20 width=264>
<DIV align=center>当前位置:首页-->><FONT
color=#ff9900>技术文章</FONT></DIV></TD>
<TD bgColor=#2875e8 width=1></TD></TR>
<TR>
<TD bgColor=#caddfa vAlign=top width=144> </TD>
<TD bgColor=#caddfa width=1></TD>
<TD align=middle colSpan=3 vAlign=top>
<TABLE border=0 cellPadding=0 cellSpacing=0 width="100%">
<TBODY>
<TR>
<TD align=middle height=325 vAlign=top>
<HR color=#2875eb SIZE=1 width="90%">
<TABLE border=0 cellPadding=10 cellSpacing=10 class=B height=465
width="100%">
<TBODY>
<TR>
<TD height=316 vAlign=top>
<P align=left><FONT color=#ff0000
size=2>如何做到像《金山词霸》一样只运行一个实例</FONT></P>
<P align=left><FONT color=#0000ff size=2>作者:孙鑫</FONT></P>
<P><BR> 我们在使用《金山词霸》时发现,在《金山词霸》已经运行了的情况下,再次点击《金山词霸》的图标,那么它不会再运行另外一个《金山词霸》,而是将已有的《金山词霸》给激活,始终只能运行一个《金山词霸》的实例。<BR>在我们的程序当中如果要实现类似《金山词霸》的功能,就要解决两个问题,首先是要判断该程序已有一个实例在运行,其次是要将已运行的应用程序实例激活,同时退出第二个应用程序实例。<BR> 对于第一个问题,我们可以通过设置命名互斥对象或命名信标对象,在程序启动的时候检测互斥对象或信标对象,如互斥对象或信标对象已存在,则可以判断此程序已有一个实例正在运行。<BR> 第二个问题是如何找到已经运行的应用程序实例,如果我们能够找到已运行实例主窗口的指针,即可调用SetForegroundWindow来激活该实例。我们可以通过两种形式找到已运行实例的主窗口,一种形式是通过调用FindWindowEx去查找正在运行的窗口的句柄,这种方式用得比较多一些,而本文通过另一种形式去查找正在运行的窗口的句柄。通过调用SetProp给应用程序主窗口设置一个标记,用GetDesktopWindow
可以获取Windows环境下的桌面窗口的句柄,所有应用程序的主窗口都可以看成该窗口的子窗口,接着我们就可以用GetWindow函数来获得这些窗口的句柄。然后再用Win32
SDK函数GetProp查找每一个应用程序的主窗口是否包含有我们设置的标记,这样就可以找到我们要找的第一个实例主窗口。<BR>下面演示代码是以一个单文档应用程序为例,工程名字是Mutex。<BR>1、在应用程序类InitInstance()函数中判断是否已有一个应用程序实例正在运行。<BR>BOOL
CMutexApp::InitInstance()<BR>{<BR>//创建命名信标对象。<BR>HANDLE
hSem=CreateSemaphore(NULL,1,1,"维新");<BR>if(hSem)
//信标对象创建成功。<BR>{<BR>//信标对象已经存在,则程序已有一个实例在运行。<BR>if(ERROR_ALREADY_EXISTS==GetLastError())<BR>{
<BR>CloseHandle(hSem); //关闭信号量句柄。 </P>
<P>//获取桌面窗口的一个子窗口。<BR>HWND
hWndPrev=::GetWindow(::GetDesktopWindow(),GW_CHILD); </P>
<P>while(::IsWindow(hWndPrev))<BR>{<BR>//判断窗口是否有我们预先设置的标记,如有,则是我们寻找的窗口,并将它激活。<BR>if(::GetProp(hWndPrev,"维新"))
<BR>{<BR>//如果主窗口已最小化,则恢复其大小。<BR>if (::IsIconic(hWndPrev))
<BR>::ShowWindow(hWndPrev,SW_RESTORE);</P>
<P>//将应用程序的主窗口激活。<BR>::SetForegroundWindow(hWndPrev);<BR>return
FALSE; //退出实例。<BR>}<BR>//继续寻找下一个窗口。<BR>hWndPrev =
::GetWindow(hWndPrev,GW_HWNDNEXT); <BR>}</P>
<P>AfxMessageBox("已有一个实例在运行,但找不到它的主窗口!");<BR>}<BR>}<BR>else<BR>{<BR>AfxMessageBox("创建信标对象失败,程序退出!");<BR>return
FALSE;<BR>}</P>
<P>AfxEnableControlContainer();</P>
<P>// Standard initialization<BR>// If you are not using these
features and wish to reduce the size<BR>// of your final
executable, you should remove from the following<BR>// the
specific initialization routines you do not need.</P>
<P>#ifdef _AFXDLL<BR>Enable3dControls(); // Call this when
using MFC in a shared
DLL<BR>#else<BR>Enable3dControlsStatic(); // Call this when
linking to MFC statically<BR>#endif</P>
<P>// Change the registry key under which our settings are
stored.<BR>// TODO: You should modify this string to be
something appropriate<BR>// such as the name of your company
or organization.<BR>SetRegistryKey(_T("Local
AppWizard-Generated Applications"));</P>
<P>LoadStdProfileSettings(); // Load standard INI file options
(including MRU)</P>
<P>// Register the application's document templates. Document
templates<BR>// serve as the connection between documents,
frame windows and views.</P>
<P>CSingleDocTemplate* pDocTemplate;<BR>pDocTemplate = new
CSingleDocTemplate(<BR>IDR_MAINFRAME,<BR>RUNTIME_CLASS(CMutexDoc),<BR>RUNTIME_CLASS(CMainFrame),
// main SDI frame
window<BR>RUNTIME_CLASS(CMutexView));<BR>AddDocTemplate(pDocTemplate);</P>
<P>// Parse command line for standard shell commands, DDE,
file open<BR>CCommandLineInfo
cmdInfo;<BR>ParseCommandLine(cmdInfo);</P>
<P>// Dispatch commands specified on the command line<BR>if
(!ProcessShellCommand(cmdInfo))<BR>return FALSE;</P>
<P>// The one and only window has been initialized, so show
and update
it.<BR>m_pMainWnd->ShowWindow(SW_SHOW);<BR>m_pMainWnd->UpdateWindow();</P>
<P>return TRUE;<BR>}<BR>2、在框架类的OnCreate()函数中设置查找标记。<BR>int
CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)<BR>{<BR>if
(CFrameWnd::OnCreate(lpCreateStruct) == -1)<BR>return -1;</P>
<P>if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD |
WS_VISIBLE | CBRS_TOP<BR>| CBRS_GRIPPER | CBRS_TOOLTIPS |
CBRS_FLYBY | CBRS_SIZE_DYNAMIC)
||<BR>!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))<BR>{<BR>TRACE0("Failed
to create toolbar\n");<BR>return -1; // fail to
create<BR>}</P>
<P>if (!m_wndStatusBar.Create(this)
||<BR>!m_wndStatusBar.SetIndicators(indicators,<BR>sizeof(indicators)/sizeof(UINT)))<BR>{<BR>TRACE0("Failed
to create status bar\n");<BR>return -1; // fail to
create<BR>}</P>
<P>// TODO: Delete these three lines if you don't want the
toolbar to<BR>// be dockable</P>
<P>m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);<BR>EnableDocking(CBRS_ALIGN_ANY);<BR>DockControlBar(&m_wndToolBar);</P>
<P><BR>//设置查找标记。<BR>::SetProp(m_hWnd,"维新",(HANDLE)1);</P>
<P>return
0;<BR>}<BR>3、在程序退出是删除设置的标记,在框架类中响应WM_DESTROY消息,进行处理。<BR>void
CMainFrame::OnDestroy() <BR>{<BR>CFrameWnd::OnDestroy();</P>
<P>// TODO: Add your message handler code
here<BR>//删除所设置的标记。<BR>::RemoveProp(m_hWnd,"维新");<BR>}<BR>至此,使应用程序只运行一个实例的功能就完成了。</P></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE></TD>
<TD bgColor=#2875e8 width=1></TD></TR>
<TR>
<TD bgColor=#caddfa width=144> </TD>
<TD bgColor=#caddfa width=1></TD>
<TD colSpan=3>
<DIV align=right><IMG height=22 src="只运行一个实例.files/bottom.gif"
width=558></DIV></TD>
<TD bgColor=#2875e8 width=1></TD></TR>
<TR>
<TD bgColor=#2875e8 colSpan=6 height=1></TD></TR></TBODY></TABLE>
<TABLE align=center border=0 cellPadding=0 cellSpacing=0 width=778>
<TBODY>
<TR>
<TD>
<DIV align=center><BR>电话:(010)89138630 EMail:<A
href="mailto:mybole@mybole.com.cn">mybole@mybole.com.cn</A>
<BR>程序员之家 版权所有 copyright©
2004-2006</DIV></TD></TR></TBODY></TABLE></DIV></BODY></HTML>
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?