Author: Tomas Rutkauskas
How to add text completion capability to a TComboBox
Answer:
Solve 1:
The Netscape Communicator location box, The Windows 98 'Run' dialog, and other
programs, have implemented a very user friendly feature known commonly as text
completion. This document describes how to add similar functionality to a
TComboBox. The most elegant and reusable way to add this functionality is by
descending from TComboBox and overriding the ComboWndProc to handle the WM_KEYUP
message. By adding a new property 'TextCompletion', the functionality can be
toggled to act like a regular TComboBox. Below is the component unit that
implements text completion in a TComboBox. This unit can be installed as is.
1 unit CompletingComboBox;
2
3 interface
4
5 uses
6 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
7 StdCtrls;
8
9 type
10 TCompletingComboBox = class(TComboBox)
11 private
12 FTextCompletion: Boolean;
13 function GetTextCompletion: Boolean;
14 procedure SetTextCompletion(const Value: Boolean);
15 protected
16 {override the WndProc() so that we can trap KeyUp events}
17 procedure ComboWndProc(var message: TMessage; ComboWnd: HWnd;
18 ComboProc: Pointer); override;
19 public
20 {Public declarations}
21 published
22 property TextCompletion: Boolean read GetTextCompletion write SetTextCompletion;
23 end;
24
25 procedure register;
26
27 implementation
28
29 procedure register;
30 begin
31 RegisterComponents('Standard', [TCompletingComboBox]);
32 end;
33
34 {TCompletingComboBox}
35
36 function TCompletingComboBox.GetTextCompletion: Boolean;
37 begin
38 Result := fTextCompletion;
39 end;
40
41 procedure TCompletingComboBox.SetTextCompletion(const Value: Boolean);
42 begin
43 fTextCompletion := Value;
44 end;
45
46 procedure TCompletingComboBox.ComboWndProc(var message: TMessage;
47 ComboWnd: HWnd; ComboProc: Pointer);
48 var
49 rc, len: Integer;
50 begin
51 inherited;
52 case message.Msg of
53 WM_KEYUP:
54 begin
55 {test to see if its a character that should not be processed}
56 if (message.WParam <> 8) and (message.WParam <> VK_DELETE) and
57 (message.WParam <> VK_SHIFT) and (FTextCompletion = True) then
58 begin
59 {Use CB_FINDSTRING to locate the string in the Items property}
60 rc := Perform(CB_FINDSTRING, -1, Integer(PChar(Caption)));
61 {if its in there then add the new string to the Text and select the
62 portion that wasn't typed in by the user}
63 if rc <> CB_ERR then
64 begin
65 {store the length of the current string}
66 len := Length(Text);
67 {set the new string}
68 ItemIndex := rc;
69 {highlight the rest of the text that was added}
70 SelStart := len;
71 SelLength := Length(Text) - len;
72 {return 0 to signify that the message has been handled}
73 message.Result := 0;
74 end;
75 end;
76 end;
77 end;
78 end;
end.
Solve 2:
Performing autocompletion in a combobox:
79
80 procedure TForm1.ComboBox1Change(Sender: TObject);
81 var
82 oldpos: Integer;
83 item: Integer;
84 begin
85 with Sender as TComboBox do
86 begin
87 oldpos := selstart;
88 item := Perform(CB_FINDSTRING, -1, lparam(Pchar(text)));
89 if item >= 0 then
90 begin
91 onchange := nil;
92 text := items[item];
93 selstart := oldpos;
94 sellength := gettextlen - selstart;
95 onchange := combobox1change;
96 end;
97 end;
98 end;
99
100 procedure TForm1.ComboBox1KeyPress(Sender: TObject; var Key: Char);
101 var
102 oldlen: Integer;
103 begin
104 if key = #8 then
105 with sender as TComboBox do
106 begin
107 oldlen := sellength;
108 if selstart > 0 then
109 begin
110 selstart := selstart - 1;
111 sellength := oldlen + 1;
112 end;
113 end;
114 end;
|