I'm currently in the process of dusting off the bugs from a tool written back in 2011. One of the bugs involves an editable ComboBox
control paired with a separate Button
control. When the button is clicked a popup menu is shown, and when an item in this menu is clicked, the text of the ComboBox
is updated.
The problem with this scenario is by default, as soon as the ComboBox
loses focus, the SelectionStart
, SelectionLength
and SelectedText
properties are reset, thus preventing my little menu from replacing the selected text. While this article doesn't solve this problem (I'll save that for the next article!), it does describe how you can get the hWnd
, or window handle (in .NET terms the Handle
) of the edit component, thus opening the door for a little Win32 API fun.
There are various approaches to doing this - you could use FindWindow
and search for a child window with a class of edit
, or use SendMessage
with the CB_GETCOMBOBOXINFO
message. Or, easiest of all, we can use the GetComboBoxInfo
function.
Interop Declarations
Using this API is very simple, as there's one method and two simple structs.
[DllImport("user32.dll")]publicstaticexternbool GetComboBoxInfo(IntPtr hWnd, ref COMBOBOXINFO pcbi); [StructLayout(LayoutKind.Sequential)] publicstruct COMBOBOXINFO {publicint cbSize;public RECT rcItem;public RECT rcButton;publicint stateButton;public IntPtr hwndCombo;public IntPtr hwndEdit;public IntPtr hwndList; } [StructLayout(LayoutKind.Sequential)] publicstruct RECT {publicint left;publicint top;publicint right;publicint bottom; }
Calling the API
There is one (well, many, but lets start simple!) caveat which you may fall foul of if you are new to Win32 API programming - often the contents of structs need to be initialized with their size first. But how to you know how big a structure is? Lucky for you, you don't need to calculate it manually - the Marshal.SizeOf
function will handle this for you.
If you forget to set the size, then the structure simply won't be populated.
NativeMethods.COMBOBOXINFO info; info = new NativeMethods.COMBOBOXINFO(); info.cbSize = Marshal.SizeOf(info);if (NativeMethods.GetComboBoxInfo(control.Handle, ref info)) {// the info structure is now populated, go wild! }
Getting the edit control handle
With the above in place, then getting the handle of the edit component is very straightforward.
private IntPtr GetEditHandle(ComboBox control) { NativeMethods.COMBOBOXINFO info; info = new NativeMethods.COMBOBOXINFO(); info.cbSize = Marshal.SizeOf(info);return NativeMethods.GetComboBoxInfo(control.Handle, ref info) ? info.hwndEdit : IntPtr.Zero; }
Bear in mind that the edit
control is a Win32 control - not a managed .NET control. In order to do anything with this therefore, you need to use additional Win32 API methods, or perhaps bind it to a NativeWindow
class for easy subclassing. I'll briefly cover some of this in a future article.
Other goodies
The COMBOBOXINFO
structure has other information, such as the handle of the list
control, which you see if you set the DropDownStyle
property of the ComboBox
to Simple
and the state of the dropdown button. You can view the MSDN Documentation to learn more about the structure.
Downloads
- GetComboBoxInfoDemo.zip (8.49 KB)
All content Copyright © by Cyotek Ltd or its respective writers. Permission to reproduce news and web log entries and other RSS feed content in unmodified form without notice is granted provided they are not used to endorse or promote any products or opinions (other than what was expressed by the author) and without taking them out of context. Written permission from the copyright owner must be obtained for everything else.
Original URL of this content is http://www.cyotek.com/blog/getting-the-hwnd-of-the-edit-component-within-a-combobox-control?source=rss