ImageComboBox

--Class:NativeMethods.vb--

Imports System.Collections.Generic
Imports System.Text
Imports System.Runtime.InteropServices
Imports System.Drawing

Namespace Demo
    Friend Class NativeMethods
#Region "WindowsMessage"

        Public Enum WindowsMessage
            WM_SETFOCUS = &H7
            WM_KILLFOCUS = &H8
            WM_PAINT = &HF

            WM_SETFONT = &H30

            ' keyboard
            WM_KEYDOWN = &H100
            WM_KEYUP = &H101
            WM_CHAR = &H102

            ' mouse
            WM_MOUSEMOVE = &H200
            WM_LBUTTONDOWN = &H201
            WM_LBUTTONUP = &H202
            WM_LBUTTONDBLCLK = &H203
            WM_RBUTTONDOWN = &H204
            WM_RBUTTONUP = &H205
            WM_RBUTTONDBLCLK = &H206
            WM_MBUTTONDOWN = &H207
            WM_MBUTTONUP = &H208
            WM_MBUTTONDBLCLK = &H209
        End Enum

#End Region

#Region "ImageLisFlags"

        <Flags()> _
        Public Enum ImageListDrawFlags As Integer
            ILD_NORMAL = &H0
            ILD_TRANSPARENT = &H1
            ILD_BLEND25 = &H2
            ILD_FOCUS = &H2
            ILD_BLEND50 = &H4
            ILD_SELECTED = &H4
            ILD_BLEND = &H4
            ILD_MASK = &H10
            ILD_IMAGE = &H20
            ILD_ROP = &H40
            ILD_OVERLAYMASK = &HF00
            ILD_PRESERVEALPHA = &H1000
            ILD_SCALE = &H2000
            ILD_DPISCALE = &H4000
            ILD_ASYNC = &H8000
        End Enum

#End Region

#Region "RECT"

        <StructLayout(LayoutKind.Sequential)> _
        Public Structure RECT
            Public Left As Integer
            Public Top As Integer
            Public Right As Integer
            Public Bottom As Integer

            Public Sub New(ByVal left__1 As Integer, ByVal top__2 As Integer, ByVal right__3 As Integer, ByVal bottom__4 As Integer)
                Left = left__1
                Top = top__2
                Right = right__3
                Bottom = bottom__4
            End Sub

            Public Sub New(ByVal rect As Rectangle)
                Left = rect.Left
                Top = rect.Top
                Right = rect.Right
                Bottom = rect.Bottom
            End Sub

            Public ReadOnly Property Rect() As Rectangle
                Get
                    Return New Rectangle(Left, Top, Right - Left, Bottom - Top)
                End Get
            End Property

            Public ReadOnly Property Size() As Size
                Get
                    Return New Size(Right - Left, Bottom - Top)
                End Get
            End Property

            Public Shared Function FromXYWH(ByVal x As Integer, ByVal y As Integer, ByVal width As Integer, ByVal height As Integer) As RECT
                Return New RECT(x, y, x + width, y + height)
            End Function

            Public Shared Function FromRectangle(ByVal rect As Rectangle) As RECT
                Return New RECT(rect.Left, rect.Top, rect.Right, rect.Bottom)
            End Function
        End Structure

#End Region

#Region "API Methods"

        <DllImport("user32.dll")> _
        Public Shared Function SendMessage(ByVal hwnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
        End Function

        <DllImport("user32.dll", CharSet:=CharSet.Auto, ExactSpelling:=True)> _
        Public Shared Function GetClientRect(ByVal hWnd As IntPtr, <[In](), Out()> ByRef rect As NativeMethods.RECT) As Boolean
        End Function

        <DllImport("user32.dll")> _
        Public Shared Function GetDC(ByVal ptr As IntPtr) As IntPtr
        End Function

        <DllImport("user32.dll")> _
        Public Shared Function ReleaseDC(ByVal hwnd As IntPtr, ByVal hDC As IntPtr) As Integer
        End Function

        <DllImport("comctl32.dll", SetLastError:=True)> _
        Public Shared Function ImageList_GetIcon(ByVal himl As IntPtr, ByVal i As Integer, ByVal flags As Integer) As IntPtr
        End Function

        <DllImport("user32.dll", SetLastError:=True)> _
        Public Shared Function DestroyIcon(ByVal hIcon As IntPtr) As Boolean
        End Function

#End Region
    End Class
End Namespace

 

--Class:ImageComboBoxItem.vb--

Imports System.ComponentModel
Imports System.Drawing
Imports System.Windows.Forms
Imports System.Runtime.Serialization
Imports System.Security.Permissions
Imports System.Drawing.Design

Namespace Demo
    <Serializable()> _
    <DefaultProperty("Text")> _
    <TypeConverter(GetType(ExpandableObjectConverter))> _
    Public Class ImageComboBoxItem
        Implements IDisposable
        Implements ISerializable
#Region "Fields"
        Public Const IMAGEINDEXEDITOR As String = "System.Windows.Forms.Design.ImageIndexEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
        Private _imageComboBox As ImageComboBox
        Private _value As String = String.Empty
        Private _imageIndexer As ImageComboBoxItemImageIndexer
        Private _tag As Object
        Private _level As Integer

#End Region

#Region "Constructors"

        Public Sub New()
        End Sub

        'public ImageComboBoxItem(string text)
        '    : this(text, -1, 0)
        '{
        '}

        'public ImageComboBoxItem(
        '    string text, int imageIndex)
        '    : this(text, imageIndex, 0)
        '{
        '}

        'public ImageComboBoxItem(
        '    string text, string imageKey)
        '    : this(text, imageKey, 0)
        '{
        '}

        'public ImageComboBoxItem(
        '    string text, int imageIndex, int level)
        '    : this()
        '{
        '    _text = text;
        '    ImageIndexer.Index = imageIndex;
        '    _level = level;
        '}

        'public ImageComboBoxItem(
        '   string text, string imageKey, int level)
        '    : this()
        '{
        '    _text = text;
        '    ImageIndexer.Key = imageKey;
        '    _level = level;
        '}

        Protected Sub New(ByVal info As SerializationInfo, ByVal context As StreamingContext)
            Me.New()
            Deserialize(info, context)
        End Sub

#End Region

#Region "Properties"

        <Localizable(True)> _
        Public Property Value() As String
            Get
                Return _value
            End Get
            Set(ByVal value As String)
                _value = value
            End Set
        End Property

        <Bindable(True)> _
        <Localizable(False)> _
        <DefaultValue("")> _
        <TypeConverter(GetType(StringConverter))> _
        <DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)> _
        Public Property Tag() As Object
            Get
                Return _tag
            End Get
            Set(ByVal value As Object)
                _tag = value
            End Set
        End Property

        <DefaultValue(0)> _
        <Localizable(True)> _
        <RefreshProperties(RefreshProperties.Repaint)> _
        <DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)> _
        Public Property Level() As Integer
            Get
                Return _level
            End Get
            Set(ByVal value As Integer)
                If _level < 0 Then
                    Throw New ArgumentOutOfRangeException("level")
                End If
                _level = value
            End Set
        End Property

        <DefaultValue(-1)> _
        <Localizable(True)> _
        <RelatedImageList("ImageComboBox.ImageList")> _
        <Editor(IMAGEINDEXEDITOR, GetType(UITypeEditor))> _
        <RefreshProperties(RefreshProperties.Repaint)> _
        <DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)> _
        <TypeConverter(GetType(NoneExcludedImageIndexConverter))> _
        Public Property ImageIndex() As Integer
            Get
                If ((ImageIndexer.Index <> -1) AndAlso (ImageList IsNot Nothing)) AndAlso (ImageIndexer.Index >= ImageList.Images.Count) Then
                    Return ImageList.Images.Count - 1
                End If
                Return ImageIndexer.Index
            End Get
            Set(ByVal value As Integer)
                If value < -1 Then
                    Throw New ArgumentOutOfRangeException("ImageIndex")
                End If
                ImageIndexer.Index = value
            End Set
        End Property

        <DefaultValue("")> _
        <Localizable(True)> _
        <RelatedImageList("ImageComboBox.ImageList")> _
        <RefreshProperties(RefreshProperties.Repaint)> _
        <Editor(IMAGEINDEXEDITOR, GetType(UITypeEditor))> _
        <DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)> _
        <TypeConverter(GetType(ImageKeyConverter))> _
        Public Property ImageKey() As String
            Get
                Return ImageIndexer.Key
            End Get
            Set(ByVal value As String)
                ImageIndexer.Key = value
            End Set
        End Property

        <Browsable(False)> _
        Public ReadOnly Property ImageComboBox() As ImageComboBox
            Get
                Return _imageComboBox
            End Get
        End Property

        Friend ReadOnly Property Image() As Image
            Get
                Dim actualIndex As Integer = ImageIndexer.ActualIndex
                If ImageList IsNot Nothing AndAlso ImageList.Images.Count > 0 AndAlso actualIndex <> -1 Then
                    Return ImageList.Images(actualIndex)
                End If
                Return Nothing
            End Get
        End Property

        <Browsable(False)> _
        Friend ReadOnly Property ImageList() As ImageList
            Get
                If ImageComboBox IsNot Nothing Then
                    Return ImageComboBox.ImageList
                End If
                Return Nothing
            End Get
        End Property

        Friend ReadOnly Property ImageIndexer() As ImageComboBoxItemImageIndexer
            Get
                If _imageIndexer Is Nothing Then
                    _imageIndexer = New ImageComboBoxItemImageIndexer(Me)
                End If
                Return _imageIndexer
            End Get
        End Property

#End Region

#Region "Methods"

        'public override string ToString()
        '{
        '    return _text;
        '}

        Friend Sub Host(ByVal parent As ImageComboBox)
            _imageComboBox = parent
        End Sub

        <SecurityPermission(SecurityAction.Demand, Flags:=SecurityPermissionFlag.SerializationFormatter), SecurityPermission(SecurityAction.InheritanceDemand, Flags:=SecurityPermissionFlag.SerializationFormatter)> _
        Protected Overridable Sub Serialize(ByVal info As SerializationInfo, ByVal context As StreamingContext)
            info.AddValue("Value", Value)
            info.AddValue("Level", Level)
            info.AddValue("ImageIndex", ImageIndexer.Index)
            If Not String.IsNullOrEmpty(ImageIndexer.Key) Then
                info.AddValue("ImageKey", ImageIndexer.Key)
            End If
        End Sub

        Protected Overridable Sub Deserialize(ByVal info As SerializationInfo, ByVal context As StreamingContext)
            Dim imageKey__1 As String = Nothing
            Dim imageIndex__2 As Integer = -1
            Dim enumerator As SerializationInfoEnumerator = info.GetEnumerator()
            While enumerator.MoveNext()
                Dim current As SerializationEntry = enumerator.Current
                If current.Name = "Value" Then
                    Value = info.GetString(current.Name)
                ElseIf current.Name = "Level" Then
                    Level = info.GetInt32(current.Name)
                Else
                    If current.Name = "ImageIndex" Then
                        imageIndex__2 = info.GetInt32(current.Name)
                        Continue While
                    End If
                    If current.Name = "ImageKey" Then
                        imageKey__1 = info.GetString(current.Name)
                        Continue While
                    End If
                End If
            End While
            If imageKey__1 IsNot Nothing Then
                ImageKey = imageKey__1
            ElseIf imageIndex__2 <> -1 Then
                ImageIndex = imageIndex__2
            End If
        End Sub

#End Region

#Region "ISerializable 成员"

        <SecurityPermission(SecurityAction.LinkDemand, Flags:=SecurityPermissionFlag.SerializationFormatter)> _
        Private Sub ISerializable_GetObjectData(ByVal info As SerializationInfo, ByVal context As StreamingContext) Implements ISerializable.GetObjectData
            Serialize(info, context)
        End Sub

#End Region

#Region "IDisposable 成员"

        Public Sub Dispose() Implements IDisposable.Dispose
            _imageComboBox = Nothing
            _imageIndexer = Nothing
            _tag = Nothing
        End Sub

#End Region

#Region "ImageComboBoxItemImageIndexer Class"

        Friend Class ImageComboBoxItemImageIndexer
            Inherits ImageIndexer
            Private _owner As ImageComboBoxItem

            Public Sub New(ByVal owner As ImageComboBoxItem)
                _owner = owner
            End Sub

            Public Overrides Property ImageList() As ImageList
                Get
                    If _owner IsNot Nothing Then
                        Return _owner.ImageList
                    End If
                    Return Nothing
                End Get
                Set(ByVal value As ImageList)
                End Set
            End Property
        End Class

#End Region
    End Class

    Friend Class ImageIndexer
        Private _imageList As ImageList
        Private _index As Integer = -1
        Private _key As String = String.Empty
        Private _useIntegerIndex As Boolean = True

        Public Overridable ReadOnly Property ActualIndex() As Integer
            Get
                If _useIntegerIndex Then
                    Return Index
                End If
                If ImageList IsNot Nothing Then
                    Return ImageList.Images.IndexOfKey(Key)
                End If
                Return -1
            End Get
        End Property

        Public Overridable Property ImageList() As ImageList
            Get
                Return _imageList
            End Get
            Set(ByVal value As ImageList)
                _imageList = value
            End Set
        End Property

        Public Overridable Property Index() As Integer
            Get
                Return _index
            End Get
            Set(ByVal value As Integer)
                _key = String.Empty
                _index = value
                _useIntegerIndex = True
            End Set
        End Property

        Public Overridable Property Key() As String
            Get
                Return _key
            End Get
            Set(ByVal value As String)
                _index = -1
                _key = IIf((value Is Nothing), String.Empty, value)
                _useIntegerIndex = False
            End Set
        End Property
    End Class

    Friend NotInheritable Class NoneExcludedImageIndexConverter
        Inherits ImageIndexConverter
        Protected Overrides ReadOnly Property IncludeNoneAsStandardValue() As Boolean
            Get
                Return False
            End Get
        End Property
    End Class
End Namespace

 

--Class:ImageComboBox.vb--

Imports System.Collections.Generic
Imports System.Text
Imports System.Windows.Forms
Imports System.ComponentModel
Imports System.Collections
Imports System.Drawing
Imports System.Drawing.Drawing2D

Namespace Demo
    <ToolboxBitmap(GetType(ComboBox))> _
    Public Class ImageComboBox
        Inherits ComboBox
#Region "Fields"
        Private _imageList As ImageList
        Private _items As ImageComboBoxItemCollection
        Private _indent As Integer = 10
        Private _defaultImage As Image
        Private _defaultImageList As ImageList
        Private _emptyTextTip As String = String.Empty
        Private _emptyTextTipColor As Color = Color.DarkGray
        Private _nativeWimdow As EditorNativeWimdow

#End Region

#Region "Constructors"

        Public Sub New()
            MyBase.New()
            MyBase.DrawMode = DrawMode.OwnerDrawFixed
            MyBase.ItemHeight = 14
            _items = New ImageComboBoxItemCollection(Me)
        End Sub

#End Region

#Region "Properties"

        <Localizable(True)> _
        <MergableProperty(False)> _
        <DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
        Public Shadows ReadOnly Property Items() As ImageComboBoxItemCollection
            Get
                Return _items
            End Get
        End Property

        <DefaultValue(DirectCast(Nothing, String))> _
        Public Property ImageList() As ImageList
            Get
                Return _imageList
            End Get
            Set(ByVal value As ImageList)
                If _imageList IsNot value Then
                    _imageList = value
                End If
            End Set
        End Property

        <DefaultValue(GetType(Image), "")> _
        Public Property DefaultImage() As Image
            Get
                Return _defaultImage
            End Get
            Set(ByVal value As Image)
                If _defaultImage IsNot value Then
                    _defaultImage = value
                    If _defaultImage Is Nothing AndAlso _defaultImageList IsNot Nothing Then
                        _defaultImageList.Dispose()
                        _defaultImageList = Nothing
                    End If

                    If _defaultImage IsNot Nothing Then
                        _defaultImageList = New ImageList()
                        _defaultImageList.ColorDepth = ColorDepth.Depth24Bit
                        _defaultImageList.ImageSize = New Size(ItemHeight, ItemHeight)
                        _defaultImageList.Images.Add(_defaultImage)
                    End If

                    If DropDownStyle <> ComboBoxStyle.DropDownList Then
                        Invalidate(True)
                    End If
                End If
            End Set
        End Property

        '[DefaultValue("")]
        'public string EmptyTextTip
        '{
        '    get { return _emptyTextTip; }
        '    set
        '    {
        '        if (DropDownStyle == ComboBoxStyle.DropDown)
        '        {
        '            _emptyTextTip = value;
        '            base.Invalidate(true);
        '        }
        '    }
        '}

        '[DefaultValue(typeof(Color), "DarkGray")]
        'public Color EmptyTextTipColor
        '{
        '    get { return _emptyTextTipColor; }
        '    set
        '    {
        '        if (DropDownStyle == ComboBoxStyle.DropDown)
        '        {
        '            _emptyTextTipColor = value;
        '            base.Invalidate(true);
        '        }
        '    }
        '}

        <DefaultValue(10)> _
        Public Property Indent() As Integer
            Get
                Return _indent
            End Get
            Set(ByVal value As Integer)
                If _indent <> value Then
                    _indent = value
                    MyBase.RefreshItems()
                End If
            End Set
        End Property

        <DefaultValue(14)> _
        Public Shadows Property ItemHeight() As Integer
            Get
                Return MyBase.ItemHeight
            End Get
            Set(ByVal value As Integer)
                MyBase.ItemHeight = value
            End Set
        End Property

        <Browsable(False)> _
        <EditorBrowsable(EditorBrowsableState.Never)> _
        <DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)> _
        Public Shadows Property DrawMode() As DrawMode
            Get
                Return MyBase.DrawMode
            End Get
            Set(ByVal value As DrawMode)
                MyBase.DrawMode = DrawMode.OwnerDrawFixed
            End Set
        End Property

        <Browsable(False)> _
        <Bindable(True)> _
        <DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)> _
        Public Shadows Property SelectedItem() As ImageComboBoxItem
            Get
                If MyBase.SelectedItem Is Nothing Then
                    Return Nothing
                End If
                Return TryCast(MyBase.SelectedItem, ImageComboBoxItem)
            End Get
            Set(ByVal value As ImageComboBoxItem)
                MyBase.SelectedItem = value
            End Set
        End Property

        Public Shadows Property DropDownStyle() As ComboBoxStyle
            Get
                Return MyBase.DropDownStyle
            End Get
            Set(ByVal value As ComboBoxStyle)
                If MyBase.DropDownStyle <> value Then
                    If value = ComboBoxStyle.DropDownList Then
                        If _nativeWimdow IsNot Nothing Then
                            _nativeWimdow.Dispose()
                            _nativeWimdow = Nothing
                        End If
                    End If
                    MyBase.DropDownStyle = value
                End If
            End Set
        End Property

        Protected Friend ReadOnly Property OldItems() As ComboBox.ObjectCollection
            Get
                Return MyBase.Items
            End Get
        End Property

        Friend ReadOnly Property DefaultImageList() As ImageList
            Get
                Return _defaultImageList
            End Get
        End Property


        'public new string SelectedValue
        '{
        '    get
        '    {
        '        if (base.SelectedValue == null)
        '        {
        '            return string.Empty;
        '        }

        '        return base.SelectedValue.ToString();
        '    }
        '    set
        '    {
        '        base.SelectedValue = value;
        '    }
        '}

#End Region

#Region "Ovveride Methods"

        Protected Overrides Sub OnCreateControl()
            MyBase.OnCreateControl()
            If DropDownStyle <> ComboBoxStyle.DropDownList AndAlso Not DesignMode Then
                If _nativeWimdow Is Nothing Then
                    _nativeWimdow = New EditorNativeWimdow(Me)
                End If
            End If
        End Sub

        Protected Overrides Sub OnHandleDestroyed(ByVal e As EventArgs)
            If _nativeWimdow IsNot Nothing Then
                _nativeWimdow.Dispose()
                _nativeWimdow = Nothing
            End If
            MyBase.OnHandleDestroyed(e)
        End Sub

        Protected Overrides Sub OnDropDown(ByVal e As EventArgs)
            MyBase.OnDropDown(e)

            Dim ddWidth As Integer = 0
            'int textWidth = 0;
            Dim itemWidth As Integer = 0
            Dim scrollBarWidth As Integer = IIf(Items.Count > MaxDropDownItems, SystemInformation.VerticalScrollBarWidth, 0)
            Dim g As Graphics = CreateGraphics()

            For Each item As ImageComboBoxItem In Items
                'textWidth = g.MeasureString(
                '    item.Text, Font).ToSize().Width;
                itemWidth = ItemHeight + 8 + _indent * item.Level + scrollBarWidth

                If itemWidth > ddWidth Then
                    ddWidth = itemWidth
                End If
            Next

            DropDownWidth = IIf((ddWidth > Width), ddWidth, Width)
            g.Dispose()
        End Sub

        Protected Overrides Sub OnDrawItem(ByVal e As DrawItemEventArgs)
            If e.Index <> -1 Then
                Dim item As ImageComboBoxItem = Items(e.Index)
                Dim g As Graphics = e.Graphics
                Dim bounds As Rectangle = e.Bounds

                Dim indentOffset As Integer = Indent * item.Level

                If (e.State And DrawItemState.ComboBoxEdit) = DrawItemState.ComboBoxEdit Then
                    indentOffset = 0
                End If

                Dim imageWidth As Integer = bounds.Height
                Dim imageRect As Rectangle
                'Rectangle textRect;
                'TextFormatFlags format =
                '    TextFormatFlags.VerticalCenter |
                '    TextFormatFlags.SingleLine |
                '    TextFormatFlags.WordBreak;

                imageRect = New Rectangle(bounds.Left + indentOffset + 2, bounds.Top, imageWidth, imageWidth)
                'textRect = new Rectangle(
                '    imageRect.Right + 3,
                '    bounds.Y,
                '    bounds.Width - imageRect.Width - indentOffset - 5,
                '    bounds.Height);

                'Rectangle backRect = new Rectangle(
                '   textRect.X,
                '   textRect.Y + 1,
                '   textRect.Width,
                '   textRect.Height - 2);

                'backRect.Width = TextRenderer.MeasureText(
                '    item.Text, e.Font, textRect.Size, format).Width;

                'if (base.RightToLeft == RightToLeft.Yes)
                '{
                '    imageRect.X = bounds.Right - imageRect.Right;
                '    textRect.X = bounds.Right - textRect.Right;
                '    backRect.X = textRect.Right - backRect.Width;
                '}

                Dim selected As Boolean = ((e.State And DrawItemState.Selected) = DrawItemState.Selected)

                Dim backColor As Color = IIf(selected, SystemColors.Highlight, MyBase.BackColor)

                Using backBrush As Brush = New SolidBrush(backColor)
                    g.FillRectangle(backBrush, bounds)
                End Using

                If selected Then
                    ControlPaint.DrawFocusRectangle(g, bounds)
                End If

                Dim image As Image = item.Image
                If image IsNot Nothing Then
                    Using graphics As New InterpolationModeGraphics(g, InterpolationMode.HighQualityBicubic)
                        If selected Then
                            Dim hIcon As IntPtr = NativeMethods.ImageList_GetIcon(ImageList.Handle, item.ImageIndexer.ActualIndex, CInt(NativeMethods.ImageListDrawFlags.ILD_SELECTED))
                            g.DrawIcon(Icon.FromHandle(hIcon), imageRect)
                            NativeMethods.DestroyIcon(hIcon)
                        Else
                            g.DrawImage(image, imageRect, 0, 0, image.Width, image.Height, _
                             GraphicsUnit.Pixel)
                        End If
                    End Using

                    'TextRenderer.DrawText(
                    '    g,
                    '    item.Text,
                    '    e.Font,
                    '    textRect,
                    '    base.ForeColor,
                    '    format);
                End If
            End If
        End Sub

        Protected Overrides Sub Dispose(ByVal disposing As Boolean)
            MyBase.Dispose(disposing)

            If disposing Then
                _imageList = Nothing
                _defaultImage = Nothing
                _defaultImageList = Nothing
                _items = Nothing
            End If
        End Sub

#End Region

#Region "EditorNativeWimdow Class"

        Private Class EditorNativeWimdow
            Inherits NativeWindow
            Implements IDisposable
#Region "Fields"

            Private _owner As ImageComboBox

            Private Const EC_LEFTMARGIN As Integer = &H1
            Private Const EC_RIGHTMARGIN As Integer = &H2
            Private Const EC_USEFONTINFO As Integer = &HFFFF
            Private Const EM_SETMARGINS As Integer = &HD3
            Private Const EM_GETMARGINS As Integer = &HD4

#End Region

#Region "Constructors"

            Public Sub New(ByVal owner As ImageComboBox)
                MyBase.New()
                _owner = owner
                Attach()
            End Sub

#End Region

#Region "Private Methods"

            Private Sub Attach()
                If Not Handle.Equals(IntPtr.Zero) Then
                    ReleaseHandle()
                End If
                'AssignHandle(_owner.EditHandle);
                SetMargin()
            End Sub

            Protected Overrides Sub WndProc(ByRef m As Message)
                MyBase.WndProc(m)

                Select Case m.Msg
                    Case CInt(NativeMethods.WindowsMessage.WM_SETFONT)
                        SetMargin()
                        Exit Select
                    Case CInt(NativeMethods.WindowsMessage.WM_PAINT)
                        RePaint()
                        Exit Select
                    Case CInt(NativeMethods.WindowsMessage.WM_SETFOCUS), CInt(NativeMethods.WindowsMessage.WM_KILLFOCUS)
                        RePaint()
                        Exit Select
                    Case CInt(NativeMethods.WindowsMessage.WM_LBUTTONDOWN), CInt(NativeMethods.WindowsMessage.WM_RBUTTONDOWN), CInt(NativeMethods.WindowsMessage.WM_MBUTTONDOWN)
                        RePaint()
                        Exit Select
                    Case CInt(NativeMethods.WindowsMessage.WM_LBUTTONUP), CInt(NativeMethods.WindowsMessage.WM_RBUTTONUP), CInt(NativeMethods.WindowsMessage.WM_MBUTTONUP)
                        RePaint()
                        Exit Select
                    Case CInt(NativeMethods.WindowsMessage.WM_LBUTTONDBLCLK), CInt(NativeMethods.WindowsMessage.WM_RBUTTONDBLCLK), CInt(NativeMethods.WindowsMessage.WM_MBUTTONDBLCLK)
                        RePaint()
                        Exit Select
                    Case CInt(NativeMethods.WindowsMessage.WM_KEYDOWN), CInt(NativeMethods.WindowsMessage.WM_CHAR), CInt(NativeMethods.WindowsMessage.WM_KEYUP)
                        RePaint()
                        Exit Select
                    Case CInt(NativeMethods.WindowsMessage.WM_MOUSEMOVE)
                        If Not m.WParam.Equals(IntPtr.Zero) Then
                            RePaint()
                        End If
                        Exit Select
                End Select
            End Sub

            Friend Sub SetMargin()
                NearMargin(Handle, _owner.ItemHeight + 5)
            End Sub

            Private Shared Function IsRightToLeft(ByVal handle As IntPtr) As Boolean
                'int style = NativeMethods.GetWindowLong(
                '    handle, (int)NativeMethods.GWL.GWL_EXSTYLE);
                'return (
                '    ((style & (int)NativeMethods.WS_EX.WS_EX_RIGHT)
                '    == (int)NativeMethods.WS_EX.WS_EX_RIGHT) ||
                '    ((style & (int)NativeMethods.WS_EX.WS_EX_RTLREADING)
                '    == (int)NativeMethods.WS_EX.WS_EX_RTLREADING) ||
                '    ((style & (int)NativeMethods.WS_EX.WS_EX_LEFTSCROLLBAR)
                '    == (int)NativeMethods.WS_EX.WS_EX_LEFTSCROLLBAR));
                Return False
            End Function

            Private Shared Sub FarMargin(ByVal handle As IntPtr, ByVal margin As Integer)
                Dim message As Integer = IIf(IsRightToLeft(handle), EC_LEFTMARGIN, EC_RIGHTMARGIN)
                If message = EC_LEFTMARGIN Then
                    margin = margin And &HFFFF
                Else
                    margin = margin * &H10000
                End If
                NativeMethods.SendMessage(handle, EM_SETMARGINS, message, margin)
            End Sub

            Friend Shared Sub NearMargin(ByVal handle As IntPtr, ByVal margin As Integer)
                Dim message As Integer = IIf(IsRightToLeft(handle), EC_RIGHTMARGIN, EC_LEFTMARGIN)
                If message = EC_LEFTMARGIN Then
                    margin = margin And &HFFFF
                Else
                    margin = margin * &H10000
                End If
                NativeMethods.SendMessage(handle, EM_SETMARGINS, message, margin)
            End Sub

            Private Sub RePaint()
                Dim item As ImageComboBoxItem = _owner.SelectedItem

                Dim rcClient As New NativeMethods.RECT()
                NativeMethods.GetClientRect(Handle, rcClient)
                'bool rightToLeft = IsRightToLeft(Handle);

                Dim handle__1 As IntPtr = Handle
                Dim hdc As IntPtr = NativeMethods.GetDC(handle__1)
                If hdc = IntPtr.Zero Then
                    Return
                End If
                Try
                    Using g As Graphics = Graphics.FromHdc(hdc)
                        Dim itemSize As Integer = _owner.ItemHeight
                        Dim imageRect As New Rectangle(2, rcClient.Top + (rcClient.Bottom - itemSize) / 2, itemSize, itemSize)

                        'Rectangle textRect = new Rectangle(
                        '    0,
                        '    0,
                        '    rcClient.Right - itemSize - 6,
                        '    rcClient.Bottom);

                        'if (rightToLeft)
                        '{
                        '    imageRect.X = rcClient.Right - itemSize - 2;
                        '    //textRect.X = 2;
                        '}
                        'else
                        '{
                        'imageRect.X = 2;
                        'textRect.X = imageRect.Right + 2;
                        '}

                        'if (_owner.Text.Length == 0)
                        '{
                        '    DrawImage(
                        '       g,
                        '       imageRect,
                        '       _owner.DefaultImage,
                        '       _owner.DefaultImageList,
                        '       0,
                        '       _owner.Focused);

                        '    //if (_owner.Text.Length == 0 &&
                        '    //    !string.IsNullOrEmpty(_owner.EmptyTextTip) &&
                        '    //    !_owner.Focused)
                        '    //{
                        '    //    TextFormatFlags format =
                        '    //    TextFormatFlags.EndEllipsis |
                        '    //    TextFormatFlags.VerticalCenter;

                        '    //    if (_owner.RightToLeft == RightToLeft.Yes)
                        '    //    {
                        '    //        format |=
                        '    //            (TextFormatFlags.RightToLeft |
                        '    //            TextFormatFlags.Right);
                        '    //    }

                        '    //    TextRenderer.DrawText(
                        '    //        g,
                        '    //        _owner.EmptyTextTip,
                        '    //        _owner.Font,
                        '    //        textRect,
                        '    //        _owner.EmptyTextTipColor,
                        '    //        format);
                        '    //}
                        '    return;
                        '}

                        'if (_owner.Text.Length > 0)
                        '{
                        '    using (SolidBrush brush =
                        '        new SolidBrush(_owner.BackColor))
                        '    {
                        '        g.FillRectangle(brush, imageRect);
                        '    }
                        '}

                        'if (_owner.Items.Count == 0)
                        '{
                        '    DrawImage(
                        '       g,
                        '       imageRect,
                        '       _owner.DefaultImage,
                        '       _owner.DefaultImageList,
                        '       0,
                        '       _owner.Focused);
                        '    return;
                        '}

                        If item Is Nothing Then
                            Return
                        End If

                        DrawImage(g, imageRect, item.Image, _owner.ImageList, item.ImageIndexer.ActualIndex, _owner.Focused)
                    End Using
                Finally
                    NativeMethods.ReleaseDC(handle__1, hdc)
                End Try
            End Sub

            Private Sub DrawImage(ByVal g As Graphics, ByVal imageRect As Rectangle, ByVal image As Image, ByVal imageList As ImageList, ByVal imageIndex As Integer, ByVal focus As Boolean)
                Using brush As New SolidBrush(_owner.BackColor)
                    g.FillRectangle(brush, imageRect)
                End Using

                If image Is Nothing Then
                    Return
                End If

                Using graphics As New InterpolationModeGraphics(g, InterpolationMode.HighQualityBicubic)
                    If focus Then
                        Dim hIcon As IntPtr = NativeMethods.ImageList_GetIcon(imageList.Handle, imageIndex, CInt(NativeMethods.ImageListDrawFlags.ILD_SELECTED))
                        g.DrawIcon(Icon.FromHandle(hIcon), imageRect)
                        NativeMethods.DestroyIcon(hIcon)
                    Else
                        g.DrawImage(image, imageRect, 0, 0, image.Width, image.Height, _
                         GraphicsUnit.Pixel)
                    End If
                End Using
            End Sub

#End Region

#Region "IDisposable 成员"

            Public Sub Dispose() Implements IDisposable.Dispose
                _owner = Nothing
                MyBase.ReleaseHandle()
            End Sub

#End Region
        End Class

#End Region

#Region "ImageComboBoxItemCollection Class"

        <ListBindable(False)> _
        Public Class ImageComboBoxItemCollection
            Implements IList
            Implements ICollection
            Implements IEnumerable
#Region "Fields"

            Private _owner As ImageComboBox

#End Region

#Region "Constructors"

            Public Sub New(ByVal owner As ImageComboBox)
                _owner = owner
            End Sub

#End Region

#Region "Properties"

            Friend ReadOnly Property Owner() As ImageComboBox
                Get
                    Return _owner
                End Get
            End Property

            Default Public Property Item(ByVal index As Integer) As ImageComboBoxItem
                Get
                    Return TryCast(Owner.OldItems(index), ImageComboBoxItem)
                End Get
                Set(ByVal value As ImageComboBoxItem)
                    Owner.OldItems(index) = value
                End Set
            End Property

            Public ReadOnly Property Count() As Integer
                Get
                    Return Owner.OldItems.Count
                End Get
            End Property

            Public ReadOnly Property IsReadOnly() As Boolean
                Get
                    Return Owner.OldItems.IsReadOnly
                End Get
            End Property

#End Region

#Region "Public Methods"

            Public Function Add(ByVal item As ImageComboBoxItem) As Integer
                If item Is Nothing Then
                    Throw New ArgumentNullException("item")
                End If
                item.Host(Owner)
                Return Owner.OldItems.Add(item)
            End Function

            Public Sub AddRange(ByVal value As ImageComboBoxItemCollection)
                For Each item As ImageComboBoxItem In value
                    Add(item)
                Next
            End Sub

            Public Sub AddRange(ByVal items As ImageComboBoxItem())
                For Each item As ImageComboBoxItem In items
                    Add(item)
                Next
            End Sub

            Public Sub Clear()
                Owner.OldItems.Clear()
            End Sub

            Public Function Contains(ByVal item As ImageComboBoxItem) As Boolean
                Return Owner.OldItems.Contains(item)
            End Function

            Public Sub CopyTo(ByVal destination As ImageComboBoxItem(), ByVal arrayIndex As Integer)
                Owner.OldItems.CopyTo(destination, arrayIndex)
            End Sub

            Public Function IndexOf(ByVal item As ImageComboBoxItem) As Integer
                Return Owner.OldItems.IndexOf(item)
            End Function

            Public Sub Insert(ByVal index As Integer, ByVal item As ImageComboBoxItem)
                If item Is Nothing Then
                    Throw New ArgumentNullException("item")
                End If
                item.Host(Owner)
                Owner.OldItems.Insert(index, item)
            End Sub

            Public Sub Remove(ByVal item As ImageComboBoxItem)
                Owner.OldItems.Remove(item)
            End Sub

            Public Sub RemoveAt(ByVal index As Integer)
                Owner.OldItems.RemoveAt(index)
            End Sub

            Public Function GetEnumerator() As IEnumerator
                Return Owner.OldItems.GetEnumerator()
            End Function

#End Region

#Region "IList 成员"

            Private Function IList_Add(ByVal value As Object) As Integer Implements IList.Add
                If Not (TypeOf value Is ImageComboBoxItem) Then
                    Throw New ArgumentException()
                End If
                Return Add(TryCast(value, ImageComboBoxItem))
            End Function

            Private Sub IList_Clear() Implements IList.Clear
                Clear()
            End Sub

            Private Function IList_Contains(ByVal value As Object) As Boolean Implements IList.Contains
                Return Contains(TryCast(value, ImageComboBoxItem))
            End Function

            Private Function IList_IndexOf(ByVal value As Object) As Integer Implements IList.IndexOf
                Return IndexOf(TryCast(value, ImageComboBoxItem))
            End Function

            Private Sub IList_Insert(ByVal index As Integer, ByVal value As Object) Implements IList.Insert
                If Not (TypeOf value Is ImageComboBoxItem) Then
                    Throw New ArgumentException()
                End If
                Insert(index, TryCast(value, ImageComboBoxItem))
            End Sub

            Private ReadOnly Property IList_IsFixedSize() As Boolean Implements IList.IsFixedSize
                Get
                    Return False
                End Get
            End Property

            Private ReadOnly Property IList_IsReadOnly() As Boolean Implements IList.IsReadOnly
                Get
                    Return IsReadOnly
                End Get
            End Property

            Private Sub IList_Remove(ByVal value As Object) Implements IList.Remove
                Remove(TryCast(value, ImageComboBoxItem))
            End Sub

            Private Sub IList_RemoveAt(ByVal index As Integer) Implements IList.RemoveAt
                RemoveAt(index)
            End Sub

            Property IList_Item(ByVal index As Integer) As Object Implements IList.Item
                Get
                    Return Me(index)
                End Get
                Set(ByVal value As Object)
                    If Not (TypeOf value Is ImageComboBoxItem) Then
                        Throw New ArgumentException()
                    End If
                    Me(index) = TryCast(value, ImageComboBoxItem)
                End Set
            End Property
#End Region

#Region "ICollection 成员"

            Private Sub ICollection_CopyTo(ByVal array As Array, ByVal index As Integer) Implements ICollection.CopyTo
                CopyTo(DirectCast(array, ImageComboBoxItem()), index)
            End Sub

            Private ReadOnly Property ICollection_Count() As Integer Implements ICollection.Count
                Get
                    Return Count
                End Get
            End Property

            Private ReadOnly Property ICollection_IsSynchronized() As Boolean Implements ICollection.IsSynchronized
                Get
                    Return False
                End Get
            End Property

            Private ReadOnly Property ICollection_SyncRoot() As Object Implements ICollection.SyncRoot
                Get
                    Return Me
                End Get
            End Property

#End Region

#Region "IEnumerable 成员"

            Private Function IEnumerable_GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
                Return GetEnumerator()
            End Function

#End Region
        End Class

#End Region
    End Class

    Public Class InterpolationModeGraphics
        Implements IDisposable
        Private _oldMode As InterpolationMode
        Private _graphics As Graphics

        Public Sub New(ByVal graphics As Graphics)
            Me.New(graphics, InterpolationMode.HighQualityBicubic)
        End Sub

        Public Sub New(ByVal graphics As Graphics, ByVal newMode As InterpolationMode)
            _graphics = graphics
            _oldMode = graphics.InterpolationMode
            graphics.InterpolationMode = newMode
        End Sub

#Region "IDisposable 成员"

        Public Sub Dispose() Implements IDisposable.Dispose
            _graphics.InterpolationMode = _oldMode
        End Sub

#End Region
    End Class
End Namespace

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值