找回密码
 加入我们

QQ登录

只需一步,快速开始

搜索
查看: 5052|回复: 0

[开源] 【分享】只允许程序运行一个实例的方法,非CMutex

[复制链接]

1214

主题

352

回帖

11

精华

管理员

菜鸟

积分
93755

贡献奖关注奖人气王精英奖乐于助人勋章

发表于 2009-7-20 23:03:38 | 显示全部楼层 |阅读模式
<p>比较经典的方法是使用Metex或Semaphore,并配合FindWindow或GetPara、SetPara来完成限制第二个实例的运行,并激活第一个实例。</p>
<p>使用data_seg来完成此任务则显得特别简单。</p>
<p>以基于对话框的程序为例:</p>
<p>首先,在主对话框(***Dlg.cpp文件)的开始部分,加入下列代码:</p>
<p>#pragma data_seg("sharesec")<br/>__declspec (allocate("sharesec")) HWND g_testapp_share_hWnd = NULL;<br/>#pragma comment(linker,"/SECTION:sharesec,RWS")</p>
<p>其中,g_testapp_share_hWnd 用来保存第一个实例的主窗口句柄。</p>
<p>然后在,OnInitDialog中加入下列代码:</p>
<p>if(g_testapp_share_hWnd)<br/>{<br/>&nbsp;&nbsp; AfxMessageBox(_T("已经有一个实例在运行!"));<br/>&nbsp;&nbsp; CWnd* pWnd = CWnd::FromHandle(g_testapp_share_hWnd);<br/>&nbsp;&nbsp; if(pWnd)<br/>&nbsp;&nbsp; {<br/>&nbsp;&nbsp;&nbsp; pWnd-&gt;ShowWindow(SW_SHOW);<br/>&nbsp;&nbsp;&nbsp; pWnd-&gt;SetForegroundWindow();<br/>&nbsp;&nbsp; }<br/>&nbsp;&nbsp; exit(0);<br/>}<br/>else<br/>{<br/>&nbsp;&nbsp; g_testapp_share_hWnd = m_hWnd;<br/>}</p>
<p>这样就完成了,只允许程序运行一个实例,并激活前一个程序的任务,简单吧? ^_^</p>
<p>~~~~~以下是完整的主对话框类实现文件,蓝色的部分即为上述新加的代码~~~~~</p>
<p>#include "stdafx.h"<br/>#include "TestApp.h"<br/>#include "TestAppDlg.h"</p>
<p>#ifdef _DEBUG<br/>#define new DEBUG_NEW<br/>#undef THIS_FILE<br/>static char THIS_FILE[] = __FILE__;<br/>#endif</p>
<p><font color="#0000ff">#pragma data_seg("sharesec")<br/>__declspec (allocate("sharesec")) HWND g_testapp_share_hWnd = NULL;<br/>#pragma comment(linker,"/SECTION:sharesec,RWS")</font></p>
<p>class CAboutDlg : public CDialog<br/>{<br/>public:<br/>CAboutDlg();</p>
<p>//{{AFX_DATA(CAboutDlg)<br/>enum { IDD = IDD_ABOUTBOX };<br/>//}}AFX_DATA</p>
<p>//{{AFX_VIRTUAL(CAboutDlg)<br/>protected:<br/>virtual void DoDataExchange(CDataExchange* pDX);&nbsp;&nbsp;&nbsp;&nbsp; // DDX/DDV support<br/>//}}AFX_VIRTUAL<br/>protected:<br/>//{{AFX_MSG(CAboutDlg)<br/>//}}AFX_MSG<br/>DECLARE_MESSAGE_MAP()<br/>};</p>
<p>CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)<br/>{<br/>//{{AFX_DATA_INIT(CAboutDlg)<br/>//}}AFX_DATA_INIT<br/>}</p>
<p>void CAboutDlg:oDataExchange(CDataExchange* pDX)<br/>{<br/>CDialog:oDataExchange(pDX);<br/>//{{AFX_DATA_MAP(CAboutDlg)<br/>//}}AFX_DATA_MAP<br/>}</p>
<p>BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)<br/>//{{AFX_MSG_MAP(CAboutDlg)<br/>//}}AFX_MSG_MAP<br/>END_MESSAGE_MAP()</p>
<p>CTestAppDlg::CTestAppDlg(CWnd* pParent /*=NULL*/)<br/>: CDialog(CTestAppDlg::IDD, pParent)<br/>{<br/>//{{AFX_DATA_INIT(CTestAppDlg)<br/>//}}AFX_DATA_INIT<br/>m_hIcon = AfxGetApp()-&gt;LoadIcon(IDR_MAINFRAME);<br/>}</p>
<p>void CTestAppDlg:oDataExchange(CDataExchange* pDX)<br/>{<br/>CDialog:oDataExchange(pDX);<br/>//{{AFX_DATA_MAP(CTestAppDlg)<br/>//}}AFX_DATA_MAP<br/>}</p>
<p>BEGIN_MESSAGE_MAP(CTestAppDlg, CDialog)<br/>//{{AFX_MSG_MAP(CTestAppDlg)<br/>ON_WM_SYSCOMMAND()<br/>ON_WM_PAINT()<br/>ON_WM_QUERYDRAGICON()<br/>//}}AFX_MSG_MAP<br/>END_MESSAGE_MAP()</p>
<p>BOOL CTestAppDlg::OnInitDialog()<br/>{<br/>CDialog::OnInitDialog();</p>
<p>ASSERT((IDM_ABOUTBOX &amp; 0xFFF0) == IDM_ABOUTBOX);<br/>ASSERT(IDM_ABOUTBOX &lt; 0xF000);</p>
<p>CMenu* pSysMenu = GetSystemMenu(FALSE);<br/>if (pSysMenu != NULL)<br/>{<br/>&nbsp;&nbsp; CString strAboutMenu;<br/>&nbsp;&nbsp; strAboutMenu.LoadString(IDS_ABOUTBOX);<br/>&nbsp;&nbsp; if (!strAboutMenu.IsEmpty())<br/>&nbsp;&nbsp; {<br/>&nbsp;&nbsp;&nbsp; pSysMenu-&gt;AppendMenu(MF_SEPARATOR);<br/>&nbsp;&nbsp;&nbsp; pSysMenu-&gt;AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);<br/>&nbsp;&nbsp; }<br/>}</p>
<p>SetIcon(m_hIcon, TRUE);&nbsp;&nbsp;&nbsp;<br/>SetIcon(m_hIcon, FALSE);&nbsp;&nbsp;<br/><br/><font color="#0000ff">if(g_testapp_share_hWnd)<br/>{<br/>&nbsp;&nbsp; AfxMessageBox(_T("已经有一个实例在运行!"));<br/>&nbsp;&nbsp; CWnd* pWnd = CWnd::FromHandle(g_testapp_share_hWnd);<br/>&nbsp;&nbsp; if(pWnd)<br/>&nbsp;&nbsp; {<br/>&nbsp;&nbsp;&nbsp; pWnd-&gt;ShowWindow(SW_SHOW);<br/>&nbsp;&nbsp;&nbsp; pWnd-&gt;SetForegroundWindow();<br/>&nbsp;&nbsp; }<br/>&nbsp;&nbsp; exit(0);<br/>}<br/>else<br/>{<br/>&nbsp;&nbsp; g_testapp_share_hWnd = m_hWnd;<br/>}</font></p>
<p>return TRUE;&nbsp;&nbsp;<br/>}</p>
<p>void CTestAppDlg::OnSysCommand(UINT nID, LPARAM lParam)<br/>{<br/>if ((nID &amp; 0xFFF0) == IDM_ABOUTBOX)<br/>{<br/>&nbsp;&nbsp; CAboutDlg dlgAbout;<br/>&nbsp;&nbsp; dlgAbout.DoModal();<br/>}<br/>else<br/>{<br/>&nbsp;&nbsp; CDialog::OnSysCommand(nID, lParam);<br/>}<br/>}</p>
<p>void CTestAppDlg::OnPaint() <br/>{<br/>if (IsIconic())<br/>{<br/>&nbsp;&nbsp; CPaintDC dc(this);</p>
<p>&nbsp;&nbsp; SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);</p>
<p>&nbsp;&nbsp; int cxIcon = GetSystemMetrics(SM_CXICON);<br/>&nbsp;&nbsp; int cyIcon = GetSystemMetrics(SM_CYICON);<br/>&nbsp;&nbsp; CRect rect;<br/>&nbsp;&nbsp; GetClientRect(&amp;rect);<br/>&nbsp;&nbsp; int x = (rect.Width() - cxIcon + 1) / 2;<br/>&nbsp;&nbsp; int y = (rect.Height() - cyIcon + 1) / 2;</p>
<p>&nbsp;&nbsp; dc.DrawIcon(x, y, m_hIcon);<br/>}<br/>else<br/>{<br/>&nbsp;&nbsp; CDialog::OnPaint();<br/>}<br/>}</p>
<p>HCURSOR CTestAppDlg::OnQueryDragIcon()<br/>{<br/>return (HCURSOR) m_hIcon;<br/>}</p>
<p>///////////////////////////////////////////////////////////////////////////////////////////////////////////////////</p>
<p><font size="2">Microsoft 的Visual C++编译器提供了一个A l l o c a t e说明符,使你可以将未经初始化的数据放入你希望的任何节中。请看下面的代码:</font></p>
<p></p>
<div style="LINE-HEIGHT: 25px; BACKGROUND-COLOR: #d7d7d7"><pre>// Create Shared section &amp; have compiler place initialized data in it.
#pragma data_seg("Shared")

// Initialized, in Shared section
int a = 0;

// Uninitialized, not in Shared section
int b;

// Have compiler stop placing initialized data in Shared section.
#pragma data_seg()

// Initialized, in Shared section
__declspec(allocate("Shared")) int c = 0;

// Uninitialized, in Shared section
__declspec(allocate("Shared")) int d;

// Initialized, not in Shared section
int e = 0;

// Uninitialized, not in Shared section
int f;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</pre></div>
<p><font style="LINE-HEIGHT: 25px" color="#000000" size="2">上面的注释清楚地指明了指定的变量将被放入哪一节。若要使A l l o c a t e声明的规则正确地起作用,那么首先必须创建节。如果删除前面这个代码中的第一行#pragma data_seg,上面的代码将不进行编译。</font></p>
<p><font style="LINE-HEIGHT: 25px" color="#000000" size="2">之所以将变量放入它们自己的节中,最常见的原因也许是要在. e x e或D L L文件的多个映像之间共享这些变量。按照默认设置, . e x e或D L L文件的每个映像都有它自己的一组变量。然而,可以将你想在该模块的所有映像之间共享的任何变量组合到它自己的节中去。当给变量分组时,系统并不为. e x e或D L L文件的每个映像创建新实例。</font></p>
<p>本帖来源:<font face="Verdana"><a href="http://hi.baidu.com/wuzj/blog/item/044aa951dda1da888d543053.html">http://hi.baidu.com/wuzj/blog/item/044aa951dda1da888d543053.html</a></font></p>
[此贴子已经被作者于2009-7-20 23:04:42编辑过]
【VB】QQ群:1422505加的请打上VB好友
【易语言】QQ群:9531809  或 177048
【FOXPRO】QQ群:6580324  或 33659603
【C/C++/VC】QQ群:3777552
【NiceBasic】QQ群:3703755
您需要登录后才可以回帖 登录 | 加入我们

本版积分规则

快速回复 返回顶部 返回列表