using System; using System.Runtime.InteropServices; using static Vanara.PInvoke.User32; namespace Vanara.PInvoke { public static partial class ComCtl32 { /// Window class for Extended Combo Box. public const string WC_COMBOBOXEX = "ComboBoxEx32"; /// A value that specifies the action that generated the CBEN_ENDEDIT notification code. [PInvokeData("Commctrl.h", MSDNShortId = "bb775750")] public enum CBEN_ENDEDIT_FLAG { /// The edit box lost the keyboard focus. CBENF_KILLFOCUS = 1, /// The user completed the edit operation by pressing ENTER. CBENF_RETURN = 2, /// The user pressed ESC. CBENF_ESCAPE = 3, /// The user activated the drop-down list. CBENF_DROPDOWN = 4, } /// /// A set of bit flags that specify attributes of COMBOBOXEXITEM or of an operation that is using this structure. The flags specify /// members that are valid or must be filled in. /// [PInvokeData("Commctrl.h", MSDNShortId = "bb775746")] [Flags] public enum ComboBoxExItemMask { /// The pszText member is valid or must be filled in. CBEIF_TEXT = 0x00000001, /// The iImage member is valid or must be filled in. CBEIF_IMAGE = 0x00000002, /// The iSelectedImage member is valid or must be filled in. CBEIF_SELECTEDIMAGE = 0x00000004, /// The iOverlay member is valid or must be filled in. CBEIF_OVERLAY = 0x00000008, /// The iIndent member is valid or must be filled in. CBEIF_INDENT = 0x00000010, /// The lParam member is valid or must be filled in. CBEIF_LPARAM = 0x00000020, /// /// Set this flag when processing CBEN_GETDISPINFO; the ComboBoxEx control will retain the supplied information and will not /// request it again. /// CBEIF_DI_SETITEM = 0x10000000, } /// Support the extended styles that are listed in this section as well as most standard combo box control styles. [PInvokeData("Commctrl.h", MSDNShortId = "bb775742")] public enum ComboBoxExStyle { /// The edit box and the dropdown list will not display item images. CBES_EX_NOEDITIMAGE = 0x00000001, /// The edit box and the dropdown list will not display item images. CBES_EX_NOEDITIMAGEINDENT = 0x00000002, /// /// Windows NT only. The edit box will use the slash (/), backslash (\), and period (.) characters as word delimiters. This makes /// keyboard shortcuts for word-by-word cursor movement effective in path names and URLs. /// CBES_EX_PATHWORDBREAKPROC = 0x00000004, /// /// Allows the ComboBoxEx control to be vertically sized smaller than its contained combo box control. If the ComboBoxEx is sized /// smaller than the combo box, the combo box will be clipped. /// CBES_EX_NOSIZELIMIT = 0x00000008, /// /// BSTR searches in the list will be case sensitive. This includes searches as a result of text being typed in the edit box and /// the CB_FINDSTRINGEXACT message. /// CBES_EX_CASESENSITIVE = 0x00000010, /// /// Windows Vista and later. Causes items in the drop-down list and the edit box (when the edit box is read only) to be truncated /// with an ellipsis ("...") rather than just clipped by the edge of the control. This is useful when the control needs to be set /// to a fixed width, yet the entries in the list may be long. /// CBES_EX_TEXTENDELLIPSIS = 0x00000020, } /// Contains combo box status information. [PInvokeData("Winuser.h", MSDNShortId = "bb775798")] [StructLayout(LayoutKind.Sequential)] public struct COMBOBOXINFO { /// The size, in bytes, of the structure. The calling application must set this to sizeof(COMBOBOXINFO). public int cbSize; /// A RECT structure that specifies the coordinates of the edit box. public RECT rcItem; /// A RECT structure that specifies the coordinates of the button that contains the drop-down arrow. public RECT rcButton; /// The combo box button state. public ComboBoxInfoState buttonState; /// A handle to the combo box. public HWND hwndCombo; /// A handle to the edit box. public HWND hwndEdit; /// A handle to the drop-down list. public HWND hwndList; /// Creates an instance of the structure from a handle and retrieves its values. /// The handle to a ComboBox. /// A structure with values from the supplied handle. public static COMBOBOXINFO FromHandle(HWND hComboBox) { if (hComboBox.IsNull) throw new ArgumentException("ComboBox handle cannot be NULL.", nameof(hComboBox)); var cbi = new COMBOBOXINFO() { cbSize = Marshal.SizeOf(typeof(COMBOBOXINFO)) }; SendMessage(hComboBox, ComboBoxMessage.CB_GETCOMBOBOXINFO, 0, ref cbi); return cbi; } /// Gets a value indicating whether this is invisible. /// true if invisible; otherwise, false. public bool Invisible => (buttonState & ComboBoxInfoState.STATE_SYSTEM_INVISIBLE) == ComboBoxInfoState.STATE_SYSTEM_INVISIBLE; /// Gets a value indicating whether this is pressed. /// true if pressed; otherwise, false. public bool Pressed => (buttonState & ComboBoxInfoState.STATE_SYSTEM_PRESSED) == ComboBoxInfoState.STATE_SYSTEM_PRESSED; /// Gets the item rectangle. /// The item rectangle. public RECT ItemRectangle => rcItem; /// Gets the button rectangle. /// The button rectangle. public RECT ButtonRectangle => rcButton; } /// Contains information used with the CBEN_DRAGBEGIN notification code. [PInvokeData("Commctrl.h", MSDNShortId = "bb775748")] [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct NMCBEDRAGBEGIN { /// The NMHDR structure that contains information about the notification code. public NMHDR hdr; /// /// The zero-based index of the item being dragged. This value will always be -1, indicating that the item being dragged is the /// item displayed in the edit portion of the control. /// public int iItemId; /// The character buffer that contains the text of the item being dragged. public string szText; } /// /// Contains information about the conclusion of an edit operation within a ComboBoxEx control. This structure is used with the /// CBEN_ENDEDIT notification code. /// [PInvokeData("Commctrl.h", MSDNShortId = "bb775750")] [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct NMCBEENDEDIT { /// The NMHDR structure that contains information about the notification code. public NMHDR hdr; /// /// A value indicating whether the contents of the control's edit box have changed. This value is nonzero if the contents have /// been modified, or zero otherwise. /// [MarshalAs(UnmanagedType.Bool)] public bool fChanged; /// /// The zero-based index of the item that will be selected after completing the edit operation. This value can be CB_ERR if no /// item will be selected. /// public int iNewSelection; /// A zero-terminated string that contains the text from within the control's edit box. public string szText; /// A value that specifies the action that generated the CBEN_ENDEDIT notification code. public CBEN_ENDEDIT_FLAG iWhy; } /// Contains information specific to ComboBoxEx items for use with notification codes. [PInvokeData("Commctrl.h", MSDNShortId = "bb775752")] [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct NMCOMBOBOXEX { /// The NMHDR structure that contains information about the notification code. public NMHDR hdr; /// /// The COMBOBOXEXITEM structure that holds item information specific to the current notification. Upon receiving a notification /// code, the COMBOBOXEXITEM structure holds information required for the owner to respond. The members of this structure are /// often used as fields for the owner to return values in response to the notification. /// public COMBOBOXEXITEM ceItem; } /// Contains information about an item in a ComboBoxEx control. /// [PInvokeData("Commctrl.h", MSDNShortId = "bb775746")] [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] public sealed class COMBOBOXEXITEM : IDisposable { /// /// A set of bit flags that specify attributes of this structure or of an operation that is using this structure. The flags /// specify members that are valid or must be filled in. /// public ComboBoxExItemMask mask; /// The zero-based index of the item. [MarshalAs(UnmanagedType.SysInt)] public int iItem; /// /// A pointer to a character buffer that contains or receives the item's text. If text information is being retrieved, this /// member must be set to the address of a character buffer that will receive the text. The size of this buffer must also be /// indicated in cchTextMax. If this member is set to LPSTR_TEXTCALLBACK, the control will request the information by using the /// CBEN_GETDISPINFO notification codes. /// public IntPtr pszText; /// The length of pszText, in TCHARs. If text information is being set, this member is ignored. public int cchTextMax; /// /// The zero-based index of an image within the image list. The specified image will be displayed for the item when it is not /// selected. If this member is set to I_IMAGECALLBACK, the control will request the information by using CBEN_GETDISPINFO /// notification codes. /// public int iImage; /// /// The zero-based index of an image within the image list. The specified image will be displayed for the item when it is /// selected. If this member is set to I_IMAGECALLBACK, the control will request the information by using CBEN_GETDISPINFO /// notification codes. /// public int iSelectedImage; /// /// The one-based index of an overlay image within the image list. If this member is set to I_IMAGECALLBACK, the control will /// request the information by using CBEN_GETDISPINFO notification codes. /// public int iOverlay; /// /// The number of indent spaces to display for the item. Each indentation equals 10 pixels. If this member is set to /// I_INDENTCALLBACK, the control will request the information by using CBEN_GETDISPINFO notification codes. /// public int iIndent; /// A value specific to the item. public IntPtr lParam; /// Initializes a new instance of the class. /// Size of the text buffer. If this value is 0, no buffer is created. public COMBOBOXEXITEM(int textBufferSize = 0) : this(textBufferSize == 0 ? null : new string('\0', textBufferSize)) { } /// Initializes a new instance of the class. /// The text. public COMBOBOXEXITEM(string text) => Text = text; /// Gets or sets the item's text. /// The text value. public string Text { get => pszText == LPSTR_TEXTCALLBACK ? null : Marshal.PtrToStringAuto(pszText); set { ((IDisposable)this).Dispose(); if (value == null) return; pszText = Marshal.StringToCoTaskMemAuto(value); cchTextMax = value.Length; mask |= ComboBoxExItemMask.CBEIF_TEXT; } } /// Gets or sets a value indicating whether to use a text callback method. /// true if using text callback method; otherwise, false. public bool UseTextCallback { get => pszText == LPSTR_TEXTCALLBACK; set { if (value) { ((IDisposable)this).Dispose(); pszText = LPSTR_TEXTCALLBACK; } mask |= ComboBoxExItemMask.CBEIF_TEXT; } } /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. void IDisposable.Dispose() { if (pszText != IntPtr.Zero && pszText != LPSTR_TEXTCALLBACK) { Marshal.FreeCoTaskMem(pszText); pszText = IntPtr.Zero; cchTextMax = 0; } } } } }