using System; using System.Drawing; using System.Windows.Forms; namespace Core.StlMes.Client.Mcp.Mch.Mcms { public partial class SuggestText : ComboBox, IMessageFilter { private System.Windows.Forms.Control ComboParentForm; // Or use type "Form" private int IgnoreTextChange; private ListBox listBoxChild; private bool MsgFilterActive; public SuggestText() { // Set up all the events we need to handle TextChanged += ComboListMatcher_TextChanged; SelectionChangeCommitted += ComboListMatcher_SelectionChangeCommitted; LostFocus += ComboListMatcher_LostFocus; MouseDown += ComboListMatcher_MouseDown; HandleDestroyed += ComboListMatcher_HandleDestroyed; } public bool PreFilterMessage(ref Message m) { if (m.Msg == 0x201) // Mouse click: WM_LBUTTONDOWN { var Pos = new Point(m.LParam.ToInt32() & 0xFFFF, m.LParam.ToInt32() >> 16); var Ctrl = FromHandle(m.HWnd); if (Ctrl != null) { // Convert the point into our parent control's coordinates ... Pos = ComboParentForm.PointToClient(Ctrl.PointToScreen(Pos)); // ... because we need to hide the list if user clicks on something other than the list-box if (ComboParentForm != null) if ((listBoxChild != null) && ((Pos.X < listBoxChild.Left) || (Pos.X > listBoxChild.Right) || (Pos.Y < listBoxChild.Top) || (Pos.Y > listBoxChild.Bottom))) HideTheList(); } } else if (m.Msg == 0x100) // WM_KEYDOWN { if ((listBoxChild != null) && listBoxChild.Visible) switch (m.WParam.ToInt32()) { case 0x1B: // Escape key HideTheList(); return true; case 0x26: // up key case 0x28: // right key // Change selection var NewIx = listBoxChild.SelectedIndex + (m.WParam.ToInt32() == 0x26 ? -1 : 1); // Keep the index valid! if ((NewIx >= 0) && (NewIx < listBoxChild.Items.Count)) listBoxChild.SelectedIndex = NewIx; return true; case 0x0D: // return (use the currently selected item) CopySelection(); return true; } } return false; } private void ComboListMatcher_HandleDestroyed(object sender, EventArgs e) { if (MsgFilterActive) Application.RemoveMessageFilter(this); } ~SuggestText() { } private void ComboListMatcher_MouseDown(object sender, MouseEventArgs e) { HideTheList(); } private void ComboListMatcher_LostFocus(object sender, EventArgs e) { if ((listBoxChild != null) && !listBoxChild.Focused) HideTheList(); } private void ComboListMatcher_SelectionChangeCommitted(object sender, EventArgs e) { IgnoreTextChange++; } private void InitListControl() { if (listBoxChild == null) { // Find parent - or keep going up until you find the parent form ComboParentForm = Parent; if (ComboParentForm != null) { // Setup a messaage filter so we can listen to the keyboard if (!MsgFilterActive) { Application.AddMessageFilter(this); MsgFilterActive = true; } listBoxChild = listBoxChild = new ListBox(); listBoxChild.Visible = false; listBoxChild.Click += listBox1_Click; ComboParentForm.Controls.Add(listBoxChild); ComboParentForm.Controls.SetChildIndex(listBoxChild, 0); // Put it at the front } } } private void ComboListMatcher_TextChanged(object sender, EventArgs e) { if (IgnoreTextChange > 0) { IgnoreTextChange = 0; return; } InitListControl(); if (listBoxChild == null) return; var SearchText = Text.Trim(); listBoxChild.Items.Clear(); // Don't show the list when nothing has been typed if (!string.IsNullOrWhiteSpace(SearchText)) foreach (string Item in Items) if ((Item != null) && Item.Contains(SearchText)) listBoxChild.Items.Add(Item); if (listBoxChild.Items.Count > 0) { var PutItHere = new Point(Left, Bottom); System.Windows.Forms.Control TheControlToMove = this; PutItHere = Parent.PointToScreen(PutItHere); TheControlToMove = listBoxChild; PutItHere = ComboParentForm.PointToClient(PutItHere); TheControlToMove.Show(); TheControlToMove.Left = PutItHere.X; TheControlToMove.Top = PutItHere.Y; TheControlToMove.Width = Width; var TotalItemHeight = listBoxChild.ItemHeight*(listBoxChild.Items.Count + 1); TheControlToMove.Height = TotalItemHeight; TheControlToMove.BringToFront(); } else HideTheList(); } /// /// Copy the selection from the list-box into the combo box /// private void CopySelection() { if (listBoxChild.SelectedItem != null) { SelectedItem = listBoxChild.SelectedItem; HideTheList(); SelectAll(); } } private void listBox1_Click(object sender, EventArgs e) { var ThisList = sender as ListBox; if (ThisList != null) CopySelection(); } private void HideTheList() { if (listBoxChild != null) listBoxChild.Hide(); } } }