开发者

MessageBox.Show not raising HelpRequested event

I have a form that is showing a MessageBox using MessageBox.Show, and trying to receive events from the Help button on the MessageBox so I can execute my own code. The Microsoft documentation shows how to do this; however, using what is suggested does not work. H开发者_Go百科ere's a shortened version of my code:

    Private Function MethodName() As Boolean

      AddHandler Me.HelpRequested, AddressOf Me.MsgBoxHelpRequested
      Select Case MessageBox.Show("Text", "Title", MessageButtons.YesNoCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2, 0, True)
        Case MsgBoxResult.Yes
          ' Do stuff
        Case MsgBoxResult.No
          ' Do stuff
        Case MsgBoxResult.Cancel
          RemoveHandler Me.HelpRequested, AddressOf Me.MsgBoxHelpRequested
          Return False
      End Select
      RemoveHandler Me.HelpRequested, AddressOf Me.MsgBoxHelpRequested

    End Function

Private Sub MsgBoxHelpRequested(ByVal sender As Object, ByVal hlpevent As System.Windows.Forms.HelpEventArgs)
  ' Breakpoint that never gets hit
  ' More code
End Sub

I've been searching for a solution to this problem, but the best I've found is this question: How to detect Help button press in Windows Forms MessageBox? that refers me back to the same Microsoft code that doesn't seem to be working.

Can anybody help me with this?

Thank you.


Pass Me as the first parameter to MessageBox.Show.

Add the handler to Form.ActiveForm instead of Me.


This is C#, and I'll auto-translate it to VB in a second.

Put this code in your form's Load event:

this.HelpRequested += new HelpEventHandler(Form1_HelpRequested);

Then add this code to your form:

void Form1_HelpRequested(object sender, HelpEventArgs hlpevent)
{
    hlpevent.Handled = true; // this will prevent windows from also opening
        // any associated help file
    // do whatever you're gonna do here
}

Then call MessageBox like this:

MessageBox.Show("message", "caption", MessageBoxButtons.OK, 
    MessageBoxIcon.Asterisk,
    MessageBoxDefaultButton.Button1, 0, true);

This will show a message box with OK and HELP buttons. When HELP is clicked, Form1_HelpRequested will be called.

VB.Net version:

Put this code in your form's Load event:

AddHandler Me.HelpRequested, AddressOf Form1_HelpRequested 

Then add this code to your form:

Private Sub Form1_HelpRequested(ByVal sender As Object, ByVal hlpevent As 
    HelpEventArgs) 
    ' this will prevent windows from also opening 
    ' any associated help file:
    hlpevent.Handled = True 
    ' do whatever you're gonna do here 
End Sub

Then call MessageBox like this:

MessageBox.Show("message", "caption", MessageBoxButtons.OK, 
    MessageBoxIcon.Asterisk, MessageBoxDefaultButton.Button1, 0, _ 
    True)

This will show a message box with OK and HELP buttons. When HELP is clicked, Form1_HelpRequested will be called.


If you call MethodName for the form's constructor (new) or in the form's Load event, you sample code will not work. That may be why it is not working for you.

The constructor is Sub New. You have to be careful of some initializations in the constructor or the form's Load event. The reason being is the handle to the control, which includes the form, is not created yet. If you test project works, then compare the test project to what you have. Consider how you are calling the methods and where. The most likely reason your application is not working, is due to the handler is not added because form is not created. (It is created when the form becomes visible. You can try adding a form.CreateControl just before adding the handler.)

Moreover, try adding the handler to the form through the designer. This will guarantee handler is assigned correctly. (The MSDN example does everything manually, and is not a good example. The VB example should show you how to do this the easy VB way, instead of a more advanced manual way.)

Public Class Form1
    Inherits System.Windows.Forms.Form

#Region " Designer-Generated "

    'Form overrides dispose to clean up the component list. 
    <System.Diagnostics.DebuggerNonUserCode()> _
    Protected Overrides Sub Dispose(ByVal disposing As Boolean)
        Try
            If disposing AndAlso components IsNot Nothing Then
                components.Dispose()
            End If
        Finally
            MyBase.Dispose(disposing)
        End Try
    End Sub
    Friend WithEvents Button2 As System.Windows.Forms.Button

    'Required by the Windows Form Designer 
    Private components As System.ComponentModel.IContainer

    'NOTE: The following procedure is required by the Windows Form Designer 
    'It can be modified using the Windows Form Designer.   
    'Do not modify it using the code editor. 
    <System.Diagnostics.DebuggerStepThrough()> _
    Private Sub InitializeComponent()
        Me.Button1 = New System.Windows.Forms.Button
        Me.Button2 = New System.Windows.Forms.Button
        Me.SuspendLayout()
        '
        'Button1
        '
        Me.Button1.Location = New System.Drawing.Point(0, 0)
        Me.Button1.Name = "Button1"
        Me.Button1.Size = New System.Drawing.Size(75, 23)
        Me.Button1.TabIndex = 0
        Me.Button1.Text = "Button1"
        Me.Button1.UseVisualStyleBackColor = True
        '
        'Button2
        '
        Me.Button2.Location = New System.Drawing.Point(0, 29)
        Me.Button2.Name = "Button2"
        Me.Button2.Size = New System.Drawing.Size(75, 23)
        Me.Button2.TabIndex = 1
        Me.Button2.Text = "Button2"
        Me.Button2.UseVisualStyleBackColor = True
        '
        'Form1
        '
        Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
        Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
        Me.ClientSize = New System.Drawing.Size(292, 266)
        Me.Controls.Add(Me.Button2)
        Me.Controls.Add(Me.Button1)
        Me.Name = "Form1"
        Me.Text = "Form1"
        Me.ResumeLayout(False)

    End Sub
    Friend WithEvents Button1 As System.Windows.Forms.Button

#End Region

    Public Sub New()
        ' This call is required by the Windows Form Designer. 
        InitializeComponent()
        ' Add any initialization after the InitializeComponent() call. 
        MethodName() 'will not work here 
    End Sub

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        MethodName() 'will not work here 
        'Me.CreateControl()
        MethodName2() 'still will not work 
    End Sub

    Private Function MethodName() As Boolean
        AddHandler Me.HelpRequested, AddressOf Me.MsgBoxHelpRequested
        Select Case MessageBox.Show("Text", "Title", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2, 0, True)
            Case Windows.Forms.DialogResult.Yes
                ' Do stuff  
            Case Windows.Forms.DialogResult.No
                ' Do stuff  
            Case Windows.Forms.DialogResult.Cancel
                RemoveHandler Me.HelpRequested, AddressOf Me.MsgBoxHelpRequested
                Return False
        End Select
        RemoveHandler Me.HelpRequested, AddressOf Me.MsgBoxHelpRequested
    End Function

    Private Function MethodName2() As Boolean
        AddHandler Me.HelpRequested, AddressOf Me.MsgBoxHelpRequested2
        Select Case MessageBox.Show("Text", "Title", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2, 0, True)
            Case Windows.Forms.DialogResult.Yes
                ' Do stuff  
            Case Windows.Forms.DialogResult.No
                ' Do stuff  
            Case Windows.Forms.DialogResult.Cancel
                RemoveHandler Me.HelpRequested, AddressOf Me.MsgBoxHelpRequested2
                Return False
        End Select
        RemoveHandler Me.HelpRequested, AddressOf Me.MsgBoxHelpRequested2
    End Function


    ''' <summary>
    '''  AddHandler Me.HelpRequested, AddressOf Module1.MsgBoxHelpRequested3
    ''' </summary>
    Private Function MethodName3() As Boolean
        AddHandler Me.HelpRequested, AddressOf Module1.MsgBoxHelpRequested3
        Select Case MessageBox.Show("Text", "Title", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button3, 0, True)
            Case Windows.Forms.DialogResult.Yes
                ' Do stuff  
            Case Windows.Forms.DialogResult.No
                ' Do stuff  
            Case Windows.Forms.DialogResult.Cancel
                RemoveHandler Me.HelpRequested, AddressOf Module1.MsgBoxHelpRequested3
                Return False
        End Select
        RemoveHandler Me.HelpRequested, AddressOf Module1.MsgBoxHelpRequested3
    End Function

    Private Sub MsgBoxHelpRequested(ByVal sender As Object, ByVal hlpevent As System.Windows.Forms.HelpEventArgs)
        ' Breakpoint that never gets hit  
        MsgBox("Here I am to save the day!")
    End Sub

    Private Sub MsgBoxHelpRequested2(ByVal sender As Object, ByVal hlpevent As System.Windows.Forms.HelpEventArgs)
        ' Breakpoint that never gets hit  
        MsgBox("Shoot, still now working.")
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        MethodName() 'always works because all handles are created 
    End Sub

    Private Sub Form1_HelpRequested(ByVal sender As System.Object, ByVal hlpevent As System.Windows.Forms.HelpEventArgs) Handles MyBase.HelpRequested
        MsgBox("Always works! No need to add a handler because of Handles MyBase.HelpRequested.")
    End Sub

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        MethodName3()
    End Sub

End Class

Module Module1

    Public Sub MsgBoxHelpRequested3(ByVal sender As Object, ByVal hlpevent As System.Windows.Forms.HelpEventArgs)
        MsgBox("Being handled in a module.")
    End Sub

End Module


As it turns out, there was another window Active than the Form calling the MessageBox. Since no version of MessageBox.Show allows you to both handle the HelpRequested event AND specify the Owner, MessageBox was looking to the ActiveForm for the recipient of the Event, rather than sending it to my Form. Making the following change finally got it working:

Private Function MethodName() As Boolean

  Me.Activate() ' <-------------------!!!!!!!!!

  AddHandler Me.HelpRequested, AddressOf Me.MsgBoxHelpRequested
  Select Case MessageBox.Show("Text", "Title", MessageButtons.YesNoCancel, _
            MessageBoxIcon.Question, MessageBoxDefaultButton.Button2, 0, True)
    Case MsgBoxResult.Yes
      ' Do stuff
    Case MsgBoxResult.No
      ' Do stuff
    Case MsgBoxResult.Cancel
      RemoveHandler Me.HelpRequested, AddressOf Me.MsgBoxHelpRequested
      Return False
  End Select
  RemoveHandler Me.HelpRequested, AddressOf Me.MsgBoxHelpRequested
End Function


Private Sub MsgBoxHelpRequested(ByVal sender As Object, _
            ByVal hlpevent As System.Windows.Forms.HelpEventArgs)
  ' Breakpoint that **finally** gets hit
  ' More code
End Sub

There are still a number of things that I will be fixing with this code relating to other things, but it sure is nice to finally have this figured out.

Thank you to everybody that helped.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜