Vb6 未触发表单激活的自定义MsgBox

Vb6 未触发表单激活的自定义MsgBox,vb6,msgbox,Vb6,Msgbox,我开发了一个定制的MsgBox,它几乎在所有方面都能正常工作。唯一的问题是,当MsgBox关闭时,父窗体运行form_激活代码。普通的MsgBox不会(再次)运行该代码 我知道我可以在Form_Activate中添加一个布尔变量来检查它是否已经启动了,但是当你有十几个表单时,这不是最好的解决方案。 那么,有没有办法在关闭自定义MsgBox后不运行Form_Activate?MsgBox表单是否需要某种特殊类型或其他类型?我尝试了所有的BorderStyles,但没有任何区别。您是否使用其他表单来

我开发了一个定制的MsgBox,它几乎在所有方面都能正常工作。唯一的问题是,当MsgBox关闭时,父窗体运行form_激活代码。普通的MsgBox不会(再次)运行该代码

我知道我可以在Form_Activate中添加一个布尔变量来检查它是否已经启动了,但是当你有十几个表单时,这不是最好的解决方案。
那么,有没有办法在关闭自定义MsgBox后不运行Form_Activate?MsgBox表单是否需要某种特殊类型或其他类型?我尝试了所有的BorderStyles,但没有任何区别。

您是否使用其他表单来制作自定义MsgBox

您不应该直接使用其他表单来显示自定义messagebox。 您应该创建一个Activex控件,并且当MsgBox关闭时,不会再次触发激活事件

在控件中,如果需要,可以使用表单。(可能只需将代码放在ActiveX控件项目中并在表单中使用即可)

我就是这样用的

这是一个使用Activex控件的自定义MsgBox示例,还有一个测试表单


我为自定义MsgBox创建了一个类

Public Class CustomMsgBox
'Creates the Main form
Dim Main As New Form

'Creates the buttons
Dim Btn1, Btn2, Btn3 As New Button

'Creates the label
Dim Lbl As New Label

'Creates the Output variable
Dim Output As Integer = 0

Private Sub Load()
    'Btn1 properties
    Btn1.Location = New Point(168, 69)
    Btn1.AutoSize = True
    Btn1.AutoSizeMode = AutoSizeMode.GrowOnly

    'Btn2 properties
    Btn2.Location = New Point(87, 69)
    Btn1.AutoSize = True
    Btn1.AutoSizeMode = AutoSizeMode.GrowOnly

    'Btn3 properties
    Btn3.Location = New Point(6, 69)
    Btn1.AutoSize = True
    Btn1.AutoSizeMode = AutoSizeMode.GrowOnly

    'Lbl properties
    Lbl.Location = New Point(12, 19)
    Lbl.AutoSize = True
    Lbl.AutoEllipsis = True

    'Main form properties
    Main.Size = New Size(211, 129)
    Main.AutoSize = True
    Main.AutoSizeMode = AutoSizeMode.GrowOnly
    Main.ShowIcon = False
    Main.Controls.Add(Btn1)
    Main.Controls.Add(Btn2)
    Main.Controls.Add(Btn3)
    Main.Controls.Add(Lbl)

    'Adds Handlers to the buttons
    AddHandler Btn1.Click, AddressOf btn1_Click
    AddHandler Btn2.Click, AddressOf btn2_Click
    AddHandler Btn3.Click, AddressOf btn3_Click

End Sub

Function CstMsgBox(ByRef Msg As String, ByRef Title As String, ByRef B1 As String, Optional ByRef B2 As String = Nothing, Optional ByRef B3 As String = Nothing) As Integer
    'Runs the Load() Sub
    Load()

    'Sets the values
    Lbl.Text = Msg
    Btn1.Text = B1
    Btn2.Text = B2
    Btn3.Text = B3
    Main.Text = Title

    'Checks if there is a value set to Btn2 and Btn3
    If Btn2.Text = Nothing Then
        Btn2.Hide()
    End If
    If Btn3.Text = Nothing Then
        Btn3.Hide()
    End If

    'Shows the MsgBox
    Main.Show()

    'Waits until a button is pressed
    Do Until Output <> 0
        Application.DoEvents()
    Loop

    'Closes the MsgBox
    Main.Close()
    Return Output

End Function

Private Sub btn1_Click(ByVal sender As Object, ByVal e As EventArgs)
    'Sets the Output value to 1
    Output = 1

End Sub

Private Sub btn2_Click(ByVal sender As Object, ByVal e As EventArgs)
    'Sets the Output value to 2
    Output = 2

End Sub

Private Sub btn3_Click(ByVal sender As Object, ByVal e As EventArgs)
    'Sets the Output value to 3
    Output = 3

End Sub
End Class


表单激活表示焦点已返回到父表单。此对话框是否以模式显示?是的,表单以模式显示。否则父窗体将不会等待它返回值。这就引出了一个问题,即您在
\u Activate
中执行的操作不应该被调用两次。因为每当你的应用程序恢复焦点时,就会调用该事件,所以它不适合初始化。你说的不是真的,Deanna_Activate仅在其自身应用程序中恢复焦点时运行。当它从外部应用程序恢复焦点时,它不会。我的解决方案绝对合适。你是说你把Form_Load代码放在Form_Activate中了(在旧的VB代码中很常见)?VB可能将MsgBox视为一个特例(我知道这对您没有帮助),我确实在使用另一个表单来创建MsgBox。你是说,这个例子是有效的,但它也有缺点。我使用的每个表单都需要一个ActiveX控件。也许我仍然可以通过将控件放在一个窗体上,然后公开重新使用该代码来使用它。使用Activex控件不是问题。但是无论如何,您可以创建一个动态库(customMsg.dll)并将引用只添加一次到您的项目中,并在所有表单上使用。添加ActiveX控件比仅使用布尔值来抑制表单中的逻辑要容易得多?使用带DoEvents的循环效率不高。当显示msgbox时,您的CPU可能达到峰值。我不知道其他解决方案。我从网上得到的。
Dim CMB As New CustomMsgBox
    CCMB.CstMsgBox('MSG, 'TITLE, 'BUTTON1, 'Optional: BUTTON2, 'Optional: BUTTON3)
Dim CMB As New CustomMsgBox
    Select Case CMB.CstMsgBox('MSG, 'TITLE, 'BUTTON1, 'Optional: BUTTON2, 'Optional: BUTTON3)
        Case 1
            'Code to execute when button1 is pressed
        Case 2
            'Code to execute when button2 is pressed
        Case 3
            'Code to execute when button3 is pressed
    End Select