Author: Daniel Wischnewski
In the following article I am going to give you a simple, enhanced combo box, that
fills in the text area with possible options from the items list. Simple, but
useful.
Note: Delphi 6 does this by default, already
Answer:
INTRODUCTION
In this article I show you how to enhance an already existing component, easily.
Because of the nature of this article you should be familar with Delphi already,
however, no deep knowledge is needed.
Developing a component is, thanks to Delphi, a rather simple task. You do not have
to start from scratch everytime you want to enhance something, already existing.
You can simple create a new class and derive it from the one you want to enhance.
GETTING STARTED
In our case we are going to enhance the TComboBox component, directly. We could
choose the TCustomComboBox, however, they have different published properties from
one Delphi version to another, therefore that want make much sense.
Delphi makes the simple task of creating a new component even more simple by
offering a small wizard. From the Menu File | New... select the Component right
from the first tab "New."
A simple wizard will show. Fill in accordingly:
Ancestor Type: TComboBox
Class Name: TFillComboBox
Palette Page: Samples (or any you want, i took "Standard")
Unit File Name: Select a folder and file to save your work
Press OK, we will install it at a later time.
The wizard will create a basic component for you, inlcuding the installation
routine shown below.
1 procedure register;
2 begin
3 RegisterComponents('Standard', [TFillComboBox]);
4 end;
This routine will be called by Delphi when you select install on your component
package including this file. The first parameter of RegisterComponents names the
palette page, where the components are installed, the second is an array of the
components to be installed.
ADDING A NEW PROPERTY
To our new component we add a new property, called AutomaticFillin. When set to
True we will search for a item matching the user input and add the remainder to the
text box, otherwise we wont.
Therefore we have to declare one private variable that will save the value of the
switch. By puting a property into the published part of the class declaration we
allow the Delphi developer to change its value in the Object Inspector.
5 private
6 FAutomaticFillin: Boolean;
7
8 procedure SetAutomaticFillin(const Value: Boolean);
9 published
10 property AutomaticFillin: Boolean
11 read FAutomaticFillin
12 write SetAutomaticFillin
13 default True;
14
15 procedure TFillComboBox.SetAutomaticFillin(const Value: Boolean);
16 begin
17 FAutomaticFillin := Value;
18 end;
THE PROCESSING OF THE USER CHANGES
In order to become notified when the user changes the text field, we have to
override the default message handler for the combo box.
19 protected
20
21 procedure ComboWndProc(
22 var message: TMessage; ComboWnd: HWnd; ComboProc: Pointer
23 ); override;
In our implementation, we check first whether the special handling is turned on. If
it is turned on, we will get the current text, the user has typed, and then search
for it in the items list. If we have a match, we will replace the text with the
matching item and select the part added by our function.
THE CODE
If your have followed the directions from the "GETTING STARTED" section, simply
replace the unit code with the following code and save your file.
24 unit FillComboBox;
25
26 interface
27
28 uses
29 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
30 StdCtrls;
31
32 type
33 TFillComboBox = class(TComboBox)
34 private
35 FAutomaticFillin: Boolean;
36 procedure SetAutomaticFillin(const Value: Boolean);
37 protected
38 procedure ComboWndProc(
39 var message: TMessage; ComboWnd: HWnd; ComboProc: Pointer
40 ); override;
41 public
42 published
43 constructor Create(AOwner: TComponent); override;
44 property AutomaticFillin: Boolean
45 read FAutomaticFillin
46 write SetAutomaticFillin
47 default True;
48 end;
49
50 procedure register;
51
52 implementation
53
54 procedure register;
55 begin
56 RegisterComponents('Standard', [TFillComboBox]);
57 end;
58
59 { TFillComboBox }
60
61 procedure TFillComboBox.ComboWndProc(
62 var message: TMessage; ComboWnd: HWnd; ComboProc: Pointer
63 );
64 var
65 I: Integer;
66 CurrentText: string;
67 begin
68 inherited ComboWndProc(message, ComboWnd, ComboProc);
69 // skip processing, if turned off
70 if not FAutomaticFillin then
71 Exit;
72 // first check whether the backspace key was pressed, we do not fill in
73 // in such case!
74 if message.Msg = WM_CHAR then
75 begin
76 // all characters from 32 (Space) through 127 (Upper ANSI) are matched
77 if TWMChar(message).CharCode in [$20..$7F] then
78 begin
79 // fill in the rest of the text
80 // save the current text, the user has typed
81 CurrentText := Text;
82 // get the first string, matching the text partially
83 I := SendMessage(Handle, CB_FINDSTRING, -1, LongInt(PChar(CurrentText)));
84 if I >= 0 then
85 begin
86 // match found!
87 // load matching text, I is the position of the matching string
88 Text := Items.Strings[I];
89 // select the text beyond the text typed
90 SelStart := Length(CurrentText);
91 SelLength := Length(Text) - Length(CurrentText);
92 end;
93 end;
94 end;
95 end;
96
97 constructor TFillComboBox.Create(AOwner: TComponent);
98 begin
99 inherited Create(AOwner);
100 FAutomaticFillin := True;
101 end;
102
103 procedure TFillComboBox.SetAutomaticFillin(const Value: Boolean);
104 begin
105 FAutomaticFillin := Value;
106 end;
107
108 end.
INSTALLING THE COMPONENT
The last step is to install the component you have just created. Go to the menu and
select Component | Install Component.... Select your FillComboBox.pas in the "Unit
file name" field and press "OK."
That's all. Now you can create a new application and use the component whenever you feel like.
|