2

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

4

2 回答 2

12

通常,用于创建单实例应用程序的策略是在应用程序初始化中添加一些代码,以确定实例是否已经在运行。如果是,它会获得主窗口的句柄,将焦点传递给它,然后默默地死去。如果不是,它会继续运行并照常完成其余的初始化序列。

您会发现许多旧的 VB 6 文章通过遍历所有顶级窗口来完成此操作,寻找标题与您期望的标题匹配的标题。但这是一个非常脆弱的解决方案,不需要太多就可以摆脱它。

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

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

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

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

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

通过使用与 VB 6 安装捆绑在一起的 API Viewer 程序,您可以找到这些 Windows API 函数的所有 VB 6 声明。

有关处理 VB 6 应用程序的多个实例的更多信息,请访问Karl Peterson 的网站在这篇关于 VB Accelerator的文章中还有一个完整的示例实现——特别关注第 2 步,您不需要其余代码。

于 2012-07-26T12:47:04.497 回答
7

您通常可以以退化的方式使用 DDE 相当简单地做到这一点:

Form1.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

模块1.bas

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
于 2012-07-26T12:56:33.370 回答