Mega Code Archive

 
Categories / Delphi / VCL
 

Fill In Combo Box (Component)

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