如何使控件正确绘制/刷新 [英] How to make a control to be painted/refreshed properly
问题描述
我有一个从支票簿派生的控件,我称之为"SettingBooleanButton",但是当任何窗口或对话框在控件上拖动时,该控件都会保持拖动的迹象
I have a control derived from checkbook which I called "SettingBooleanButton", but when any window or dialog is dragged over the control the control keeps signs of the drag
下一张图片显示了将应用程序窗口拖动到控件上方的效果
The next image shows the effect of dragging an application window over control
这是我用于OnPaint()的代码块
This is the code block that I have for OnPaint()
Public Class SettingBooleanButton
Inherits CheckBox
Private _settingSection As String
Private _settingName As String
Private _associatedSetting As Setting
Public Event StateChange(ByVal affectedSetting As Setting)
Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
Appearance = Appearance.Button
FlatStyle = FlatStyle.Flat
TextAlign = ContentAlignment.MiddleCenter
AutoSize = False
End Sub
Public Property SettingSection As String
Get
Return _settingSection
End Get
Set(value As String)
_settingSection = value
End Set
End Property
Public Property SettingName As String
Get
Return _settingName
End Get
Set(value As String)
_settingName = value
End Set
End Property
''' <summary>
''' Sets a boolean value to indicate the initial checked state of the control.
''' </summary>
''' <value>
''' <c>true</c> to set it as [checked state]; otherwise, <c>false</c>.
''' </value>
Public Property CheckedState As Boolean
Get
Return Checked
End Get
Set(value As Boolean)
_associatedSetting = New Setting(_settingSection, _settingName, String.Empty)
RemoveHandler CheckedChanged, AddressOf StateChanged
Checked = value
SetText()
AddHandler CheckedChanged, AddressOf StateChanged
End Set
End Property
Private Sub StateChanged(sender As Object, e As EventArgs)
If IsNothing(_associatedSetting) Then
Return
End If
_associatedSetting.Value = Checked.ToString()
SetText()
RaiseEvent StateChange(_associatedSetting)
End Sub
Public Sub SetText()
If Checked Then
Font = New Font(Font.FontFamily, Font.Size, FontStyle.Bold)
ForeColor = Color.WhiteSmoke
Text = Resource.SettingBooleanButton_TrueState
Else
Font = New Font(Font.FontFamily, Font.Size, FontStyle.Regular)
ForeColor = SystemColors.ControlText
Text = Resource.SettingBooleanButton_FalseState
End If
End Sub
Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
MyBase.OnPaint(e)
If Checked Then
ControlPaint.DrawBorder(e.Graphics, e.ClipRectangle, Color.Black, ButtonBorderStyle.Solid)
End If
End Sub
End Class
推荐答案
ControlPaint.DrawBorder(e.Graphics, e.ClipRectangle, ...)
像这样使用e.ClipRectangle是Paint事件处理程序中的传统错误.它是不是与您要绘制的边框匹配的矩形.只是需要绘画的控件的一部分.通常是整个控件,但并非总是如此.例如,当您在控件上拖动窗口时,仅需要重绘显示的部分.因此,现在您在错误的位置上绘制了边框,从而产生了黑线.
Using e.ClipRectangle like this is a traditional bug in a Paint event handler. It is not a rectangle that matches the border you want to draw. It is only the part of the control that needs to be painted. Which is usually the entire control, but not always. Such as in your case when you drag a window across your control, only the part that is revealed needs to be repainted. So now you are painting the border in the wrong position, producing those black lines.
仅当绘画代码昂贵时才使用ClipRectangle,而您想趁此机会在不需要它时跳过该昂贵代码.这非常罕见,在Windows中裁剪已经非常有效.
You only ever use the ClipRectangle if your painting code is expensive and you want to take the opportunity to skip that expensive code when it isn't needed anyway. Which is pretty rare, clipping in Windows is already pretty efficient.
您需要传递边框的实际矩形.修复:
You'll need to pass the actual rectangle of your border. Fix:
ControlPaint.DrawBorder(e.Graphics, Me.ClientRectangle, _
Color.Black, ButtonBorderStyle.Solid)
这篇关于如何使控件正确绘制/刷新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!