2

I have developed a custom MsgBox that works fine in almost every way. The only problem is that when the MsgBox closes the parent form runs the Form_Activate code. A normal MsgBox does not run that code (again).

I know i could add a boolean variable to Form_Activate to check if it has fired already, but that's not the best solution when you have a dozen forms. So, is there a way to not run Form_Activate after closing my custom MsgBox? Does the MsgBox form need to be of some special type or something? I tried all BorderStyles but that doesn't make any difference.

Martin
  • 1,184
  • 8
  • 24
  • 1
    Form activate means focus has returned to the parent form. Is this dialog shown modally? – Tony Hopkinson Feb 26 '13 at 15:29
  • Yes, the form is shown modally. Otherwise the parent form would not wait for it to return a value. – Martin Feb 26 '13 at 15:37
  • That begs the question of what you're doing in `_Activate` that shouldn't be called twice. As that event will be called whenever your application regains focus, it's NOT suitable for initialisation. – Deanna Feb 26 '13 at 15:43
  • What you say is not true, Deanna. _Activate will only run when it regains focus within it's own application. It does not when it's regains focus from an external application. My solution is definitely suitable. – Martin Feb 26 '13 at 16:14
  • 1
    You mean you have put Form_Load code in Form_Activate (quite common in old VB code)? VB probably treats MsgBox as a special case (which doesn't help you I know) – Rob Feb 26 '13 at 17:35
  • Since the `Activate` event is meant to act just as you are seeing it behave it might be a lot less trouble simply to move "initialization" logic to the `Initialize` and/or `Load` events. – Bob77 Feb 27 '13 at 05:56
  • could you please post the code of form_activate ? – Hrqls Feb 27 '13 at 06:39
  • The `Activate` and `Load` events are both fired when the form is not visible. These events differ for a reason, so it's not "simply" moving code to another event. The code itself has no value for this question. I should be able to run any code i want in the `Activate` event. And yes, my code belongs in `Activate` and not in `Load`. – Martin Feb 27 '13 at 09:51
  • Yes you can run any code in you like in activate. Controlling when activate gets called, very different issue. I might be wrong but I thought avtivate got called when the form get focus. Nothing about in or out of the app – Tony Hopkinson Feb 27 '13 at 12:25

2 Answers2

2

Are you using another form to make custom MsgBox?

You shouldn't use directly other form to show a custom messagebox. You should create an Activex control, and Activate event won't fire again when the MsgBox is closed.

Within the control you can use a form if you want it. (Probably just have to place your code inside an ActiveX control project and use it in your forms)

I use it that way.

This is a custom MsgBox example using Activex Control, with a test form too.

http://www.codeguru.com/code/legacy/vb_othctrl/2166_CustomMsgBox.zip

Gonzalo
  • 2,866
  • 7
  • 27
  • 42
  • I am indeed using another form to create the MsgBox. You're example works, but it has a downside. It requires an ActiveX control on every form i use. Maybe i can still use it by putting the control on one form and then re-use that code publicly. – Martin Feb 27 '13 at 09:48
  • Using an Activex control is not a problem. But anyway you can create a dynamic library (customMsg.dll) and add the reference only once into your proyect, and use on all your forms – Gonzalo Feb 27 '13 at 10:18
  • Is it really easier to add an ActiveX control than just to suppress the logic in Form_Activate with a Boolean? – MarkJ Mar 21 '16 at 15:06
0

I created a Class for a Custom 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

You can use it by typing this:

Dim CMB As New CustomMsgBox
    CCMB.CstMsgBox('MSG, 'TITLE, 'BUTTON1, 'Optional: BUTTON2, 'Optional: BUTTON3)

OR

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