Handling VScrollbar Paint event

2019-09-17 16:56发布

问题:

I've been trying to handle the Paint event for a control on a form. However the event never gets handled, and I'm not sure what I'm doing wrong. I've created a very simple WinForms project to demonstrate this (I've included the generated designer code to show that there's nothing else there):

Form1.vb

Public Class Form1
    Private Sub Form1_Load( sender As Object,  e As EventArgs) Handles MyBase.Load
        AddHandler VScrollBar1.Paint, AddressOf VScrollBar1_Paint
    End Sub

    Private Sub VScrollBar1_Paint (ByVal sender As Object, ByVal e As PaintEventArgs)
        Dim str As String = "test"
        System.Windows.Forms.MessageBox.Show(str)
    End Sub                              
End Class

Form1.Designer.vb

<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class Form1
    Inherits System.Windows.Forms.Form

    '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

    '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.VScrollBar1 = New System.Windows.Forms.VScrollBar()
        Me.SuspendLayout
        '
        'VScrollBar1
        '
        Me.VScrollBar1.Location = New System.Drawing.Point(26, 56)
        Me.VScrollBar1.Name = "VScrollBar1"
        Me.VScrollBar1.Size = New System.Drawing.Size(17, 80)
        Me.VScrollBar1.TabIndex = 0
        '
        'Form1
        '
        Me.AutoScaleDimensions = New System.Drawing.SizeF(6!, 13!)
        Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
        Me.ClientSize = New System.Drawing.Size(284, 261)
        Me.Controls.Add(Me.VScrollBar1)
        Me.Name = "Form1"
        Me.Text = "Form1"
        Me.ResumeLayout(false)

    End Sub
        Friend WithEvents VScrollBar1 As System.Windows.Forms.VScrollBar

End Class

The event is never handled, but the control is drawn correctly. What am I missing?

回答1:

Well, after spending a bit more time on this, I've discovered that all you need to do is call the SetStyle() method with the flag and value parameters set to ControlStyles.userPaint and True, respectively.

This method isn't public though, so reflection is needed in order to invoke it:

Dim methodInfo As System.Reflection.MethodInfo = VScrollBar1.GetType().GetMethod("SetStyle", Reflection.BindingFlags.Instance Or Reflection.BindingFlags.NonPublic)
methodInfo.Invoke(VScrollBar1, {ControlStyles.UserPaint, True})

I put the above code into the Form1_Load method above, just above the AddHandler line and it appears to work (I can handle the event).