OSDN Git Service

v2.6.0.0 draft
[passer/Passer2.git] / components / AutoCompleteTextBox.cs
1 /**
2  * $Revision: 12 $
3  * $Date: 2006-08-17 16:26:11 +0900 (木, 17 8 2006) $
4 */
5
6 using System;
7 using System.Collections.Generic;
8 using System.ComponentModel;
9 using System.Drawing;
10 using System.Data;
11 using System.Text;
12 using System.Windows.Forms;
13 using System.Runtime.InteropServices;
14 using System.Diagnostics;
15 using Lugens.Utils;
16 using System.IO;
17
18 namespace Lugens.Components
19 {
20     public partial class AutoCompleteTextBox : TextBox, IComparer<IconListBoxItem>
21     {
22         [DllImport("Imm32.dll")]
23         private static extern IntPtr ImmGetContext(IntPtr hWnd);
24
25         [DllImport("Imm32.dll")]
26         private static extern int ImmGetCompositionString(
27             IntPtr hIMC, int dwIndex, byte[] buf, int dwBufLen);
28
29         [DllImport("Imm32.dll")]
30         private static extern bool ImmReleaseContext(IntPtr hWnd, IntPtr hIMC);
31
32         // IME入力中文字取得に使用する値(ひらがな)
33         private const int GCS_COMPSTR = 0x0008;
34
35         /// <summary>
36         /// オートコンプリートドロップダウンリスト表示の最大件数
37         /// </summary>
38         private int maxDropdownCount = 3;
39         /// <summary>
40         /// オートコンプリートドロップダウンリスト表示の最大件数
41         /// </summary>
42         public int MaxDropdownCount { get { return this.maxDropdownCount; } set { this.maxDropdownCount = value; } }
43
44         /// <summary>
45         /// オートコンプリートドロップダウンリストのアイテム
46         /// </summary>
47         private List<IconListBoxItem> items = new List<IconListBoxItem>();
48         public List<IconListBoxItem> Items { get { return this.items; } }
49         
50         private DropdownListForm dropdownForm = new DropdownListForm();
51         public DropdownListForm DropdownForm { get { return this.dropdownForm; } }
52
53         private bool showableDropdownList = true;
54         public bool ShowableDropdownList { get { return this.showableDropdownList; } set { this.showableDropdownList = value; } }
55
56         /// <summary>
57         /// タブ補完時のイベントハンドラ
58         /// </summary>
59         /// <param name="type"></param>
60         public delegate void ComplementEventHandler(IconListBoxType type);
61         public event ComplementEventHandler Complement;
62
63         /// <summary>
64         /// IME変換時のイベントハンドラ
65         /// </summary>
66         /// <param name="type"></param>
67         public delegate void ImeCompositionEventHandler(int type, string text);
68         public event ImeCompositionEventHandler ImeComposition;
69
70         private bool complemented = false;
71         public bool Complemented
72         {
73             get { return complemented; }
74             set { complemented = value; }
75         }
76
77         private string imeText;
78         public string ImeText
79         {
80             get { return imeText; }
81             set { imeText = value; }
82         }
83
84         protected override void Dispose(bool disposing)
85         {
86             base.Dispose(disposing);
87         }
88
89         #region コンポーネント デザイナで生成されたコード
90
91         /// <summary>
92         /// デザイナ サポートに必要なメソッドです。このメソッドの内容を 
93         /// コード エディタで変更しないでください。
94         /// </summary>
95         private void InitializeComponent()
96         {
97             this.SuspendLayout();
98             // 
99             // AutoCompleteTextBox
100             // 
101             this.SizeChanged += new System.EventHandler(this.AutoCompleteTextBox_SizeChanged);
102             this.ResumeLayout(false);
103
104         }
105
106         #endregion
107
108         public AutoCompleteTextBox() : base()
109         {
110             InitializeComponent();
111             dropdownForm.ParentTextBox = this;
112             dropdownForm.SetBounds(-1, -1, 1, 1);
113         }
114
115         protected override void OnTextChanged(EventArgs e)
116         {
117             base.OnTextChanged(e);
118         }
119
120         protected override void OnKeyDown(KeyEventArgs e)
121         {
122             if (e.Handled)
123                 return;
124
125             Size t = TextRenderer.MeasureText(this.Text, this.Font);
126             int index;
127             IconListBox listBox = this.dropdownForm.DropdownListBox;
128             switch (e.KeyCode)
129             {
130                 case Keys.Tab:
131                     if (this.dropdownForm.Visible && this.dropdownForm.DropdownListBox.SelectedIndex >= 0)
132                     {
133                         //タブキーによるコマンド補完
134                         this.complemented = true;
135                         IconListBoxItem item = (IconListBoxItem)this.dropdownForm.DropdownListBox.SelectedItem;
136                         switch (item.Type)
137                         {
138                             case IconListBoxType.Directory:
139                             case IconListBoxType.Command:
140                             case IconListBoxType.File:
141                             case IconListBoxType.History:
142                             case IconListBoxType.SysCommand:
143                             case IconListBoxType.SearchEngine:
144                                 this.Text = item.Text;
145                                 this.SelectionStart = this.Text.Length;
146                                 this.dropdownForm.DoVisibleChange(false);
147                                 this.Complement(item.Type);
148                                 break;
149                         }
150                         //e.Handled = true;
151                     }
152                     break;
153
154                 case Keys.A:
155                     if ((Keys.Control & Control.ModifierKeys) == Keys.Control || Keys.Home == e.KeyCode)
156                     {
157                         this.SelectAll();
158                         e.Handled = true;
159                     }
160                     break;
161
162                 case Keys.Up:
163                     if (listBox.Items.Count > 0)
164                     {
165                         if ((Keys.Control & Control.ModifierKeys) == Keys.Control || Keys.Home == e.KeyCode)
166                             index = 0;
167                         else
168                             index = listBox.SelectedIndex - 1;
169                         index = Math.Max(index, 0);
170                         listBox.SelectedIndex = Math.Max(index, 0);
171                     }
172                     e.Handled = true;
173                     break;
174                 case Keys.Down:
175                     if (listBox.Items.Count > 0)
176                     {
177                         if ((Control.ModifierKeys & Keys.Control) == Keys.Control || Keys.End == e.KeyCode)
178                             index = listBox.Items.Count - 1;
179                         else
180                             index = listBox.SelectedIndex + 1;
181                         listBox.SelectedIndex = Math.Min(index, listBox.Items.Count - 1);
182                     }
183                     e.Handled = true;
184                     break;
185                 case Keys.PageUp:
186                     if (this.dropdownForm.Visible)
187                     {
188                         index = listBox.SelectedIndex - maxDropdownCount + 1;
189                         if (index < 0)
190                             index = 0;
191                         listBox.SelectedIndex = index;
192                     }
193                     break;
194
195                 case Keys.PageDown:
196                     if (this.dropdownForm.Visible)
197                     {
198                         index = listBox.SelectedIndex + maxDropdownCount - 1;
199                         if (index > listBox.Items.Count - 1)
200                             index = listBox.Items.Count - 1;
201                         listBox.SelectedIndex = index;
202                     }
203                     break;
204
205                 case Keys.Home:
206                     if (this.dropdownForm.Visible)
207                     {
208                         if (Keys.Control == (Keys.Control & Control.ModifierKeys))
209                         {
210                             listBox.SelectedIndex = 0;
211                             e.Handled = true;
212                         }
213                     }
214                     break;
215
216                 case Keys.End:
217                     if (this.dropdownForm.Visible)
218                     {
219                         if (Keys.Control == (Keys.Control & Control.ModifierKeys))
220                         {
221                             listBox.SelectedIndex = listBox.Items.Count - 1;
222                             e.Handled = true;
223                         }
224                     }
225                     break;
226             }
227             base.OnKeyDown(e);
228         }
229
230         protected override void OnKeyPress(KeyPressEventArgs e)
231         {
232             switch ((Keys)e.KeyChar)
233             {
234                 case Keys.Enter:
235                     if (this.dropdownForm.Visible)
236                     {
237                         if (this.dropdownForm.DropdownListBox.SelectedIndex >= 0)
238                         {
239                             this.Text = this.dropdownForm.DropdownListBox.Text;
240                             this.SelectionStart = this.Text.Length;
241                         }
242                         this.dropdownForm.DoVisibleChange(false);
243                     }
244                     break;
245
246 /*                case Keys.Tab:
247
248                     if (this.dropdownForm.Visible)
249                     {
250                         //タブキーによるコマンド補完
251                         this.complemented = true;
252                         IconListViewItem item = (IconListViewItem)this.dropdownForm.DropdownListView.SelectedItems[0];
253                         switch (item.Type)
254                         {
255                             case IconListViewType.Directory:
256                             case IconListViewType.Command:
257                             case IconListViewType.File:
258                             case IconListViewType.SysCommand:
259                                 this.Text = item.Text;
260                                 this.SelectionStart = this.Text.Length;
261                                 this.dropdownForm.DoVisibleChange(false);
262                                 this.Complement(item.Type);
263                                 break;
264                         }
265                         e.Handled = true;
266                     }
267                     break;
268 */
269                 case Keys.F16:
270                     int si;
271                     int i;
272
273                     si = this.SelectionStart;
274                     if (si > 0)
275                     {
276                         i = si - 2;
277                         while (i > 0)
278                         {
279                             char c = this.Text[i];
280                             if (c == '\\' || c == ' ')
281                             {
282                                 i++;
283                                 break;
284                             }
285                             i--;
286                         }
287                         if (this.Text.Length == si)
288                             this.Text = this.Text.Substring(0, i);
289                         else
290                             this.Text = this.Text.Substring(0, i) + this.Text.Substring(si);
291                         this.SelectionStart = i;
292                     }
293                     e.Handled = true;
294                     break;
295             }
296             base.OnKeyPress(e);
297             this.complemented = false;
298         }
299
300         /// <summary>
301         /// 
302         /// </summary>
303         /// <param name="keyData"></param>
304         /// <returns></returns>
305         protected override bool IsInputKey(Keys keyData)
306         {
307             switch (keyData)
308             {
309                 case Keys.Enter:
310                 case Keys.Escape:
311                 case Keys.Space:
312                 case Keys.Tab:
313                     return true;
314             }
315             return base.IsInputKey(keyData);
316         }
317
318         public void SetDropdownFormLocation()
319         {
320             if (this.Parent == null || this.Parent.Parent == null)
321                 return;
322             int count = Math.Min(this.maxDropdownCount, this.dropdownForm.DropdownListBox.Items.Count);
323             Rectangle r = this.Parent.Parent.RectangleToScreen(this.Parent.Bounds);
324             r.Height += r.Y - 1;
325             r.Y++;
326             Size size = new Size(this.Parent.Width, this.dropdownForm.DropdownListBox.ItemHeight + 4 + ((count - 1) * this.dropdownForm.DropdownListBox.ItemHeight));
327             this.dropdownForm.Size = size;
328             this.dropdownForm.Location = Util.CalcWindowLocate(r, size, Util.Locate.Down);
329 /*
330             if (this.Parent == null)
331                 return;
332             int count = Math.Min(this.maxDropdownCount, this.dropdownForm.DropdownListBox.Items.Count);
333             Rectangle r = this.Parent.RectangleToScreen(this.Bounds);
334             r.Height += r.Y - 1;
335             r.Y++;
336             Size size = new Size(this.Width, this.dropdownForm.DropdownListBox.ItemHeight + 4 + ((count - 1) * this.dropdownForm.DropdownListBox.ItemHeight));
337             this.dropdownForm.Size = size;
338             this.dropdownForm.Location = Util.CalcWindowLocate(r, size, Util.Locate.Down);*/
339         }
340
341         public void SortItems()
342         {
343             this.items.Sort(this);
344         }
345
346         public int Compare(IconListBoxItem item1, IconListBoxItem item2)
347         {
348             return item1.Text.CompareTo(item2.Text);
349         }
350
351         private void AutoCompleteTextBox_SizeChanged(object sender, EventArgs e)
352         {
353             this.SetDropdownFormLocation();
354         }
355
356         protected override void WndProc(ref Message m)
357         {
358             switch (m.Msg)
359             {
360                 case 0x010F: //WM_IME_COMPOSITION
361                     //if (((int)m.LParam & GCS_COMPSTR) == GCS_COMPSTR)
362                     //{
363                         IntPtr hIMC = ImmGetContext(this.Handle);
364                         StringBuilder sb = new StringBuilder(1024);
365                         byte[] buffer = new byte[1024];
366                         int length = ImmGetCompositionString(hIMC, GCS_COMPSTR, buffer, 1024);
367                         ImmReleaseContext(this.Handle, hIMC);
368                         string str = Encoding.GetEncoding("Shift_JIS").GetString(buffer);
369                         str = str.TrimEnd('\0');
370                         this.ImeComposition((int)m.LParam, str);
371                     //}
372                     break;
373             }
374             base.WndProc(ref m);
375         }
376
377     }
378 }