我有一个DateTimePicker,我动态'分配了Paint-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
在处理组件时,我正在移除处理程序并重置样式。但只要分配了Handler,DateTimePicker就会像没有内容的普通文本框一样呈现,但按钮正常工作,我也可以输入值。如果我已经覆盖了OnPaint()方法,我只需要调用MyBase.OnPaint()或者类似的......但这是一个事件处理程序......我现在完全无能为力。
答案 0 :(得分:2)
DateTimePicker
没有OnPaint
方法来绘制自己。它实际上是一个围绕windows控件SysDateTimePick32
的包装器,所以当你设置UserPaint = true时,控件(真实的)不再绘制自己,只有你的绘图。
您可以继承DateTimePicker
,覆盖WndProc
,通过执行WM_PAINT
订阅者来回复Paint 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
希望这有帮助,
答案 1 :(得分: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
我们删除Handler和Paint-Event的样式,刷新控件('使其正确渲染),然后在新渲染的控件上绘制我们的东西,然后重新添加Style和Paint-事件处理程序。 缺点是,我们绘制的所有内容都会在某人输入某些信息时消失(如果您使用日历框则会在那里显示),并且在some_one_刷新控件之前可能不会返回。所以这似乎是一个丑陋的黑客,然后是一个真正的解决方法甚至解决方案[1]。
尽管如此,我只使用DateTimePicker对此进行了测试,并且不知道这是否也适用于其他控件(但似乎如此)。
[1]我的意思是,我知道解决方案,在框架内重写控件......