1

我有一个 DateTimePicker,我“动态地”分配 Paint-Event,不幸的是,只要分配了这个 Event,文本和 DropDown-Button 都不会被渲染(但正在工作)。

我编写了一个组件,它采用另一个控件并在其上绘制一些东西

Public Sub New(Byval parent As Control)
    Me._parent = parent
    Me._setStyle = Me._parent.GetType().GetMethod("SetStyle", Reflection.BindingFlags.Instance Or Reflection.BindingFlags.NonPublic)
    Me._setStyle.Invoke(Me._parent, New Object() {ControlStyles.UserPaint, True})
    Me._setStyle.Invoke(Me._parent, New Object() {ControlStyles.OptimizedDoubleBuffer, True})

    AddHandler Me._parent.Paint, AddressOf RemotePaintHandler
End Sub

Private Sub RemotePaintHandler(ByVal sender As Object, ByVal e As PaintEventArgs)
    'draw something here'
End Sub

在处理组件时,我将删除处理程序并重置样式。但是只要分配了处理程序,DateTimePicker 就会像没有内容的普通文本框一样呈现,但是按钮正在工作,我也可以输入值。如果我覆盖了 OnPaint() 方法,我只需调用 MyBase.OnPaint() 或类似方法......但这是一个事件处理程序......我现在完全一无所知。

4

2 回答 2

2

DateTimePicker没有OnPaint办法绘制自己。它实际上是 windows 控件的一个包装器SysDateTimePick32,因此当您设置 UserPaint = true 时,该控件(真正的)不再绘制自己,只会有您的绘图。

您可以通过执行订阅者继承DateTimePicker、覆盖WndProc、响应消息。这里有一个例子:WM_PAINTPaint event

Public Class DTP
    Inherits DateTimePicker

    ' Events '
    Public Event Paint2 As PaintEventHandler

    ' Methods '
    Protected Overrides Sub WndProc(ByRef m As Message)

        MyBase.WndProc((m))

        If ((m.Msg = &HF) AndAlso (Not Me.Paint2 Is Nothing)) Then

            Dim g As Graphics = MyBase.CreateGraphics
            Me.Paint2.Invoke(Me, New PaintEventArgs( _
                                       g, _
                                       Rectangle.Round(g.VisibleClipBounds) _
                                     ) _
                            )
        End If

    End Sub

End Class

然后使用这个新控件而不是常规的DateTimePicker& 订阅它的 Paint2 事件来绘制你需要的东西:

(你不需要设置,无论如何UserPaint = True你都在捕捉)WM_PAINT

Public Sub New(Byval parent As Control)
    Me._parent = parent
    Me._setStyle = Me._parent.GetType().GetMethod("SetStyle", _
                               Reflection.BindingFlags.Instance _
                               Or Reflection.BindingFlags.NonPublic)
    'Me._setStyle.Invoke(Me._parent, New Object(){ControlStyles.UserPaint,True})'
    Me._setStyle.Invoke(Me._parent,  _
                        New Object() {ControlStyles.OptimizedDoubleBuffer, True})

    AddHandler Me._parent.Paint2, AddressOf RemotePaintHandler
End Sub

Private Sub RemotePaintHandler(ByVal sender As Object, ByVal e As PaintEventArgs)
    'draw something here'
End Sub

希望这可以帮助,

于 2009-10-29T21:19:43.303 回答
0

我想通了。看起来 UserPaint 发生在底层控件中,而不是 DateTimePicker 本身,导致它呈现错误。只要设置了 Style UserPaint,就会发生这种情况。

一种解决方法是让它在 Paint-Event 中正确呈现......我担心这并不容易,但可能:

Private Sub RemotePaintHandler(ByVal sender As Object, ByVal e As PaintEventArgs)
    RemoveHandler Me._parent.Paint, AddressOf RemotePaintHandler
    Me._setStyle.Invoke(Me._parent, New Object() {ControlStyles.UserPaint, False})

    Me._parent.Refresh()
    ' now draw something '

    Me._setStyle.Invoke(Me._parent, New Object() {ControlStyles.UserPaint, True})
    AddHandler Me._parent.Paint, AddressOf RemotePaintHandler
End Sub

我们删除了 Paint-Event 的 Handler 和 Style,刷新了控件(使其正确渲染),然后在新渲染的控件之上绘制我们的东西,并重新添加 Style 和 Paint-Eventhandler。不利的一面是,当有人输入一些信息时,我们绘制的所有内容都会消失(如果您使用日历框,它就在那里),并且在 some_one_ 刷新控件之前可能不会回来。所以这似乎是一个丑陋的黑客然后是一个真正的解决方法,甚至是一个解决方案[1]。

虽然,我只用 DateTimePicker 对此进行了测试,并且不知道这是否也适用于其他控件(但似乎如此)。

[1] 我的意思是,我知道解决方案,重写框架内的控件...

于 2009-10-21T08:48:17.777 回答