Reputation: 1001
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
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
Upvotes: 1
Views: 1887
Reputation: 41
Sometimes the simplest solutions (or causes) are overlooked.
I have a panel with 15 buttons on it and each has an image. Depending on rows selected from a data grid they all might be enabled or disabled.
It all worked fine except toggling between enabled and disabled was taking 2+ seconds and caused lag when multi-selecting from the data grid.
Tried a few things, then I thought maybe it was something to do with the images.
The images were all in an imagelist and size was set to 24,24 which was a compromise between 32,32 and 16,16. I changed the size in the imagelist to 32,32 as that is the native size of all the images... and shazam!!! All the buttons are basically rendered instantly now. No idea ATM whether being small PNG images makes a difference... but I'm going to convert all the images I have to ICO format.
Also... as all my buttons are on a panel I enable/disable the panel which in turn enables and disables all the children on it.
Upvotes: 0
Reputation: 941227
ControlPaint.DrawBorder(e.Graphics, e.ClipRectangle, ...)
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.
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)
Upvotes: 8