当用户试图在vb6中打开新实例时,返回到已打开的应用程序

当用户试图在vb6中打开新实例时,返回到已打开的应用程序,vb6,Vb6,假设用户将我的visual basic应用程序最小化到任务栏通知图标。现在,我希望当用户打开一个新实例时,旧实例应该恢复。通常,用于创建单实例应用程序的策略是向应用程序初始化中添加一些代码,以确定实例是否已在运行。如果是,它将获得主窗口的句柄,将焦点传递给它,然后静默地消失。如果没有,它将继续运行,并像往常一样完成初始化序列的其余部分 你会发现很多旧的VB6文章都是通过遍历所有的顶级窗口来实现这一点的,寻找一个与你期望的标题匹配的窗口。但这是一个相当脆弱的解决方案,不需要太多时间就能摆脱它 同样

假设用户将我的visual basic应用程序最小化到任务栏通知图标。现在,我希望当用户打开一个新实例时,旧实例应该恢复。

通常,用于创建单实例应用程序的策略是向应用程序初始化中添加一些代码,以确定实例是否已在运行。如果是,它将获得主窗口的句柄,将焦点传递给它,然后静默地消失。如果没有,它将继续运行,并像往常一样完成初始化序列的其余部分

你会发现很多旧的VB6文章都是通过遍历所有的顶级窗口来实现这一点的,寻找一个与你期望的标题匹配的窗口。但这是一个相当脆弱的解决方案,不需要太多时间就能摆脱它

同样的处理。这是非常简单的使用,但也非常简单的实现。它根据可执行文件的名称工作,并查找名称匹配的正在运行的进程。但是,如果用户创建并重命名可执行文件的副本,这很容易失败。如果这对您来说是可以接受的,您可以通过查询
App.PrevInstance
属性来非常轻松地实现这一点。否则,您将需要使用更健壮的解决方案

一种可能性是在应用程序的第一个实例启动时创建并注册一个命名互斥体。然后,当后续实例尝试注册相同的互斥时,它们将失败,这表明实例已经在运行。您可以在的答案中找到有关在VB6中使用互斥体的说明

使用互斥体的几个重要注意事项:

  • 您需要确保在应用程序关闭时调用和函数,以释放您创建的互斥体的所有权并销毁它

  • 当您在VB6IDE中运行程序(例如调试它)并且它注册了一个互斥体时,互斥体属于IDE,在您关闭IDE并重新启动它之前不会被释放。为了防止出现这种情况,可以在IDE/调试器内部使用条件编译运行时禁止创建互斥体。如果您采用这种方法,请确保在调试器之外测试您的程序,以确保与互斥相关的功能按预期工作!您永远不应该将未经彻底测试的产品发送给客户

通过使用随VB6安装附带的API查看器程序,可以找到这些Windows API函数的所有VB6声明


有关处理VB6应用程序的多个实例的更多信息,请参见。还有一个完整的示例实现,特别是在步骤2中,您不需要剩下的代码。

您通常可以简单地使用DDE以退化的方式来实现:

格式1.frm

Option Explicit
'This is Form1.  To use as DDE source at design time we set:
'   Form1.LinkMode = 1 (Source, i.e. vbLinkSource).
'   Form1.LinkTopic = "Form1" (default).
'
'Note we use (hidden) Label1 on this Form as a DDE destination.

Private PrevState As Integer

Private Sub Form_LinkExecute(CmdStr As String, Cancel As Integer)
    'Got a "command" so restore Form1 and accept the command.
    WindowState = PrevState
    Caption = "I am awake!"
    Cancel = False
End Sub

Private Sub Form_Load()
    PrevState = WindowState
End Sub

Private Sub Form_Resize()
    If WindowState <> vbMinimized Then PrevState = WindowState
End Sub

我没有尝试过任何东西,但想过通过在注册表中创建一个值来向旧实例发送消息,但我正在寻找一种不需要计时器的简洁方式……为什么不让新应用程序检查现有实例(例如,使用a),如果它存在,使用和查找hWnd并显示/恢复窗口?你怎么知道它不起作用,你刚才说你没有尝试过任何东西?为什么要将它隐藏在屏幕上?这可能就是为什么他们一直在开始一个新的副本…很好的答案。我正在写一本,但你的涵盖了我要说的一切,还有更多。我写了一些类似的东西,但你显然能比我更快地找到链接。:-)很抱歉,我已经理解了所有这些,并且也检查了,但是我的旧实例使用了me.hide code并在任务栏中显示,但是我想要的是exexution me.show code(在创建新实例时显示代码)。@Varun:是的。其思想是检测前一个实例是否正在运行,如果正在运行,则将焦点设置为该实例并将其置于前台。但是,当有人双击您的通知区域图标时,您将应用程序置于前台,这与您在结束重复实例之前将前一个实例置于前台的方式相同。+1。回答得好!但是当你的程序关闭时,你不需要做任何特殊的事情。当进程终止时,Windows将自动释放互斥锁并关闭句柄。我喜欢这个+1。“退化”可能是,但这并不比必须为新实例提供一些外部指标更重要,关于是恢复
正常
还是最大化
我认为如果应用程序使用多个顶级窗口,也很容易适应。与我过去使用的API方法相比,它显然是一个更简洁的解决方案。也许更好的词可能是残留的、最小的、琐碎的,甚至是重新调整用途。“degrade”在日常用语中有太多的负面含义。@Rob说实话,我不知道“degrade”在编程中的含义。我偶尔会看到它被使用,并且有点假设它的意思是“不正确的用法”,但毫无疑问,我离这个目标还有很远的距离。:-)它在工程学和数学中有一定的字面意义,完全脱离了俗语的社会内涵。例如,在几何中,点是退化圆,圆是退化椭圆,等等。
Option Explicit

Private Sub Main()
    Load Form1
    'After Form1 is loaded (hidden), try DDE link to possible prior copy.
    With Form1.Label1
        .LinkTopic = App.EXEName & "|Form1"
        On Error Resume Next
        .LinkMode = vbLinkManual
        If Err.Number = 0 Then
            On Error GoTo 0
            'Link succeeded.  Wake up prior copy via pushback to
            'the DDE source, then unload Form1 and terminate.
            .LinkExecute "Wake up!"
            Unload Form1
        Else
            On Error GoTo 0
            'Link failed, so we're 1st.  Show Form1.
            Form1.Show vbModal
        End If
    End With
End Sub