VCL Delphi

Title: Fill In Combo Box (Component)
Question: 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.
procedure Register;
begin
RegisterComponents('Standard', [TFillComboBox]);
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.
private
FAutomaticFillin: Boolean;
procedure SetAutomaticFillin(const Value: Boolean);
published
property AutomaticFillin: Boolean
read FAutomaticFillin
write SetAutomaticFillin
default True;
procedure TFillComboBox.SetAutomaticFillin(const Value: Boolean);
begin
FAutomaticFillin := Value;
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.
protected
procedure ComboWndProc(
var Message: TMessage; ComboWnd: HWnd; ComboProc: Pointer
); 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.
unit FillComboBox;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
type
TFillComboBox = class(TComboBox)
private
FAutomaticFillin: Boolean;
procedure SetAutomaticFillin(const Value: Boolean);
protected
procedure ComboWndProc(
var Message: TMessage; ComboWnd: HWnd; ComboProc: Pointer
); override;
public
published
constructor Create(AOwner: TComponent); override;
property AutomaticFillin: Boolean
read FAutomaticFillin
write SetAutomaticFillin
default True;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Standard', [TFillComboBox]);
end;
{ TFillComboBox }
procedure TFillComboBox.ComboWndProc(
var Message: TMessage; ComboWnd: HWnd; ComboProc: Pointer
);
var
I: Integer;
CurrentText: String;
begin
inherited ComboWndProc(Message, ComboWnd, ComboProc);
// skip processing, if turned off
if not FAutomaticFillin then
Exit;
// first check whether the backspace key was pressed, we do not fill in
// in such case!
if Message.Msg = WM_CHAR then
begin
// all characters from 32 (Space) through 127 (Upper ANSI) are matched
if TWMChar(Message).CharCode in [$20..$7F] then
begin
// fill in the rest of the text
// save the current text, the user has typed
CurrentText := Text;
// get the first string, matching the text partially
I := SendMessage(Handle, CB_FINDSTRING, -1, LongInt(PChar(CurrentText)));
if I = 0 then
begin
// match found!
// load matching text, I is the position of the matching string
Text := Items.Strings[I];
// select the text beyond the text typed
SelStart := Length(CurrentText);
SelLength := Length(Text) - Length(CurrentText);
end;
end;
end;
end;
constructor TFillComboBox.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FAutomaticFillin := True;
end;
procedure TFillComboBox.SetAutomaticFillin(const Value: Boolean);
begin
FAutomaticFillin := Value;
end;
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.
Regards,
Daniel