123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432 |
- unit IEComboBox;
- {==================================================================
- Components TIECustomCombobox / Version 1.4 / January 2000
- TIEComboBox
- TIEDriveBox
- ==================================================================
- Description:
- ============
- TIECustomComboBox is a combobox with variable width of the dropdown list and
- provides the additional event OnCloseUp.
- TIEComboBox publishes the properties of the class TIECustomComboBox including
- the property Align wich might be was forgotten by Borland.
- TIEDriveComboBox realizes a selection control for the aviable drives of
- the system with icons. The drive icons are taken from the system image
- list.
- Author:
- =======
- (c) Ingo Eckel 1999
- Sodener Weg 38
- 65812 Bad Soden
- Germany
- For detailed documentation and history see the documentation in TIEDriveComboBox.htm.
- V1.3:
- - Property DisplayStyle changed.
- {==================================================================}
- {Required compiler options:}
- {$A+,B-,X+,H+,P+}
- interface
- uses
- StdCtrls, Controls, Messages, Types, Classes, Graphics;
- const
- IconWidth = 16;
- type
- TIECloseUpEvent = procedure (Sender: TObject; Canceled: Boolean) of object;
- // =======================================================================
- // Class TIECustomComboBox
- // =======================================================================
- TIECustomComboBox = class(TCustomComboBox)
- private
- FDropDownFixedWidth: Integer;
- FOnCloseUp: TIECloseUpEvent;
- FCanceled: Boolean;
- FUseSystemImageList: Boolean;
- FSystemImageList: TImageList;
- function GetTopIndex: Integer;
- procedure SetTopIndex(Value: Integer);
- procedure SetUseSystemImageList(Value: Boolean);
- procedure CMFontChanged(var Message: TMessage); message CM_FONTCHANGED;
- protected
- procedure DrawItem(Index: Integer; Rect: TRect; State: TOwnerDrawState); override;
- function GetItemImage(Index: Integer): Integer; virtual;
- function GetItemIndent(Index: Integer): Integer; virtual;
- function GetItemText(Index: Integer): string;
- function GetItemTextEx(Index: Integer; ForList: Boolean): string; virtual;
- function ImageList: TImageList; virtual;
- procedure CNCommand(var Message: TWMCommand); message CN_COMMAND;
- procedure DoCloseUp(Canceled: Boolean); virtual;
- procedure DropDown; override;
- function GetMaxItemWidth: Integer;
- procedure ResetItemHeight;
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- function GetTextWidth(Str: string): Integer;
- procedure DoPreloadImages;
- property ItemImage[Index: Integer]: Integer read GetItemImage;
- property ItemIndent[Index: Integer]: Integer read GetItemIndent;
- property ItemText[Index: Integer]: string read GetItemText;
- property TopIndex: Integer read GetTopIndex write SetTopIndex;
- property UseSystemImageList: Boolean read FUseSystemImageList write SetUseSystemImageList;
- property DropDownFixedWidth: Integer read FDropDownFixedWidth write FDropDownFixedWidth default 0;
- property OnCloseUp: TIECloseUpEvent read FOnCloseUp write FOnCloseUp;
- published
- end;
- // =======================================================================
- // Class TIEComboBox
- // =======================================================================
- TIEComboBox = class(TIECustomComboBox)
- published
- property DropDownFixedWidth;
- property OnCloseUp;
- property Style; {Must be published before Items}
- property Align;
- property Anchors;
- property BiDiMode;
- property Color;
- property Constraints;
- property Ctl3D;
- property DragCursor;
- property DragKind;
- property DragMode;
- property DropDownCount;
- property Enabled;
- property Font;
- property ImeMode;
- property ImeName;
- property ItemHeight;
- property Items;
- property MaxLength;
- property ParentBiDiMode;
- property ParentColor;
- property ParentCtl3D;
- property ParentFont;
- property ParentShowHint;
- property PopupMenu;
- property ShowHint;
- property Sorted;
- property TabOrder;
- property TabStop;
- property Text;
- property Visible;
- property OnChange;
- property OnClick;
- 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;
- function GetItemHeight(Font: TFont): Integer;
- procedure Register;
- implementation
- uses
- SysUtils, Forms, Dialogs, Imglist, ShellAPI, CommCtrl, Math, Windows;
- procedure Register;
- begin
- RegisterComponents('DriveDir', [TIEComboBox]);
- end;
- // =======================================================================
- // Class TIECustomComboBox
- // =======================================================================
- constructor TIECustomComboBox.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- FCanceled := True;
- FUseSystemImageList := False;
- FSystemImageList := nil;
- end; {TIECustomComboBox.Create}
- destructor TIECustomComboBox.Destroy;
- begin
- FreeAndNil(FSystemImageList);
- inherited;
- end;
- procedure TIECustomComboBox.CMFontChanged(var Message: TMessage);
- begin
- inherited;
- ResetItemHeight;
- RecreateWnd;
- end; {CMFontChanged}
- procedure TIECustomComboBox.DoCloseUp(Canceled: Boolean);
- begin
- if Assigned(FOnCloseUp) then
- FOnCloseUp(Self, Canceled);
- end; { DoCloseUp }
- procedure TIECustomComboBox.DropDown;
- var
- ItemWidth: Integer;
- begin
- {Check to see if DropDownFixed Width > 0. Then just set the
- width of the list box. Otherwise, loop through the items
- and set the width of the list box to 8 pixels > than the
- widest string to buffer the right side. Anything less than
- 8 for some reason touches the end of the item on high-res
- monitor settings.}
- if (FDropDownFixedWidth > 0) then
- Self.Perform(CB_SETDROPPEDWIDTH, FDropDownFixedWidth, 0)
- else
- begin
- ItemWidth := GetMaxItemWidth + 8;
- if Items.Count > DropDowncount then
- Inc(ItemWidth, 16);
- Self.Perform(CB_SETDROPPEDWIDTH, ItemWidth, 0);
- end;
- inherited DropDown;
- end; {TIECustomComboBox.DropDown}
- function TIECustomComboBox.GetTextWidth(Str: string): Integer;
- var
- DC: HDC;
- SaveFont: HFont;
- Size: TSize;
- begin
- DC := GetDC(0);
- try
- SaveFont := SelectObject(DC, Font.Handle);
- GetTextExtentPoint32(DC, PChar(Str), Length(Str), Size);
- Result := Size.Cx;
- SelectObject(DC, SaveFont);
- finally
- ReleaseDC(0, DC);
- end;
- end; {TIECustomComboBox.GetTextWidth}
- function TIECustomComboBox.GetMaxItemWidth: Integer;
- var
- DC: HDC;
- SaveFont: HFont;
- Size: TSize;
- Index: Integer;
- begin
- Result := 0;
- DC := GetDC(0);
- try
- SaveFont := SelectObject(DC, Font.Handle);
- for Index := 0 to Items.Count - 1 do
- begin
- GetTextExtentPoint32(DC, PChar(ItemText[Index]), Length(ItemText[Index]), Size);
- if (ImageList <> nil) and (ItemImage[Index] >= 0) then
- Inc(Size.Cx, IconWidth + 6);
- Inc(Size.Cx, ItemIndent[Index]);
- if Size.Cx > Result then Result := Size.Cx;
- end;
- SelectObject(DC, SaveFont);
- finally
- ReleaseDC(0, DC);
- end;
- end; {TIECustomComboBox.GetMaxItemWidth}
- function TIECustomComboBox.GetTopIndex: Integer;
- begin
- Result := Perform(CB_GETTOPINDEX, 0, 0);
- end; {TIECustomComboBox.GetTopIndex}
- {$HINTS OFF}
- procedure TIECustomComboBox.DoPreloadImages;
- var
- Index, Dummy: Integer;
- begin
- for Index := 0 to Items.Count-1 do
- Dummy := ItemImage[Index];
- end;
- {$HINTS ON}
- procedure TIECustomComboBox.ResetItemHeight;
- var
- AHeight: Integer;
- Begin
- AHeight := Max(GetItemHeight(Font), 10) + 2;
- inherited ItemHeight := AHeight;
- if HandleAllocated then
- begin
- {Set height of list items:}
- SendMessage(Handle, CB_SETITEMHEIGHT, 0, Max(AHeight, 12));
- {Set height of selection field:}
- SendMessage(Handle, CB_SETITEMHEIGHT, -1, AHeight);
- {Set height of delphi-control:}
- Height := AHeight;
- end;
- end;
- procedure TIECustomComboBox.SetTopIndex(Value: Integer);
- begin
- if Value <> TopIndex then
- Perform(CB_SETTOPINDEX, Value, 0);
- end; {TIECustomComboBox.SetTopIndex}
- procedure TIECustomComboBox.CNCommand(var Message: TWMCommand);
- begin
- inherited;
- case Message.NotifyCode of
- CBN_CLOSEUP:
- DoCloseUp(FCanceled);
- CBN_SELENDCANCEL:
- FCanceled := True;
- CBN_SELENDOK:
- FCanceled := False;
- end;
- end; {TIECustomComboBox.CNCommand}
- function GetItemHeight(Font: TFont): Integer;
- var
- DC: HDC;
- SaveFont: HFont;
- Metrics: TTextMetric;
- begin
- DC := GetDC(0);
- try
- SaveFont := SelectObject(DC, Font.Handle);
- GetTextMetrics(DC, Metrics);
- SelectObject(DC, SaveFont);
- finally
- ReleaseDC(0, DC);
- end;
- Result := Metrics.tmHeight;
- end; {GetItemHeight}
- procedure TIECustomComboBox.DrawItem(Index: Integer; Rect: TRect; State: TOwnerDrawState);
- var
- Text: string;
- Image: Integer;
- InList: Boolean;
- begin
- inherited;
- if Style = csOwnerDrawFixed then
- with Canvas do
- begin
- FillRect(Rect);
- Pen.Color := clWindowText;
- // Rect.Top = 3 when we draw selected item in component rect (not in dropdown)
- InList := (Rect.Top <> 3);
- Text := GetItemTextEx(Index, InList);
- if InList then Rect.Left := Rect.Left + ItemIndent[Index];
- if ImageList <> nil then
- begin
- Image := ItemImage[Index];
- if Image >= 0 then
- begin
- ImageList.Draw(Canvas, Rect.Left + 2, Rect.Top, Image);
- Rect.Left := Rect.Left + IconWidth + 6;
- end
- else Rect.Left := Rect.Left + 2;
- end
- else Rect.Left := Rect.Left + 2;
- DrawText(Canvas.Handle, PChar(Text), Length(Text), Rect,
- DrawTextBiDiModeFlags(DT_SINGLELINE or DT_VCENTER or DT_NOPREFIX));
- end;
- end;
- function TIECustomComboBox.GetItemImage(Index: Integer): Integer;
- begin
- Result := -1;
- end;
- function TIECustomComboBox.GetItemIndent(Index: Integer): Integer;
- begin
- Result := 0;
- end;
- function TIECustomComboBox.GetItemText(Index: Integer): string;
- begin
- Result := GetItemTextEx(Index, True);
- end;
- function TIECustomComboBox.GetItemTextEx(Index: Integer; ForList: Boolean): string;
- begin
- Result := Items[Index];
- end;
- function TIECustomComboBox.ImageList: TImageList;
- var
- ImageListHandle: HImageList;
- FileInfo: TSHFileInfo;
- begin
- if FUseSystemImageList then
- begin
- if not Assigned(FSystemImageList) then
- begin
- FSystemImageList := TImageList.Create(Self);
- ImageListHandle := SHGetFileInfo('', 0, FileInfo, SizeOf(FileInfo),
- SHGFI_SYSICONINDEX or SHGFI_SMALLICON);
- if ImageListHandle <> 0 then
- with FSystemImageList do
- begin
- ShareImages := True;
- Handle := ImageListHandle;
- DrawingStyle := dsTransparent;
- end;
- end;
- Result := FSystemImageList;
- end
- else Result := nil;
- end;
- procedure TIECustomComboBox.SetUseSystemImageList(Value: Boolean);
- begin
- if FUseSystemImageList <> Value then
- begin
- if not FUseSystemImageList then
- begin
- if ImageList <> nil then
- raise Exception.Create('ImageList is already created.');
- end
- else FreeAndNil(FSystemImageList);
- FUseSystemImageList := Value;
- end;
- end;
- initialization
- end.
|