Hi guys; still unemployed but all the spare time gives me time to play with the AutoCAD API.
I have coded a custom control that inherits from the standard .NET combo box and attempts to replicate
the AutoCAD Select Color combo box. I intend to use this in multiple add-ons I am writing for AutoCAD.
My target is AutoCAD 2010 and I am using Visual Studio 2008 (should have waited for VS2010, I've heard)
All the code is in VB (sorry, I know most of you use c#)
Namespace CCSDotNetArx
''' <summary>
''' Custom control that mirrors the legacy AutoCAD select colour combo box
''' </summary>
Public Class ColourComboBox
Inherits ComboBox
''' <summary>
''' New colours collection that determines the list in the combo box
''' </summary>
Private Colours As New List(Of String)
Private mSelectedColour As AcadCo.Color
Public Property SelectedColour() As AcadCo.Color
Get
If Not IsNothing(mSelectedColour) Then
Return mSelectedColour
Else
Return Nothing
End If
End Get
Set(ByVal value As AcadCo.Color)
mSelectedColour = value
End Set
End Property
''' <summary>
''' Default ctor
''' </summary>
Public Sub New()
Me.DrawMode = Windows.Forms.DrawMode.OwnerDrawFixed
Me.DropDownStyle = ComboBoxStyle.DropDownList
InitialiseDefaultColours()
RefreshMe()
End Sub
Public Shadows Sub Dispose()
If Not IsNothing(Colours) Then Colours = Nothing
End Sub
''' <summary>
''' Refresh the custom combo box and reload all colours
''' </summary>
Private Sub RefreshMe()
Me.Items.Clear()
For i As Integer = 0 To Colours.Count - 1
Me.Items.Add(Colours(i))
Next
If Me.Items.Contains("Select...") Then
Me.Items.Remove("Select...")
End If
Me.Items.Add("Select...")
End Sub
''' <summary>
''' Add the default colours to the colours collection
''' </summary>
Private Sub InitialiseDefaultColours()
Colours.Add("1")
Colours.Add("2")
Colours.Add("3")
Colours.Add("4")
Colours.Add("5")
Colours.Add("6")
Colours.Add("7")
End Sub
''' <summary>
''' Add a new item to the colours collection
''' </summary>
''' <param name="item">Input for the new item</param>
Private Sub AddNewItem(ByVal item As String)
Colours.Add(item)
End Sub
''' <summary>
''' Determine when the "Select..." item is clicked and display the select colour dialog box
''' </summary>
''' <remarks></remarks>
Private Sub SelectColour(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.SelectedValueChanged
'Get the value of the combo box and continue if valid
Dim TextValue As String = Me.Text : If TextValue = "" Then Exit Sub
'Ignore all values except the custom select item at the bottom of the list
If Not TextValue = "Select..." Then
SelectedColour = AcadCo.Color.FromColorIndex(AcadCo.ColorMethod.ByAci, TextValue)
Exit Sub
End If
'Load the AutoCAD Select Colour dialog to prompt the user for a new colour
Dim clr As New AcadWd.ColorDialog : clr.IncludeByBlockByLayer = False : clr.SetDialogTabs(1)
If clr.ShowDialog <> DialogResult.OK Then
RefreshMe()
Me.Text = "1"
Else
'Check the colours list to see if the colour has already been added
If Colours.Contains(clr.Color.ColorIndex) Then
RefreshMe()
Me.Text = clr.Color.ColorIndex
Else
AddNewItem(clr.Color.ColorIndex)
RefreshMe()
Me.Text = clr.Color.ColorIndex
End If
End If
End Sub
''' <summary>
''' Perform all the painting of the items in the combo box replicating the AutoCAD legacy colour combo box
''' </summary>
''' <remarks></remarks>
Private Sub CustomDraw(ByVal sender As Object, ByVal e As DrawItemEventArgs) Handles Me.DrawItem
If e.Index = -1 Then Exit Sub
'Get the text value of the combo box item
Dim TextString As String = Me.Items(e.Index)
'Create a rectangle for custom drawing the colour box
Dim ColourBoxRect As New Rectangle(e.Bounds.X + 1, e.Bounds.Y + 1, 18, e.Bounds.Height - 3)
'Create a rectangle for custom drawing the text string
Dim TextBoxRect As New Rectangle(e.Bounds.X + ColourBoxRect.Width + 4, e.Bounds.Y + 1, e.Bounds.Width - 1, e.Bounds.Height - 1)
'Create a new brush for the background of the item
Dim BackColourBrush As New SolidBrush(e.BackColor)
'Create a new brush for the colour box
Dim ColourBoxBrush As SolidBrush = Nothing
'Create an AutoCAD colour for looking up the RGB values of the intended colour
Dim AutoCADColour As AcadCo.Color = Nothing
'Create a colour for the colour box
Dim ColourBoxColour As Drawing.Color = Nothing
'We do not need a colour box if the text is Select... as this executes a call to select a
'new colour
If Not TextString = "Select..." Then
'Add a Try/Catch to prevent the forms designer from crashing when attempting to load the AutoCAD libraries
Try
'Get the AutoCAD colour object from the value of the item
AutoCADColour = AcadCo.Color.FromColorIndex(AcadCo.ColorMethod.ByAci, TextString)
'Get the RGB values of the AutoCAD colour to create a system colour for the colour box
ColourBoxColour = Drawing.Color.FromArgb(AutoCADColour.ColorValue.R, AutoCADColour.ColorValue.G, AutoCADColour.ColorValue.B)
'Set the colour box brush to the required colour
ColourBoxBrush = New SolidBrush(ColourBoxColour)
Catch ex As Exception
Exit Sub
End Try
'Draw the background of the cell
e.Graphics.FillRectangle(BackColourBrush, e.Bounds)
'Fill the Colour Box with the new colour
e.Graphics.FillRectangle(ColourBoxBrush, ColourBoxRect)
'Draw the rectangle for the colour box
e.Graphics.DrawRectangle(Pens.Black, ColourBoxRect)
'Custom draw the text
e.Graphics.DrawString(TextString, Me.Font, Brushes.Black, TextBoxRect)
Else
'Draw the background of the cell
e.Graphics.FillRectangle(BackColourBrush, e.Bounds)
'Custom draw the text
e.Graphics.DrawString(TextString, Me.Font, Brushes.Black, TextBoxRect)
End If
If Not IsNothing(BackColourBrush) Then BackColourBrush.Dispose()
If Not IsNothing(ColourBoxBrush) Then ColourBoxBrush.Dispose()
End Sub
End Class
End Namespace
The above code seems to work quite well, however, is there any suggestions to 'clean-up' the code. I have 'a hunch'
that something isn't quite right?
Also, any pointers how it could be modified to support True Color and Color Books - with the ability to persist the
'SelectedValue'?