Mega Code Archive

 
Categories / Delphi / VCL
 

Lookup ComboBox Component

Title: Lookup ComboBox Component Question: ** UPDATED ** Feb 2006 1) Fixed ItemIndex now works 2) DropDownWidth Property Added 3) Sorted property changed to Rutime method Sort I recently had a requirement for a TComboLookUp. This is similar in functionality to the Delphi TDBLookupComboBox whereby the drop down list displays lookup fields and the edit box is populated by a different value. The requirement I had was to have a combobox that allowed a user to type in an E-Mail address, but the dropdown box must display peoples names (more meaningfull than a dropdown box of E-Mail addresses), and populate the combo box's edit field with the corresponding E-Mail address. The solution was relatively simple in that a new component TComboLookUp was created as a descendant of TCustomComboBox. All that was required was to override a few virtual methods and switch the contents of the (now hidden) Items property with either ItemsLookUp or ItemsDisplay properties. TComboLookUp introduces 3 new properties ItemsLookUp : TStringList - List of names for Dropdown Box ItemsDisplay : TStringList - Corresponding name to put into edit box portion. DropDownWidth - Width of drop down box (it can now be wider than the text box). If it is 0 then DropDownWidth = Width Obviously both of these lists must contain the same number of lines, if this is not so then an Exception will be raised at runtime. Answer: unit ComboLookUp; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TComboLookUp = class(TCustomComboBox) private { Private declarations } FItemIndex : integer; FSaveWidth, FDropDownWidth : integer; FSortList, FLookUpList, FDisplayList : TStringList; procedure SetFLookUpList(NewValue : TStringList); procedure SetFDisplayList(NewValue : TStringList); protected { Protected declarations } procedure AdjustDropdown; override; procedure DropDown; override; procedure CloseUp; override; procedure DoExit; override; procedure SetList(TS : TStringList); virtual; procedure CheckListLens; virtual; function GetItemIndex: Integer; override; procedure SetItemIndex(const Value: Integer); override; public { Public declarations } constructor Create(AOwner : TComponent); override; destructor Destroy; override; procedure Loaded; override; procedure Sort; published { Published new declarations } property ItemsLookUp : TstringList read FLookUpList write SetFLookUpList; property ItemsDisplay : TstringList read FDisplayList write SetFDisplayList; property DropDownWidth : integer read FDropDownWidth write FDropDownWidth; { Surface hidden properties } property Anchors; property Color; property Constraints; property DragCursor; property DragKind; property DragMode; property DropDownCount; property Enabled; property Font; property ItemHeight; property MaxLength; property ParentColor; property ParentFont; property PopupMenu; property ShowHint; property Style; property TabOrder; property Text; property Visible; { Surface hidden events } property OnChange; property OnClick; property OnContextPopup; property OnDblClick; property OnDragDrop; property OnDragOver; property OnDrawItem; property OnDropDown; property OnEndDock; property OnEndDrag; property OnEnter; property OnExit; property OnKeyDown; property OnKeyPress; property OnKeyUp; property OnMeasureItem; property OnStartDock; property OnStartDrag; end; procedure Register; // ------------------------------------------------------------------------------ implementation procedure Register; begin RegisterComponents('MahExtra', [TComboLookUp]); end; // =================================== // Create and Destroy Component // =================================== constructor TComboLookUp.Create(AOwner : TComponent); begin inherited Create(AOwner); FItemIndex := -1; FLookUpList := TStringList.Create; FDisplayList := TStringList.Create; FSortList := TStringList.Create; FDropDownWidth := 0; end; destructor TComboLookUp.Destroy; begin FDisplayList.Free; FLookUpList.Free; FSortList.Free; inherited Destroy; end; // =========================================== // Assign initial items to FLookUpList // =========================================== procedure TComboLookUp.Loaded; begin inherited Loaded; if not (csDesigning in ComponentState) then begin Items.Assign(FLookUpList); if FItemIndex -1 then SetItemIndex(FItemIndex); end; end; // ====================================== // TStringList Set Property Methods // ====================================== procedure TComboLookUp.SetFLookUpList(NewValue : TStringList); begin FLookUpList.Assign(NewValue); end; procedure TComboLookUp.SetFDisplayList(NewValue : TStringList); begin FDisplayList.Assign(NewValue); end; // ====================== // Override events // ====================== procedure TComboLookUp.SetList(TS : TStringList); var i : integer; begin if not (csDesigning in ComponentState) then begin CheckListLens; i := ItemIndex; Items.Assign(TS); ItemIndex := i; end; end; function TComboLookUp.GetItemIndex: Integer; begin if csLoading in ComponentState then Result := FItemIndex else Result := SendMessage(Handle, CB_GETCURSEL, 0, 0); end; procedure TComboLookUp.SetItemIndex(const Value: Integer); begin if Items.Text = '' then Items.Assign(FDisplayList); if csLoading in ComponentState then FItemIndex := Value else if GetItemIndex Value then SendMessage(Handle, CB_SETCURSEL, Value, 0); end; procedure TComboLookUp.AdjustDropdown; var Count: Integer; iWidth : integer; begin if FDropDownWidth iWidth := Width else iWidth := FDropDownWidth; FSaveWidth := Width; Count := ItemCount; if Count DropDownCount then Count := DropDownCount; if Count FDroppingDown := True; try SetWindowPos(FDropHandle, 0, 0, 0, iWidth, ItemHeight * Count + Height + 2, SWP_NOMOVE or SWP_NOZORDER or SWP_NOACTIVATE or SWP_NOREDRAW or SWP_HIDEWINDOW); finally FDroppingDown := False; end; SetWindowPos(FDropHandle, 0, 0, 0, 0 , 0, SWP_NOMOVE or SWP_NOSIZE or SWP_NOZORDER or SWP_NOACTIVATE or SWP_NOREDRAW or SWP_SHOWWINDOW); Invalidate; end; procedure TComboLookUp.DropDown; begin SetList(FLookUpList); inherited DropDown; end; procedure TComboLookUp.CloseUp; begin Width := FSaveWidth; SetList(FDisplayList); inherited CloseUp; end; procedure TComboLookUp.DoExit; begin SetList(FDisplayList); inherited DoExit; end; // ========================================== // Sort lists if property Sorted is set // ========================================== procedure TComboLookUp.CheckListLens; begin if (FLookUpList.Count FDisplayList.Count) then raise Exception.Create(#13#10'TComboLookUp - ' + 'Lookup items Display items'); end; procedure TComboLookUp.Sort; var i,p : integer; begin FSortList.Clear; CheckListLens; for i := 0 to FLookUpList.Count - 1 do FSortList.Add(FLookUpList[i] + #254 + FDisplayList[i]); FSortList.Sort; FLookUpList.Clear; FDisplayList.Clear; for i := 0 to FSortList.Count - 1 do begin p := pos(#254,FSortList[i]); FLookUpList.Add(Copy(FSortList[i],1,P - 1)); FDisplayList.Add(Copy(FSortList[i],p + 1,MAX_PATH)); end; end; end.