SDL Jetzt erst recht!
This commit is contained in:
213
SDL/cSplitButton.vb
Normal file
213
SDL/cSplitButton.vb
Normal file
@@ -0,0 +1,213 @@
|
||||
Imports System.Windows.Forms.VisualStyles
|
||||
|
||||
Public Class SplitButton
|
||||
Inherits Button
|
||||
|
||||
Private _state As PushButtonState
|
||||
Private Const PushButtonWidth As Integer = 14
|
||||
Private Shared BorderSize As Integer = SystemInformation.Border3DSize.Width * 2
|
||||
Private skipNextOpen As Boolean = False
|
||||
Private dropDownRectangle As New Rectangle
|
||||
Private _showSplit As Boolean = True
|
||||
|
||||
Public Sub New()
|
||||
Me.AutoSize = True
|
||||
End Sub
|
||||
Public Property ShowSplit() As Boolean
|
||||
Get
|
||||
Return Me._showSplit
|
||||
End Get
|
||||
Set(ByVal value As Boolean)
|
||||
If value <> Me._showSplit Then
|
||||
Me._showSplit = value
|
||||
Me.Invalidate()
|
||||
If Me.Parent IsNot Nothing Then
|
||||
Me.Parent.PerformLayout()
|
||||
End If
|
||||
End If
|
||||
End Set
|
||||
End Property
|
||||
Private Property State() As PushButtonState
|
||||
Get
|
||||
Return Me._state
|
||||
End Get
|
||||
Set(ByVal value As PushButtonState)
|
||||
If value <> Me._state Then
|
||||
Me._state = value
|
||||
Me.Invalidate()
|
||||
End If
|
||||
End Set
|
||||
End Property
|
||||
Public Overrides Function GetPreferredSize(ByVal proposedSize As System.Drawing.Size) As System.Drawing.Size
|
||||
GetPreferredSize = MyBase.GetPreferredSize(proposedSize)
|
||||
If Me._showSplit AndAlso Not String.IsNullOrEmpty(Me.Text) AndAlso TextRenderer.MeasureText(Me.Text, Me.Font).Width + PushButtonWidth > GetPreferredSize.Width Then
|
||||
GetPreferredSize += New Size(PushButtonWidth + BorderSize * 2, 0)
|
||||
End If
|
||||
End Function
|
||||
Protected Overrides Function IsInputKey(ByVal keyData As System.Windows.Forms.Keys) As Boolean
|
||||
If (keyData.Equals(Keys.Down) AndAlso Me._showSplit) Then Return True
|
||||
Return MyBase.IsInputKey(keyData)
|
||||
End Function
|
||||
Protected Overrides Sub OnGotFocus(ByVal e As System.EventArgs)
|
||||
If Not Me._showSplit Then
|
||||
MyBase.OnGotFocus(e)
|
||||
ElseIf Not State = PushButtonState.Pressed AndAlso Not State = PushButtonState.Disabled Then
|
||||
State = PushButtonState.Default
|
||||
End If
|
||||
End Sub
|
||||
Protected Overrides Sub OnLostFocus(ByVal e As System.EventArgs)
|
||||
If Not Me._showSplit Then
|
||||
MyBase.OnLostFocus(e)
|
||||
ElseIf State <> PushButtonState.Pressed AndAlso State <> PushButtonState.Disabled Then
|
||||
State = PushButtonState.Normal
|
||||
End If
|
||||
End Sub
|
||||
Protected Overrides Sub OnKeyDown(ByVal kevent As System.Windows.Forms.KeyEventArgs)
|
||||
If Me._showSplit Then
|
||||
If kevent.KeyCode = Keys.Down Then
|
||||
ShowContextMenuStrip()
|
||||
ElseIf kevent.KeyCode = Keys.Space AndAlso kevent.Modifiers = Keys.None Then
|
||||
State = PushButtonState.Pressed
|
||||
End If
|
||||
End If
|
||||
MyBase.OnKeyDown(kevent)
|
||||
End Sub
|
||||
Protected Overrides Sub OnKeyUp(ByVal kevent As System.Windows.Forms.KeyEventArgs)
|
||||
If kevent.KeyCode = Keys.Space Then
|
||||
If Control.MouseButtons = MouseButtons.None Then
|
||||
State = PushButtonState.Normal
|
||||
End If
|
||||
End If
|
||||
MyBase.OnKeyUp(kevent)
|
||||
End Sub
|
||||
Protected Overrides Sub OnMouseDown(ByVal e As System.Windows.Forms.MouseEventArgs)
|
||||
If Not Me._showSplit Then
|
||||
MyBase.OnMouseDown(e)
|
||||
ElseIf dropDownRectangle.Contains(e.Location) Then
|
||||
ShowContextMenuStrip()
|
||||
Else
|
||||
State = PushButtonState.Pressed
|
||||
End If
|
||||
End Sub
|
||||
Protected Overrides Sub OnMouseUp(ByVal e As System.Windows.Forms.MouseEventArgs)
|
||||
If Not Me._showSplit Then
|
||||
MyBase.OnMouseUp(e)
|
||||
ElseIf ContextMenuStrip Is Nothing OrElse Not ContextMenuStrip.Visible Then
|
||||
SetButtonDrawState()
|
||||
If Bounds.Contains(Parent.PointToClient(Cursor.Position)) AndAlso Not dropDownRectangle.Contains(e.Location) Then
|
||||
OnClick(New EventArgs())
|
||||
End If
|
||||
End If
|
||||
End Sub
|
||||
Protected Overrides Sub OnMouseEnter(ByVal e As System.EventArgs)
|
||||
If Not ShowSplit Then
|
||||
MyBase.OnMouseEnter(e)
|
||||
ElseIf State <> PushButtonState.Pressed AndAlso State <> PushButtonState.Disabled Then
|
||||
State = PushButtonState.Hot
|
||||
End If
|
||||
End Sub
|
||||
Protected Overrides Sub OnMouseLeave(ByVal e As System.EventArgs)
|
||||
If Not ShowSplit Then
|
||||
MyBase.OnMouseLeave(e)
|
||||
ElseIf State <> PushButtonState.Pressed AndAlso State <> PushButtonState.Disabled Then
|
||||
If Focused Then
|
||||
State = PushButtonState.Default
|
||||
Else
|
||||
State = PushButtonState.Normal
|
||||
End If
|
||||
End If
|
||||
End Sub
|
||||
Protected Overrides Sub OnPaint(ByVal pevent As System.Windows.Forms.PaintEventArgs)
|
||||
MyBase.OnPaint(pevent)
|
||||
If Me._showSplit Then
|
||||
Dim g As Graphics = pevent.Graphics
|
||||
Dim bounds As Rectangle = Me.ClientRectangle
|
||||
|
||||
'draw the button background as according to the current state.
|
||||
If State <> PushButtonState.Pressed AndAlso IsDefault AndAlso Not Application.RenderWithVisualStyles Then
|
||||
Dim backgroundBounds As Rectangle = bounds
|
||||
backgroundBounds.Inflate(-1, -1)
|
||||
ButtonRenderer.DrawButton(g, backgroundBounds, State)
|
||||
'button renderer doesnt draw the black frame when themes are off =(
|
||||
g.DrawRectangle(SystemPens.WindowFrame, 0, 0, bounds.Width - 1, bounds.Height - 1)
|
||||
Else
|
||||
ButtonRenderer.DrawButton(g, bounds, State)
|
||||
End If
|
||||
|
||||
'calculate the current dropdown rectangle.
|
||||
dropDownRectangle = New Rectangle(bounds.Right - PushButtonWidth - 1, BorderSize, PushButtonWidth, bounds.Height - BorderSize * 2)
|
||||
Dim internalBorder As Integer = BorderSize
|
||||
Dim focusRect As New Rectangle(internalBorder, internalBorder, bounds.Width - dropDownRectangle.Width - internalBorder, bounds.Height - (internalBorder * 2))
|
||||
Dim drawSplitLine As Boolean = State = PushButtonState.Hot OrElse State = PushButtonState.Pressed OrElse Not Application.RenderWithVisualStyles
|
||||
If RightToLeft = Windows.Forms.RightToLeft.Yes Then
|
||||
dropDownRectangle.X = bounds.Left + 1
|
||||
focusRect.X = dropDownRectangle.Right
|
||||
If drawSplitLine Then
|
||||
'draw two lines at the edge of the dropdown button
|
||||
g.DrawLine(SystemPens.ButtonShadow, bounds.Left + PushButtonWidth, BorderSize, bounds.Left + PushButtonWidth, bounds.Bottom - BorderSize)
|
||||
g.DrawLine(SystemPens.ButtonFace, bounds.Left + PushButtonWidth + 1, BorderSize, bounds.Left + PushButtonWidth + 1, bounds.Bottom - BorderSize)
|
||||
End If
|
||||
ElseIf drawSplitLine Then
|
||||
'draw two lines at the edge of the dropdown button
|
||||
g.DrawLine(SystemPens.ButtonShadow, bounds.Right - PushButtonWidth, BorderSize, bounds.Right - PushButtonWidth, bounds.Bottom - BorderSize)
|
||||
g.DrawLine(SystemPens.ButtonFace, bounds.Right - PushButtonWidth - 1, BorderSize, bounds.Right - PushButtonWidth - 1, bounds.Bottom - BorderSize)
|
||||
End If
|
||||
|
||||
'Draw an arrow in the correct location
|
||||
Dim middle As New Point(dropDownRectangle.Left + dropDownRectangle.Width / 2, dropDownRectangle.Top + dropDownRectangle.Height / 2)
|
||||
'if the width is odd - favor pushing it over one pixel right.
|
||||
middle.X += dropDownRectangle.Width Mod 2
|
||||
Dim arrow As Point() = New Point() {New Point(middle.X - 2, middle.Y - 1), New Point(middle.X + 3, middle.Y - 1), New Point(middle.X, middle.Y + 2)}
|
||||
g.FillPolygon(SystemBrushes.ControlText, arrow)
|
||||
|
||||
'Figure out how to draw the text
|
||||
Dim formatFlags As TextFormatFlags = TextFormatFlags.HorizontalCenter Or TextFormatFlags.VerticalCenter
|
||||
'If we dont' use mnemonic, set formatFlag to NoPrefix as this will show ampersand.
|
||||
If Not UseMnemonic Then
|
||||
formatFlags = formatFlags Or TextFormatFlags.NoPrefix
|
||||
ElseIf Not ShowKeyboardCues Then
|
||||
formatFlags = formatFlags Or TextFormatFlags.HidePrefix
|
||||
End If
|
||||
If Not String.IsNullOrEmpty(Me.Text) Then
|
||||
TextRenderer.DrawText(g, Text, Font, focusRect, SystemColors.ControlText, formatFlags)
|
||||
End If
|
||||
|
||||
'draw the focus rectangle.
|
||||
If State <> PushButtonState.Pressed AndAlso Focused Then
|
||||
ControlPaint.DrawFocusRectangle(g, focusRect)
|
||||
End If
|
||||
End If
|
||||
End Sub
|
||||
Private Sub ShowContextMenuStrip()
|
||||
If skipNextOpen Then
|
||||
'we were called because we're closing the context menu strip
|
||||
'when clicking the dropdown button.
|
||||
skipNextOpen = False
|
||||
Else
|
||||
State = PushButtonState.Pressed
|
||||
If ContextMenuStrip IsNot Nothing Then
|
||||
AddHandler ContextMenuStrip.Closing, AddressOf ContextMenuStrip_Closing
|
||||
ContextMenuStrip.Show(Me, New Point(0, Height), ToolStripDropDownDirection.BelowRight)
|
||||
End If
|
||||
End If
|
||||
End Sub
|
||||
Private Sub ContextMenuStrip_Closing(ByVal sender As Object, ByVal e As ToolStripDropDownClosingEventArgs)
|
||||
Dim cms As ContextMenuStrip = CType(sender, ContextMenuStrip)
|
||||
If cms IsNot Nothing Then
|
||||
RemoveHandler cms.Closing, AddressOf ContextMenuStrip_Closing
|
||||
End If
|
||||
SetButtonDrawState()
|
||||
If e.CloseReason = ToolStripDropDownCloseReason.AppClicked Then
|
||||
skipNextOpen = dropDownRectangle.Contains(Me.PointToClient(Cursor.Position))
|
||||
End If
|
||||
End Sub
|
||||
Private Sub SetButtonDrawState()
|
||||
If Bounds.Contains(Parent.PointToClient(Cursor.Position)) Then
|
||||
State = PushButtonState.Hot
|
||||
ElseIf Focused Then
|
||||
State = PushButtonState.Default
|
||||
Else
|
||||
State = PushButtonState.Normal
|
||||
End If
|
||||
End Sub
|
||||
End Class
|
||||
Reference in New Issue
Block a user