用DDE实现窗体防止运行多个实例并传递命令

上网的朋友一定都用过网络蚂蚁(Net Ants)的吧?不知你在使用过程中有没有注意过,那就是如果你想调动两个“蚂蚁”为您效力是不可能的——它总会把新运行的关闭。这点在VB 中很容易实现:

Private Sub Form_Load()

If App.PrevInstance Then

MsgBox "你已经运行这个应用程序了"

End   注释: 退出新运行的程序

End If

End Sub

这样如果你运行这个程序后在运行它,它会弹出一个消息框并拒绝再次运行。这非常容易。

而“蚂蚁”程序的妙处就在于:在重复运行“蚂蚁”时它不仅拒绝运行,而且能把已经运行的“蚂蚁”激活,这样用上面的程序就无能为力了。但事实上实现拒绝运行并激活已运行的 程序有多种方法:

1、用FindWindow函数得到已经运行窗体的句柄(HWND),然后用SetActiveWindow等API函数将其激活。其缺点也很明显,那就是没法传递参数。

2、用FindWindow函数得到已运行窗体的句柄后用SendMessage的方法给窗体传送一个自定义消息(附带参数),然后在窗体中拦截并进行处理,但这样做要修改窗体的标准消息处理程序,用在VC,BC或DELPHI编写的程序中还行,但在VB中工作量太大,并且容易发生“一般保护行错误”使VB崩溃,不太可取(当然,如果你有足够的信心和不怕崩溃的精神,也可以试一下 ^_^ )。

3、使用DDE技术。

所谓DDE技术,就是动态数据交换技术。也许你很奇怪,这与本文所讨论的内容有什么相干的?且听我慢慢讲来。

为了实现拒绝运行并把已经运行的程序激活并实现各种功能,我们可以先用本文开头提到的方法,检测一下程序有没有被运行过,如果没有,就正常运行,如果已经被运行过,就打通与它的DDE通道,传给它一个(或一些)数据,然后由已经运行的程序对数据进行处理,再去实现各种“意想不到”的功能,这时也许就有人对这你的程序喊:“酷、酷……” ^_^

好了,耳听为虚,眼见为实,下面让我们动点真格的。

打开VB,新建一个工程,选择菜单中的“工程->工程1 属性”,把工程名称改为“P1”(我爱偷懒,能短则短 ^_^ ),把已有的一个窗体的“LinkTopic”属性改为“FormDDE”,把“LinkMode” 属性改为“1 - Source”,添加一个PictureBox控件作为DDE执行控件,命名为picDDE。然后添加一个 TextBox控件,命名为“txtInfo”,并把“MultiLine”属性设置为“True”,以便显示多行文本,作为 消息显示控件。

最后在窗体代码区输入以下代码:

Const COMMANDLINE = "CommandLine="    注释: 还是为了省事,定义一个常量
Private Sub Form_LinkExecute(CmdStr As String, Cancel As Integer)
Static lngCount As Long
Dim Info As String
Info = txtInfo.Text   注释:   保留原有信息
Select Case CmdStr     注释:  CmdStr 是DDE程序传送过来的参数
  Case "Max"
   Me.WindowState = 2
   Info = Info + vbNewLine + "窗体已被最大化"
  Case "ShowTime"
   Info = Info + vbNewLine + "最后一次运行这个程序的时间是:" + Str(Now)
  Case "Count"
   lngCount = lngCount + 1
   Info = Info + vbNewLine + "你已经第" + Str(lngCount) + "次重复调用这个程序。" _
       + vbNewLine + "但怕您不多给工资,所以只运行了一个 ^_^"
End Select
If Left(CmdStr, Len(COMMANDLINE)) = COMMANDLINE Then
  Info = Info + vbNewLine + "新程序曾以命令行形式运行" + vbNewLine + "命令行为:" _
     + vbNewLine + Right(CmdStr, Len(CmdStr) - Len(COMMANDLINE))
End If
txtInfo.Text = Info   注释:  把信息显示出来
Cancel = False  
End Sub
Private Sub LinkAndSendMessage(ByVal Msg As String)
Dim t As Long
picDDE.LinkMode = 0        注释:--
picDDE.LinkTopic = "P1|FormDDE"  注释: |______连接DDE程序并发送数据/参数
picDDE.LinkMode = 2        注释: |   “|”为管道符,是“退格键”旁边的竖线,
picDDE.LinkExecute Msg      注释:--    不是字母或数字!
t = picDDE.LinkTimeout   注释:--
picDDE.LinkTimeout = 1   注释: |______终止DDE通道。当然,也可以用别的方法
picDDE.LinkMode = 0    注释: |   这里用的是超时强制终止的方法
picDDE.LinkTimeout = t   注释:--
End Sub
Private Sub Form_Load()
If App.PrevInstance Then   注释: 程序是否已经运行
  Me.LinkTopic = ""     注释: 这两行用于清除新运行的程序的DDE服务器属性,
  Me.LinkMode = 0      注释: 否则在连接DDE程序时会出乱子的
  LinkAndSendMessage "Max"     注释:--
  LinkAndSendMessage "Count"    注释: |-----连接DDE接受程序并传送数据/参数
  LinkAndSendMessage "ShowTime"   注释:--
  If Command <> "" Then       注释: 如果有命令行参数,就传递过去
   LinkAndSendMessage COMMANDLINE + Command
  End If
  End                注释: 结束新程序的运行
End If
End Sub

测试一下:

把工程“P1”编译成EXE文件(设名称为 P1.EXE )

1、打开“我的电脑”,找到 P1.EXE 并执行。可以看到程序正常运行了。

2、再运行一次,这次新程序没有运行成功,而原来运行的程序却被最大化了,而且文本框中有以下

字符:

窗体已被最大化

你已经第 1次重复调用这个程序。

但怕您不多给工资,所以只运行了一个 ^_^

最后一次运行这个程序的时间是:00-2-6 7:11:01

3、打开 MS-DOS方式 ,用命令行方式再次运行程序,如 “P1 How Are You?”

这时原来运行的程序文本框中又多了几行字:

窗体已被最大化

你已经第 2次重复调用这个程序。

但怕您不多给工资,所以只运行了一个 ^_^

最后一次运行这个程序的时间是:00-2-6 7:14:32

新程序曾以命令行形式运行

命令行为:

How Are You?

OK,运行完全正确,然后你就可以把它应用的你的程序中了。

当然,这只是一些个人心得,如有疏漏之出,还请各位大虾指正。

时间: 2024-11-02 09:20:20

用DDE实现窗体防止运行多个实例并传递命令的相关文章

创建C#窗体 当运行时只显示标题栏(如ENVI)

问题描述 创建C#窗体当运行时只显示标题栏(如ENVI) 解决方案 解决方案二:应该是工具栏吧解决方案三:没看明白,请lz再详细描述下你的需求呢?解决方案四:LZ你想干啥,只有标题栏的船体还有啥意义啊,单纯的为了显示标题?如果是想嵌入其他窗体的话,还不如搞成自定义控件解决方案五:需求不明确

Python实现保证只能运行一个脚本实例

  这篇文章主要介绍了Python实现保证只能运行一个脚本实例,本文直接给出实现代码,需要的朋友可以参考下 保证只能运行一个脚本实例,方法是程序运行时监听一个特定端口,如果失败则说明已经有实例在跑. 使用装饰器实现,便于重用 代码如下: import functools def just_one_instance(func): ''' 装饰器 如果已经有实例在跑则退出 复制代码 代码如下: :return: ''' @functools.wraps(func) def f(*args,**kwa

javascript 实现子父窗体互相传值的简单实例

 本篇文章主要是对javascript 实现子父窗体互相传值的简单实例进行了介绍,需要的朋友可以过来参考下,希望对大家有所帮助 window.showModalDialog() 使用方法:   var returnValue = window.showModalDialog(url [, arguments] [,features]);   url  -- 必选参数,类型:字符串,用来指定对话框要显示的文档的URL   arguments  -- 可选参数,类型:变体,用来向对话框传递参数,传递

一个Tomcat运行多个实例

本文介绍在同一个tomcat下运行mydomain.com和mysite.com这两个实例的步骤. 有时候,我们希望周期性的更新Tomcat:有时候,我们又想统一管理安装在一台机器上的tomcat(比如让tomcat版本统一,让多个实例的tomcat的依赖统一.配置统一等).在这些场景下,我们都不希望把Web应用程序的文件放入Tomcat发行版的目录结构中,而是让一个tomcat运行多个实例,并把Web应用放在tomcat的安装目录之外. 一般在使用Tomcat时,服务器会从conf及webap

我想做一个窗体,这里面可以像在dos命令窗下一样输入命令,并在文本域显示结果,用java该怎么写

问题描述 我想做一个窗体,这里面可以像在dos命令窗下一样输入命令,并在文本域显示结果,用java该怎么写 要效果完全跟dos一样,我试过用 rutime.getRuntime().exec(),但是有些命令可以得到正确结果,有些命令就没反应,像ping命令arp-a就可以,java,c:,dir,这些就不行,不知其中奥妙,求大神给个程序,我搜了很多感觉都不适合 解决方案 http://www.cnblogs.com/leohxj/archive/2012/11/26/2789284.html

PHP+FastCGI+Nginx配置PHP运行环境_php实例

      CGI的英文全称为Common Gateway Interface(公共网关接口),是Nginx和动态脚本程序的桥梁,Nginx通过FastCGI接口将动态请求发送给FastCGI,FastCGI中的Wrapper进程生成一个线程,将请求交给脚本解释程序执行,然后通过原来的socket将解释执行后的结果原路返回给Nginx,之后Nginx将结果交给客户端.     Nginx是通过套接字文件socket来将动态请求发送给wrapper,使用的是Tcp协议.wrapper通过CGI接口

同一个PC只能运行一个应用实例(考虑多个用户会话情况)

原文:同一个PC只能运行一个应用实例(考虑多个用户会话情况) 1 class Program 2 { 3 private static Mutex m; 4 5 [STAThread] 6 static void Main() 7 { 8 bool createNew = false; 9 10 /* 11 * 在运行终端服务的服务器上,已命名的系统 mutex 可以具有两级可见性. 12 * 如果名称以前缀"Global\"开头,则 mutex 在所有终端服务器会话中均为可见. 13

用vbs检索在运行对话框中键入的一系列命令的代码_vbs

问: 您好,脚本专家!有时,我在运行对话框中键入了多个命令,随后想要对其进行检索.我知道我最近使用过的命令缓存在某个地方,因为当我开始在运行对话框中键入时,它们便会显示出来.如何使用脚本检索这些命令? -- KJ 答: 您好,KJ.您知道,一看到您的问题,我们首先想到的是:为什么我们没有想过这个问题?不用说,脚本专家使用运行对话框已经有好多年了,并且我们也非常清楚地知道,最近使用的命令(如果您统计过的话,是最近使用过的 26 个)缓存在计算机上的某个地方.然而,我们从未编写过可检索此列表的脚本.

用VB.NET做一个单词查询的小窗体,运行没有反应

问题描述 数据库用的是SQLSERVER2000,已经建立一个叫me的数据库,单词存在1个叫az的表中我想实现的功能是再textbook1中输入单词(模糊查询),下面的listbox1中能显示全部可能单词,然后用户选择出待查单词,又能显示出单词全部的信息,但现在代码如下,在textbox中输入单词后运行没有任何反应PublicClassForm1DimiAsIntegerPrivateSubTextBox1_TextChanged(ByValsenderAsObject,ByValeAsSyst