SuggestText.cs 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. using System;
  2. using System.Drawing;
  3. using System.Windows.Forms;
  4. namespace Core.StlMes.Client.Mcp.Mch.Mcms
  5. {
  6. public partial class SuggestText : ComboBox, IMessageFilter
  7. {
  8. private System.Windows.Forms.Control ComboParentForm; // Or use type "Form"
  9. private int IgnoreTextChange;
  10. private ListBox listBoxChild;
  11. private bool MsgFilterActive;
  12. public SuggestText()
  13. {
  14. // Set up all the events we need to handle
  15. TextChanged += ComboListMatcher_TextChanged;
  16. SelectionChangeCommitted += ComboListMatcher_SelectionChangeCommitted;
  17. LostFocus += ComboListMatcher_LostFocus;
  18. MouseDown += ComboListMatcher_MouseDown;
  19. HandleDestroyed += ComboListMatcher_HandleDestroyed;
  20. }
  21. public bool PreFilterMessage(ref Message m)
  22. {
  23. if (m.Msg == 0x201) // Mouse click: WM_LBUTTONDOWN
  24. {
  25. var Pos = new Point(m.LParam.ToInt32() & 0xFFFF, m.LParam.ToInt32() >> 16);
  26. var Ctrl = FromHandle(m.HWnd);
  27. if (Ctrl != null)
  28. {
  29. // Convert the point into our parent control's coordinates ...
  30. Pos = ComboParentForm.PointToClient(Ctrl.PointToScreen(Pos));
  31. // ... because we need to hide the list if user clicks on something other than the list-box
  32. if (ComboParentForm != null)
  33. if ((listBoxChild != null) &&
  34. ((Pos.X < listBoxChild.Left) || (Pos.X > listBoxChild.Right) || (Pos.Y < listBoxChild.Top) ||
  35. (Pos.Y > listBoxChild.Bottom)))
  36. HideTheList();
  37. }
  38. }
  39. else if (m.Msg == 0x100) // WM_KEYDOWN
  40. {
  41. if ((listBoxChild != null) && listBoxChild.Visible)
  42. switch (m.WParam.ToInt32())
  43. {
  44. case 0x1B: // Escape key
  45. HideTheList();
  46. return true;
  47. case 0x26: // up key
  48. case 0x28: // right key
  49. // Change selection
  50. var NewIx = listBoxChild.SelectedIndex + (m.WParam.ToInt32() == 0x26 ? -1 : 1);
  51. // Keep the index valid!
  52. if ((NewIx >= 0) && (NewIx < listBoxChild.Items.Count))
  53. listBoxChild.SelectedIndex = NewIx;
  54. return true;
  55. case 0x0D: // return (use the currently selected item)
  56. CopySelection();
  57. return true;
  58. }
  59. }
  60. return false;
  61. }
  62. private void ComboListMatcher_HandleDestroyed(object sender, EventArgs e)
  63. {
  64. if (MsgFilterActive)
  65. Application.RemoveMessageFilter(this);
  66. }
  67. ~SuggestText()
  68. {
  69. }
  70. private void ComboListMatcher_MouseDown(object sender, MouseEventArgs e)
  71. {
  72. HideTheList();
  73. }
  74. private void ComboListMatcher_LostFocus(object sender, EventArgs e)
  75. {
  76. if ((listBoxChild != null) && !listBoxChild.Focused)
  77. HideTheList();
  78. }
  79. private void ComboListMatcher_SelectionChangeCommitted(object sender, EventArgs e)
  80. {
  81. IgnoreTextChange++;
  82. }
  83. private void InitListControl()
  84. {
  85. if (listBoxChild == null)
  86. {
  87. // Find parent - or keep going up until you find the parent form
  88. ComboParentForm = Parent;
  89. if (ComboParentForm != null)
  90. {
  91. // Setup a messaage filter so we can listen to the keyboard
  92. if (!MsgFilterActive)
  93. {
  94. Application.AddMessageFilter(this);
  95. MsgFilterActive = true;
  96. }
  97. listBoxChild = listBoxChild = new ListBox();
  98. listBoxChild.Visible = false;
  99. listBoxChild.Click += listBox1_Click;
  100. ComboParentForm.Controls.Add(listBoxChild);
  101. ComboParentForm.Controls.SetChildIndex(listBoxChild, 0); // Put it at the front
  102. }
  103. }
  104. }
  105. private void ComboListMatcher_TextChanged(object sender, EventArgs e)
  106. {
  107. if (IgnoreTextChange > 0)
  108. {
  109. IgnoreTextChange = 0;
  110. return;
  111. }
  112. InitListControl();
  113. if (listBoxChild == null)
  114. return;
  115. var SearchText = Text.Trim();
  116. listBoxChild.Items.Clear();
  117. // Don't show the list when nothing has been typed
  118. if (!string.IsNullOrWhiteSpace(SearchText))
  119. foreach (string Item in Items)
  120. if ((Item != null) && Item.Contains(SearchText))
  121. listBoxChild.Items.Add(Item);
  122. if (listBoxChild.Items.Count > 0)
  123. {
  124. var PutItHere = new Point(Left, Bottom);
  125. System.Windows.Forms.Control TheControlToMove = this;
  126. PutItHere = Parent.PointToScreen(PutItHere);
  127. TheControlToMove = listBoxChild;
  128. PutItHere = ComboParentForm.PointToClient(PutItHere);
  129. TheControlToMove.Show();
  130. TheControlToMove.Left = PutItHere.X;
  131. TheControlToMove.Top = PutItHere.Y;
  132. TheControlToMove.Width = Width;
  133. var TotalItemHeight = listBoxChild.ItemHeight*(listBoxChild.Items.Count + 1);
  134. TheControlToMove.Height = TotalItemHeight;
  135. TheControlToMove.BringToFront();
  136. }
  137. else
  138. HideTheList();
  139. }
  140. /// <summary>
  141. /// Copy the selection from the list-box into the combo box
  142. /// </summary>
  143. private void CopySelection()
  144. {
  145. if (listBoxChild.SelectedItem != null)
  146. {
  147. SelectedItem = listBoxChild.SelectedItem;
  148. HideTheList();
  149. SelectAll();
  150. }
  151. }
  152. private void listBox1_Click(object sender, EventArgs e)
  153. {
  154. var ThisList = sender as ListBox;
  155. if (ThisList != null)
  156. CopySelection();
  157. }
  158. private void HideTheList()
  159. {
  160. if (listBoxChild != null)
  161. listBoxChild.Hide();
  162. }
  163. }
  164. }