Building a combo box - can't get listbox to draw outside the form

  • Thread starter Thread starter Andrew Cuthbert
  • Start date Start date
A

Andrew Cuthbert

Hi all,

I'm struggling with something I thought would be simple. I
need to build a combo box from scratch as I need to do
more alterations than an owner draw combo box will allow.
I was always told a combo box was just a textbox and a
listbox. Well, that's fine but the listbox is bound by the
clipping region of the form. Thus if the combo is
positioned near the bottom of the form, the listbox gets
chopped off.

I've tried creating a form for the listbox to sit on, and
then move both to the relevant location. This is still
buggy though as when you click in the listbox, the host
form loses focus - and I also suspect creating a whole
form just for this feature is not very efficient.

There must be a way surely to do this in .NET through GDI+
or something. Essentially all I want is to fool .NET into
drawing the listbox where I specify on the screen, without
being bound by a forms drawing area.

Any ideas?

Thanks,

Andrew Cuthbert
 
Hi Andrew,

why not make the form a bit larger at the bottom? Perhaps at runtime if the listbox dropps down? Or move the combobox a bit up?

I am writing the glue logic to make a combo from a textbox, a button and listbox for use in a datagrid column to avoid exactly this
problem. Not easy, I can say... I expect it to be done during the next week, you may have a look at

http://www.i-syn.gmxhome.de/devcom/colstyles/intro.htm

then.
Ulrich
 
Ulrich,

thanks for the reply. I've taken a look at your code on the site, and I
think you've taken a very different approach. You are inheriting from
Forms.ComboxBox which will handle the display of the listbox for you. What I
want is to draw the listbox above everything, not only in my
application/form but outside the form. If you put a combo box at the bottom
of a form and open the drop down - you will notice the list pops out over
the edge of the form. It is this behaviour I'm trying to reproduce but for
various reasons I can't inherit from combobox - not least because it'll
really bug me if a Microsoft .NET component can do things I can't in my
components!!

Thanks for your help - any futher thoughts?

Andrew

Ulrich Sprick said:
Hi Andrew,

why not make the form a bit larger at the bottom? Perhaps at runtime if
the listbox dropps down? Or move the combobox a bit up?
I am writing the glue logic to make a combo from a textbox, a button and
listbox for use in a datagrid column to avoid exactly this
 
Put your listbox onto a separate Form with FormBorderStyle.None and
TopMost=true, and position it so its top-left corner (in screen
coordinates) is the same as the bottom-left corner of the combo box.
That's essentially the way the standard ComboBox control works.
 
Hi, I also needed for various reasons to create controls
that draw outside the form, like a tool tip or something.
So I figured that the only way is to create an inherited
form which I called FloatingWin and don't provide any
painting in it. Than a listbox like the one you want to
draw can basically be derived from here. One trick to
make sure that the parent form doesn't loose focus is to
override the OnActivate for the floating window and there
set the focus back on the main form, after you do some
processing...
This is the constructor for the floating window:

public FloatingWin(Form owner) : base()
{
this.windowHeight = 0;
this.windowWidth = 0;
this.ownerTop = false; (*)
base.Visible = false;
base.ShowInTaskbar = false;
base.StartPosition = 0;
base.FormBorderStyle = FormBorderStyle.None;
base.Owner = owner;
if (owner != null)
{
this.ownerTop = owner.TopMost;
}
}

You can see that this form is always owned by another
form and I also need to keep track if the owner form is
on top (*), because if the owner form goes under you
should make the floating windows that belong to it
invisible too...


I hope this helps,

Iulian
 
Andrew Cuthbert said:
I'm struggling with something I thought would be simple. I
need to build a combo box from scratch as I need to do
more alterations than an owner draw combo box will allow.
I was always told a combo box was just a textbox and a
listbox. Well, that's fine but the listbox is bound by the
clipping region of the form. Thus if the combo is
positioned near the bottom of the form, the listbox gets
chopped off.


The ListBox needs to be a child of the desktop rather then the Form. To see
this, create a new Windows Forms application, add a ListBox (set Visible to
False and BorderStyle to FixedSingle), place a Button in the bottom right
and add the following code:

Private Declare Auto Function SetParent Lib "user32.dll" _
(childHwnd As IntPtr, parentHwnd As IntPtr) As IntPtr

Private m_lst As DropDownListBox

Private Sub Button1_Click(sender As Object, e As EventArgs) _
Handles Button1.Click

If m_lst Is Nothing Then
m_lst = New DropDownListBox()
m_lst.BorderStyle = BorderStyle.FixedSingle
m_lst.Location = _
PointToScreen( _
New Point(Button1.Left, Button1.Top + Button1.Height))
SetParent(m_lst.Handle, IntPtr.Zero)
m_lst.Visible = True
Else
m_lst.Visible = False
m_lst.Dispose()
m_lst = Nothing
End If

End Sub

Private Class DropDownListBox
Inherits ListBox

Public Sub New()
MyBase.New()
End Sub

Protected Overrides ReadOnly Property CreateParams() As CreateParams

Get
Dim cp As CreateParams = MyBase.CreateParams
cp.ExStyle = cp.ExStyle Or &H80 ' WS_EX_TOOLWINDOW
Return cp
End Get

End Property

End Class

Ideally the code for setting the parent should be done in the
DropDownListBox class, however for some reason setting CreateParams.Parent
to IntPtr.Zero doesn't achieve the desired result so some further
investigation will be required.
 
[snip]
The ListBox needs to be a child of the desktop rather then the Form. To see
this, create a new Windows Forms application, add a ListBox (set Visible to
False and BorderStyle to FixedSingle), place a Button in the bottom right

[snip]

I should clarify that you don't need to add a ListBox to the From; just use
the DroppedDownListBox in code as shown. If you call SetParent on a regular
ListBox then Windows will create a TaskBar entry for it since any unowned
windows (i.e. immediate children of the desktop) automatically get a TaskBar
entry unless WS_EX_TOOLWINDOW is specified.
 
Back
Top