DateTimePicker and UserPaint...Text and button missing
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...
精彩评论