xersoft
asked on
Designing a simple drop down list box control from scratch
Hi,
I’m trying to create a drop down control from scratch. I’m running into one problem so far: The actual drop down part of the box. So far I was thinking that making a separate form and managing its position would work. So I did that and it works great. The control would work for many applications the way it is. The problem is that I need to call dropdownform.show and this deactivates the form the actual drop down control lives on. I’ve attempted to put the code up in this message.
The question is how do I make a control that will ‘float’ over everything else (the window with the drop down selections in it) that does not deactivate the container control for the drop down.
Thanks for any help.
Control:
Public Class DropDownList
Inherits System.Windows.Forms.UserC ontrol
'dropdownbutton
Private mDropDownRegion As Drawing.Region
'drop down form
Dim WithEvents dropDownfrm As frmComboDrop
Dim dropDownfrmHeight As Integer = 100
Dim DropDownDirection As Integer = 1
Dim Showingdropdownfrm As Boolean = False
#Region " Windows Form Designer generated code "
Public Sub New()
MyBase.New()
'This call is required by the Windows Form Designer.
InitializeComponent()
'Add any initialization after the InitializeComponent() call
Me.SetStyle(Windows.Forms. ControlSty les.Double Buffer Or Windows.Forms.ControlStyle s.UserPain t Or Windows.Forms.ControlStyle s.AllPaint ingInWmPai nt, True)
Me.UpdateStyles()
dropDownfrm = New frmComboDrop
End Sub
'UserControl overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
'Required by the Windows Form Designer
Private components As System.ComponentModel.ICon tainer
'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
Friend WithEvents tmrShowForm As System.Windows.Forms.Timer
<System.Diagnostics.Debugg erStepThro ugh()> Private Sub InitializeComponent()
Me.components = New System.ComponentModel.Cont ainer
Me.tmrShowForm = New System.Windows.Forms.Timer (Me.compon ents)
'
'tmrShowForm
'
Me.tmrShowForm.Interval = 25
'
'DropDownList
'
Me.BackColor = System.Drawing.SystemColor s.Window
Me.Name = "DropDownList"
Me.Size = New System.Drawing.Size(208, 20)
End Sub
#End Region
Private ReadOnly Property ClickBoxSize() As Integer
Get
Return Me.Size.Height
End Get
End Property
<ComponentModel.Browsable( False)> Public ReadOnly Property Items() As ArrayList
Get
Return dropDownfrm.Items
End Get
End Property
Private Sub DropDownList_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Resize
Me.Size = New Drawing.Size(Me.Size.Width , ClickBoxSize)
Me.Invalidate()
End Sub
Private Sub DropDownList_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.Paint EventArgs) Handles MyBase.Paint
Dim DropDownButtonRect As New Drawing.Rectangle(Me.Size. Width - ClickBoxSize - 1, 0, ClickBoxSize, ClickBoxSize - 1)
Dim TextBoxAreaRect As New Drawing.Rectangle(0, 0, Me.Size.Width - DropDownButtonRect.Width, Me.Size.Height - 1)
Dim SymbolFont As New Drawing.Font("Marlett", 16, Drawing.FontStyle.Regular, Drawing.GraphicsUnit.Pixel )
Dim DownArrowSize As Drawing.Size = e.Graphics.MeasureString(" 6", SymbolFont).ToSize
'draw the text box stuff
e.Graphics.FillRectangle(D rawing.Sys temBrushes .Window, TextBoxAreaRect)
'text in text box area
Dim TextSize As Drawing.Size = e.Graphics.MeasureString(M e.Text, Me.Font).ToSize
Dim TextPoint As New Drawing.Point(0, CInt(TextBoxAreaRect.Heigh t / 2 - TextSize.Height / 2))
e.Graphics.DrawString(Me.T ext, Me.Font, Drawing.SystemBrushes.Cont rolText, TextPoint.X, TextPoint.Y)
'draw button
e.Graphics.FillRectangle(D rawing.Sys temBrushes .Control, DropDownButtonRect)
'draw button text
Dim ButtonTextPoint As New Drawing.Point(DropDownButt onRect.X + CInt(DropDownButtonRect.Wi dth / 2 - DownArrowSize.Width / 2), DropDownButtonRect.Y + CInt(DropDownButtonRect.He ight / 2 - DownArrowSize.Height / 2))
e.Graphics.DrawString("6", SymbolFont, Drawing.SystemBrushes.Cont rolText, ButtonTextPoint.X, ButtonTextPoint.Y)
'button border
e.Graphics.DrawRectangle(D rawing.Sys temPens.Co ntrolText, DropDownButtonRect)
If Not mDropDownRegion Is Nothing Then
mDropDownRegion.Dispose()
End If
mDropDownRegion = New Drawing.Region(DropDownBut tonRect)
End Sub
Private Sub DropDownList_MouseDown(ByV al sender As Object, ByVal e As System.Windows.Forms.Mouse EventArgs) Handles MyBase.MouseDown
If Not mDropDownRegion Is Nothing Then
If mDropDownRegion.IsVisible( e.X, e.Y) Then
Dim button As New Windows.Forms.Button
button.Location = New Drawing.Point(10, 10)
button.Show()
'ShowDropDown()
End If
End If
End Sub
Private Sub ShowDropDown()
If Showingdropdownfrm = False Then
dropDownfrm.Size = New Drawing.Size(Me.Size.Width , 10)
dropDownfrm.Location = Me.PointToScreen(New Drawing.Point(0, Me.Height))
dropDownfrm.TopMost = True
dropDownfrm.Show()
tmrShowForm.Enabled = True
Showingdropdownfrm = True
DropDownDirection = 1
'dropDownfrm.Focus()
End If
End Sub
Private Sub dropDownfrm_HideMeEvent(By Val sender As Object, ByVal e As System.EventArgs) Handles dropDownfrm.HideMeEvent
DropDownDirection = -1
tmrShowForm.Enabled = True
End Sub
Private Sub tmrShowForm_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tmrShowForm.Tick
If Showingdropdownfrm Then
Dim NewHeight As Integer = dropDownfrm.Size.Height
NewHeight += DropDownDirection * Convert.ToInt32(dropDownfr mHeight / 3)
If NewHeight > dropDownfrmHeight Then
NewHeight = dropDownfrmHeight
tmrShowForm.Enabled = False
End If
If NewHeight < 0 Then
dropDownfrm.Hide()
Showingdropdownfrm = False
tmrShowForm.Enabled = False
Exit Sub
End If
dropDownfrm.Size = New Drawing.Size(Me.Size.Width , NewHeight)
dropDownfrm.Location = Me.PointToScreen(New Drawing.Point(0, Me.Height))
End If
End Sub
Private Sub dropDownfrm_TextChanged(By Val sender As Object, ByVal e As System.EventArgs) Handles dropDownfrm.TextChanged
Me.Text = DirectCast(sender, frmComboDrop).Text
End Sub
Private Sub DropDownList_TextChanged(B yVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.TextChanged
Me.Invalidate()
End Sub
End Class
'probably put this in another file?
Friend Class frmComboDrop
Inherits System.Windows.Forms.Form
Public Event HideMeEvent(ByVal sender As Object, ByVal e As EventArgs)
Private mItems As New ArrayList
#Region " Windows Form Designer generated code "
Public Sub New()
MyBase.New()
'This call is required by the Windows Form Designer.
InitializeComponent()
'Add any initialization after the InitializeComponent() call
Me.SetStyle(Windows.Forms. ControlSty les.Select able, False)
Me.UpdateStyles()
End Sub
'Form overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
'Required by the Windows Form Designer
Private components As System.ComponentModel.ICon tainer
'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
<System.Diagnostics.Debugg erStepThro ugh()> Private Sub InitializeComponent()
'
'frmComboDrop
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.AutoScroll = True
Me.BackColor = System.Drawing.SystemColor s.Window
Me.ClientSize = New System.Drawing.Size(164, 100)
Me.ControlBox = False
Me.FormBorderStyle = System.Windows.Forms.FormB orderStyle .None
Me.Name = "frmComboDrop"
Me.ShowInTaskbar = False
Me.StartPosition = System.Windows.Forms.FormS tartPositi on.Manual
End Sub
#End Region
Public ReadOnly Property Items() As ArrayList
Get
Return mItems
End Get
End Property
Private Sub Item_Click(ByVal sender As Object, ByVal e As System.EventArgs)
Me.Text = DirectCast(sender, Windows.Forms.LinkLabel).T ext
RaiseEvent HideMeEvent(Me, New EventArgs)
End Sub
Private Sub frmComboDrop_GotFocus(ByVa l sender As Object, ByVal e As System.EventArgs) Handles MyBase.GotFocus
'show all the data
Me.Controls.Clear()
For Each itm As Object In Items
Dim lnk As New Windows.Forms.LinkLabel
lnk.Text = itm.ToString
lnk.AutoSize = True
lnk.LinkBehavior = Windows.Forms.LinkBehavior .HoverUnde rline
AddHandler lnk.Click, AddressOf Item_Click
lnk.Location = New Drawing.Point(0, Me.Controls.Count * (lnk.Size.Height + 1))
Me.Controls.Add(lnk)
Next
End Sub
Private Sub frmComboDrop_Deactivate(By Val sender As Object, ByVal e As System.EventArgs) Handles MyBase.Deactivate
RaiseEvent HideMeEvent(Me, New EventArgs)
End Sub
End Class
I’m trying to create a drop down control from scratch. I’m running into one problem so far: The actual drop down part of the box. So far I was thinking that making a separate form and managing its position would work. So I did that and it works great. The control would work for many applications the way it is. The problem is that I need to call dropdownform.show and this deactivates the form the actual drop down control lives on. I’ve attempted to put the code up in this message.
The question is how do I make a control that will ‘float’ over everything else (the window with the drop down selections in it) that does not deactivate the container control for the drop down.
Thanks for any help.
Control:
Public Class DropDownList
Inherits System.Windows.Forms.UserC
'dropdownbutton
Private mDropDownRegion As Drawing.Region
'drop down form
Dim WithEvents dropDownfrm As frmComboDrop
Dim dropDownfrmHeight As Integer = 100
Dim DropDownDirection As Integer = 1
Dim Showingdropdownfrm As Boolean = False
#Region " Windows Form Designer generated code "
Public Sub New()
MyBase.New()
'This call is required by the Windows Form Designer.
InitializeComponent()
'Add any initialization after the InitializeComponent() call
Me.SetStyle(Windows.Forms.
Me.UpdateStyles()
dropDownfrm = New frmComboDrop
End Sub
'UserControl overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
'Required by the Windows Form Designer
Private components As System.ComponentModel.ICon
'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
Friend WithEvents tmrShowForm As System.Windows.Forms.Timer
<System.Diagnostics.Debugg
Me.components = New System.ComponentModel.Cont
Me.tmrShowForm = New System.Windows.Forms.Timer
'
'tmrShowForm
'
Me.tmrShowForm.Interval = 25
'
'DropDownList
'
Me.BackColor = System.Drawing.SystemColor
Me.Name = "DropDownList"
Me.Size = New System.Drawing.Size(208, 20)
End Sub
#End Region
Private ReadOnly Property ClickBoxSize() As Integer
Get
Return Me.Size.Height
End Get
End Property
<ComponentModel.Browsable(
Get
Return dropDownfrm.Items
End Get
End Property
Private Sub DropDownList_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Resize
Me.Size = New Drawing.Size(Me.Size.Width
Me.Invalidate()
End Sub
Private Sub DropDownList_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.Paint
Dim DropDownButtonRect As New Drawing.Rectangle(Me.Size.
Dim TextBoxAreaRect As New Drawing.Rectangle(0, 0, Me.Size.Width - DropDownButtonRect.Width, Me.Size.Height - 1)
Dim SymbolFont As New Drawing.Font("Marlett", 16, Drawing.FontStyle.Regular,
Dim DownArrowSize As Drawing.Size = e.Graphics.MeasureString("
'draw the text box stuff
e.Graphics.FillRectangle(D
'text in text box area
Dim TextSize As Drawing.Size = e.Graphics.MeasureString(M
Dim TextPoint As New Drawing.Point(0, CInt(TextBoxAreaRect.Heigh
e.Graphics.DrawString(Me.T
'draw button
e.Graphics.FillRectangle(D
'draw button text
Dim ButtonTextPoint As New Drawing.Point(DropDownButt
e.Graphics.DrawString("6",
'button border
e.Graphics.DrawRectangle(D
If Not mDropDownRegion Is Nothing Then
mDropDownRegion.Dispose()
End If
mDropDownRegion = New Drawing.Region(DropDownBut
End Sub
Private Sub DropDownList_MouseDown(ByV
If Not mDropDownRegion Is Nothing Then
If mDropDownRegion.IsVisible(
Dim button As New Windows.Forms.Button
button.Location = New Drawing.Point(10, 10)
button.Show()
'ShowDropDown()
End If
End If
End Sub
Private Sub ShowDropDown()
If Showingdropdownfrm = False Then
dropDownfrm.Size = New Drawing.Size(Me.Size.Width
dropDownfrm.Location = Me.PointToScreen(New Drawing.Point(0, Me.Height))
dropDownfrm.TopMost = True
dropDownfrm.Show()
tmrShowForm.Enabled = True
Showingdropdownfrm = True
DropDownDirection = 1
'dropDownfrm.Focus()
End If
End Sub
Private Sub dropDownfrm_HideMeEvent(By
DropDownDirection = -1
tmrShowForm.Enabled = True
End Sub
Private Sub tmrShowForm_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tmrShowForm.Tick
If Showingdropdownfrm Then
Dim NewHeight As Integer = dropDownfrm.Size.Height
NewHeight += DropDownDirection * Convert.ToInt32(dropDownfr
If NewHeight > dropDownfrmHeight Then
NewHeight = dropDownfrmHeight
tmrShowForm.Enabled = False
End If
If NewHeight < 0 Then
dropDownfrm.Hide()
Showingdropdownfrm = False
tmrShowForm.Enabled = False
Exit Sub
End If
dropDownfrm.Size = New Drawing.Size(Me.Size.Width
dropDownfrm.Location = Me.PointToScreen(New Drawing.Point(0, Me.Height))
End If
End Sub
Private Sub dropDownfrm_TextChanged(By
Me.Text = DirectCast(sender, frmComboDrop).Text
End Sub
Private Sub DropDownList_TextChanged(B
Me.Invalidate()
End Sub
End Class
'probably put this in another file?
Friend Class frmComboDrop
Inherits System.Windows.Forms.Form
Public Event HideMeEvent(ByVal sender As Object, ByVal e As EventArgs)
Private mItems As New ArrayList
#Region " Windows Form Designer generated code "
Public Sub New()
MyBase.New()
'This call is required by the Windows Form Designer.
InitializeComponent()
'Add any initialization after the InitializeComponent() call
Me.SetStyle(Windows.Forms.
Me.UpdateStyles()
End Sub
'Form overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
'Required by the Windows Form Designer
Private components As System.ComponentModel.ICon
'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
<System.Diagnostics.Debugg
'
'frmComboDrop
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.AutoScroll = True
Me.BackColor = System.Drawing.SystemColor
Me.ClientSize = New System.Drawing.Size(164, 100)
Me.ControlBox = False
Me.FormBorderStyle = System.Windows.Forms.FormB
Me.Name = "frmComboDrop"
Me.ShowInTaskbar = False
Me.StartPosition = System.Windows.Forms.FormS
End Sub
#End Region
Public ReadOnly Property Items() As ArrayList
Get
Return mItems
End Get
End Property
Private Sub Item_Click(ByVal sender As Object, ByVal e As System.EventArgs)
Me.Text = DirectCast(sender, Windows.Forms.LinkLabel).T
RaiseEvent HideMeEvent(Me, New EventArgs)
End Sub
Private Sub frmComboDrop_GotFocus(ByVa
'show all the data
Me.Controls.Clear()
For Each itm As Object In Items
Dim lnk As New Windows.Forms.LinkLabel
lnk.Text = itm.ToString
lnk.AutoSize = True
lnk.LinkBehavior = Windows.Forms.LinkBehavior
AddHandler lnk.Click, AddressOf Item_Click
lnk.Location = New Drawing.Point(0, Me.Controls.Count * (lnk.Size.Height + 1))
Me.Controls.Add(lnk)
Next
End Sub
Private Sub frmComboDrop_Deactivate(By
RaiseEvent HideMeEvent(Me, New EventArgs)
End Sub
End Class
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
'CLASS: DropDownList
'bad code
Private Sub DropDownList_MouseDown(ByV
If Not mDropDownRegion Is Nothing Then
If mDropDownRegion.IsVisible(
Dim button As New Windows.Forms.Button
button.Location = New Drawing.Point(10, 10)
button.Show()
'ShowDropDown()
End If
End If
End Sub
'good code
Private Sub DropDownList_MouseDown(ByV
If Not mDropDownRegion Is Nothing Then
If mDropDownRegion.IsVisible(
ShowDropDown()
End If
End If
End Sub