开发者

DateTimePicker and UserPaint...Text and button missing

开发者 https://www.devze.com 2022-12-08 19:45 出处:网络
I\'ve got a DateTimePicker which I \'dynamically\' assign the Paint-Event, unfortunately as long as this Event is assigned neither the text nor the DropDown-Button are rendered (but are working).

I've got a DateTimePicker which I 'dynamically' assign the Paint-Event, unfortunately as long as this Event is assigned neither the text nor the DropDown-Button are rendered (but are working).

I've written a component which takes another control and draws something on it

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

At disposing of the component I'm removing the handler and resetting the styles. But as long as the Handler is assigned the DateTimePicker renders like a normal Textbox without content, but the button is working and I can also enter values. If I've overwritten the OnPaint() method I'd simply call MyBase.OnPaint() or similar...but this is an eventhandler...I'm totally cluel开发者_运维知识库ess here right now.


The DateTimePicker have no OnPaint method to draw itself. It's in fact a wrapper around the windows control SysDateTimePick32, so when you set UserPaint = true, the control (real one) no longer draws itself and there will be only your drawings.

You can inherit from DateTimePicker, override WndProc, respond to WM_PAINT message by executing Paint event subscribers. Here an example:

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

then use this new control instead of the regular DateTimePicker & subscribe to it's Paint2 event to draw what you need:

(you don't need to set UserPaint = True, you're capturing WM_PAINT anyway)

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

hope this helps,


I figured something out. As it seems the UserPaint happens within the underlying control and not in the DateTimePicker itself, 'causing it to render faulty. This will happen as long as the Style UserPaint is set.

One workaround is to let it render correct within the Paint-Event...which is not that easy I fear, but possible:

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

We remove the Handler and the Style for the Paint-Event, refresh the control ('causing it to render correctly), then drawing our things on top of the newly rendered control, and re-adding the Style and the Paint-Eventhandler. The downside is, that everything we draw disappears while somebody is entering some information (it's there if you use the calendar box), and might not come back until some_one_ refreshes the control. So this seems to be an ugly hack then a real workaround or even a solution[1].

Though, I've only tested this with a DateTimePicker, and have no clue if this also works with other controls (but it seems so).

[1] I mean, I know the solution, rewriting the Control within the Framework...

0

精彩评论

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

关注公众号