只运行一个实例.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%">&nbsp;</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>&nbsp;</TD>
    <TD height=20 width=314><IMG height=24 src="只运行一个实例.files/jishu.gif" 
      width=185></TD>
    <TD height=20 width=264>
      <DIV align=center>当前位置:首页--&gt;&gt;<FONT 
color=#ff9900>技术文章</FONT></DIV></TD>
    <TD bgColor=#2875e8 width=1></TD></TR>
  <TR>
    <TD bgColor=#caddfa vAlign=top width=144>&nbsp; </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-&gt;ShowWindow(SW_SHOW);<BR>m_pMainWnd-&gt;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(&amp;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>&nbsp;</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&copy; 
2004-2006</DIV></TD></TR></TBODY></TABLE></DIV></BODY></HTML>

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?