HistoryComboBox.pas 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. unit HistoryComboBox;
  2. interface
  3. uses
  4. Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  5. StdCtrls;
  6. type
  7. THistorySaveOn = set of (soExit, soDropDown);
  8. const
  9. DefaultHistorySaveOn = [soExit, soDropDown];
  10. DefaultMaxHistorySize = 30;
  11. type
  12. THistoryComboBox = class;
  13. THistoryComboBoxGetData = procedure(Sender: THistoryComboBox; var Data: Pointer) of object;
  14. THistoryComboBoxSetData = procedure(Sender: THistoryComboBox; Data: Pointer) of object;
  15. THistoryComboBox = class(TComboBox)
  16. private
  17. { Private declarations }
  18. FSaveOn: THistorySaveOn;
  19. FMaxHistorySize: Integer;
  20. FOnGetData: THistoryComboBoxGetData;
  21. FOnSetData: THistoryComboBoxSetData;
  22. procedure SetMaxHistorySize(AMaxHistorySize: Integer);
  23. function StoreSaveOn: Boolean;
  24. function GetMaxItemWidth: Integer;
  25. protected
  26. { Protected declarations }
  27. procedure DoExit; override;
  28. procedure DropDown; override;
  29. procedure KeyDown(var Key: Word; Shift: TShiftState); override;
  30. procedure Change; override;
  31. public
  32. { Public declarations }
  33. constructor Create(AOwner: TComponent); override;
  34. procedure SaveToHistory; virtual;
  35. published
  36. { Published declarations }
  37. property SaveOn: THistorySaveOn read FSaveOn write FSaveOn stored StoreSaveOn;
  38. property MaxHistorySize: Integer read FMaxHistorySize write SetMaxHistorySize default DefaultMaxHistorySize;
  39. property OnGetData: THistoryComboBoxGetData read FOnGetData write FOnGetData;
  40. property OnSetData: THistoryComboBoxSetData read FOnSetData write FOnSetData;
  41. end;
  42. procedure SaveToHistory(Strings: TStrings; T: string; Data: Pointer = nil; MaxHistorySize: Integer = DefaultMaxHistorySize);
  43. procedure Register;
  44. implementation
  45. uses
  46. PasTools;
  47. procedure Register;
  48. begin
  49. RegisterComponents('Martin', [THistoryComboBox]);
  50. end;
  51. procedure SaveToHistory(Strings: TStrings; T: string; Data: Pointer; MaxHistorySize: Integer);
  52. begin
  53. if T <> '' then
  54. begin
  55. while Strings.IndexOf(T) >= 0 do Strings.Delete(Strings.IndexOf(T));
  56. Strings.InsertObject(0, T, TObject(Data));
  57. end;
  58. while Strings.Count > MaxHistorySize do
  59. Strings.Delete(Strings.Count-1);
  60. end;
  61. { THistoryComboBox }
  62. constructor THistoryComboBox.Create(AOwner: TComponent);
  63. begin
  64. inherited;
  65. FSaveOn := DefaultHistorySaveOn;
  66. FMaxHistorySize := DefaultMaxHistorySize;
  67. FOnGetData := nil;
  68. FOnSetData := nil;
  69. end;
  70. procedure THistoryComboBox.KeyDown(var Key: Word; Shift: TShiftState);
  71. begin
  72. if ((Key = VK_DOWN) or (Key = VK_UP)) and
  73. (not (ssAlt in Shift)) and (soDropDown in SaveOn) then
  74. if Items.IndexOf(Text) < 0 then SaveToHistory;
  75. inherited;
  76. end;
  77. procedure THistoryComboBox.SetMaxHistorySize(AMaxHistorySize: Integer);
  78. begin
  79. FMaxHistorySize := AMaxHistorySize;
  80. while Items.Count > FMaxHistorySize do
  81. Items.Delete(Items.Count-1);
  82. end;
  83. procedure THistoryComboBox.DoExit;
  84. begin
  85. inherited;
  86. if soExit in SaveOn then SaveToHistory;
  87. end;
  88. procedure THistoryComboBox.DropDown;
  89. var
  90. ItemWidth: Integer;
  91. begin
  92. inherited;
  93. if soDropDown in SaveOn then SaveToHistory;
  94. // taken from TIECustomComboBox:
  95. ItemWidth := GetMaxItemWidth + ScaleByPixelsPerInch(8);
  96. if Items.Count > DropDowncount then
  97. Inc(ItemWidth, GetSystemMetrics(SM_CXVSCROLL));
  98. Self.Perform(CB_SETDROPPEDWIDTH, ItemWidth, 0);
  99. end;
  100. procedure THistoryComboBox.Change;
  101. var
  102. Index: Integer;
  103. begin
  104. inherited Change;
  105. if Assigned(OnSetData) then
  106. begin
  107. // note that ItemIndex is not reliable
  108. Index := Items.IndexOf(Text);
  109. if Index >= 0 then OnSetData(Self, Items.Objects[Index]);
  110. end;
  111. end;
  112. procedure THistoryComboBox.SaveToHistory;
  113. var
  114. Data: Pointer;
  115. begin
  116. if Text <> '' then
  117. begin
  118. Data := nil;
  119. if Assigned(OnGetData) then
  120. OnGetData(Self, Data);
  121. HistoryComboBox.SaveToHistory(Items, Text, Data, MaxHistorySize);
  122. ItemIndex := 0;
  123. end;
  124. end;
  125. function THistoryComboBox.StoreSaveOn: Boolean;
  126. begin
  127. Result := (SaveOn <> DefaultHistorySaveOn);
  128. end;
  129. // taken from TIECustomComboBox:
  130. function THistoryComboBox.GetMaxItemWidth: Integer;
  131. var
  132. DC: HDC;
  133. SaveFont: HFont;
  134. Size: TSize;
  135. Index: Integer;
  136. begin
  137. Result := 0;
  138. DC := GetDC(0);
  139. try
  140. SaveFont := SelectObject(DC, Font.Handle);
  141. for Index := 0 to Items.Count - 1 do
  142. begin
  143. GetTextExtentPoint32(DC, PChar(Items[Index]), Length(Items[Index]), Size);
  144. if Size.Cx > Result then Result := Size.Cx;
  145. end;
  146. SelectObject(DC, SaveFont);
  147. finally
  148. ReleaseDC(0, DC);
  149. end;
  150. end;
  151. initialization
  152. end.