123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196 |
- unit HistoryComboBox;
- interface
- uses
- Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
- StdCtrls;
- type
- TUIStateAwareComboBox = class(TComboBox)
- protected
- procedure ComboWndProc(var Message: TMessage; ComboWnd: HWnd; ComboProc: TWindowProcPtr); override;
- end;
- type
- THistorySaveOn = set of (soExit, soDropDown);
- const
- DefaultHistorySaveOn = [soExit, soDropDown];
- DefaultMaxHistorySize = 30;
- type
- THistoryComboBox = class;
- THistoryComboBoxGetData = procedure(Sender: THistoryComboBox; var Data: Pointer) of object;
- THistoryComboBoxSetData = procedure(Sender: THistoryComboBox; Data: Pointer) of object;
- THistoryComboBox = class(TUIStateAwareComboBox)
- private
- { Private declarations }
- FSaveOn: THistorySaveOn;
- FMaxHistorySize: Integer;
- FOnGetData: THistoryComboBoxGetData;
- FOnSetData: THistoryComboBoxSetData;
- procedure SetMaxHistorySize(AMaxHistorySize: Integer);
- function GetMaxItemWidth: Integer;
- protected
- { Protected declarations }
- procedure DoExit; override;
- procedure DropDown; override;
- procedure KeyDown(var Key: Word; Shift: TShiftState); override;
- procedure Change; override;
- public
- { Public declarations }
- constructor Create(AOwner: TComponent); override;
- procedure SaveToHistory; virtual;
- published
- { Published declarations }
- property SaveOn: THistorySaveOn read FSaveOn write FSaveOn default DefaultHistorySaveOn;
- property MaxHistorySize: Integer read FMaxHistorySize write SetMaxHistorySize default DefaultMaxHistorySize;
- property OnGetData: THistoryComboBoxGetData read FOnGetData write FOnGetData;
- property OnSetData: THistoryComboBoxSetData read FOnSetData write FOnSetData;
- end;
- procedure SaveToHistory(Strings: TStrings; T: string; Data: Pointer = nil; MaxHistorySize: Integer = DefaultMaxHistorySize);
- procedure Register;
- implementation
- uses
- PasTools;
- procedure Register;
- begin
- RegisterComponents('Martin', [THistoryComboBox]);
- end;
- procedure SaveToHistory(Strings: TStrings; T: string; Data: Pointer; MaxHistorySize: Integer);
- begin
- if T <> '' then
- begin
- while Strings.IndexOf(T) >= 0 do Strings.Delete(Strings.IndexOf(T));
- Strings.InsertObject(0, T, TObject(Data));
- end;
- while Strings.Count > MaxHistorySize do
- Strings.Delete(Strings.Count-1);
- end;
- { TUIStateAwareComboBox }
- procedure TUIStateAwareComboBox.ComboWndProc(var Message: TMessage; ComboWnd: HWnd; ComboProc: TWindowProcPtr);
- begin
- inherited;
- if Message.Msg = WM_SYSKEYDOWN then
- begin
- UpdateUIState(TWMKey(Message).CharCode);
- end;
- end;
- { THistoryComboBox }
- constructor THistoryComboBox.Create(AOwner: TComponent);
- begin
- inherited;
- FSaveOn := DefaultHistorySaveOn;
- FMaxHistorySize := DefaultMaxHistorySize;
- FOnGetData := nil;
- FOnSetData := nil;
- end;
- procedure THistoryComboBox.KeyDown(var Key: Word; Shift: TShiftState);
- begin
- if ((Key = VK_DOWN) or (Key = VK_UP)) and
- (not (ssAlt in Shift)) and (soDropDown in SaveOn) then
- begin
- if Items.IndexOf(Text) < 0 then SaveToHistory;
- end;
- if DroppedDown and (Key = VK_DELETE) and (ssCtrl in Shift) and (SaveOn <> []) then
- begin
- Items.Clear;
- Key := 0;
- end;
- inherited;
- end;
- procedure THistoryComboBox.SetMaxHistorySize(AMaxHistorySize: Integer);
- begin
- FMaxHistorySize := AMaxHistorySize;
- while Items.Count > FMaxHistorySize do
- Items.Delete(Items.Count-1);
- end;
- procedure THistoryComboBox.DoExit;
- begin
- inherited;
- if soExit in SaveOn then SaveToHistory;
- end;
- procedure THistoryComboBox.DropDown;
- var
- ItemWidth: Integer;
- begin
- inherited;
- if soDropDown in SaveOn then SaveToHistory;
- ItemWidth := GetMaxItemWidth + ScaleByPixelsPerInch(8, Self);
- if Items.Count > DropDownCount then
- Inc(ItemWidth, GetSystemMetricsForControl(Self, SM_CXVSCROLL));
- Self.Perform(CB_SETDROPPEDWIDTH, ItemWidth, 0);
- end;
- procedure THistoryComboBox.Change;
- var
- Index: Integer;
- begin
- inherited Change;
- if Assigned(OnSetData) then
- begin
- // note that ItemIndex is not reliable
- Index := Items.IndexOf(Text);
- if Index >= 0 then OnSetData(Self, Items.Objects[Index]);
- end;
- end;
- procedure THistoryComboBox.SaveToHistory;
- var
- Data: Pointer;
- begin
- if Text <> '' then
- begin
- Data := nil;
- if Assigned(OnGetData) then
- OnGetData(Self, Data);
- HistoryComboBox.SaveToHistory(Items, Text, Data, MaxHistorySize);
- ItemIndex := 0;
- end;
- end;
- function THistoryComboBox.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(Items[Index]), Length(Items[Index]), Size);
- if Size.Cx > Result then Result := Size.Cx;
- end;
- SelectObject(DC, SaveFont);
- finally
- ReleaseDC(0, DC);
- end;
- end;
- initialization
- end.
|