HistoryComboBox.pas 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  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. procedure Register;
  46. begin
  47. RegisterComponents('Martin', [THistoryComboBox]);
  48. end;
  49. procedure SaveToHistory(Strings: TStrings; T: string; Data: Pointer; MaxHistorySize: Integer);
  50. begin
  51. if T <> '' then
  52. begin
  53. while Strings.IndexOf(T) >= 0 do Strings.Delete(Strings.IndexOf(T));
  54. Strings.InsertObject(0, T, TObject(Data));
  55. end;
  56. while Strings.Count > MaxHistorySize do
  57. Strings.Delete(Strings.Count-1);
  58. end;
  59. { THistoryComboBox }
  60. constructor THistoryComboBox.Create(AOwner: TComponent);
  61. begin
  62. inherited;
  63. FSaveOn := DefaultHistorySaveOn;
  64. FMaxHistorySize := DefaultMaxHistorySize;
  65. FOnGetData := nil;
  66. FOnSetData := nil;
  67. end;
  68. procedure THistoryComboBox.KeyDown(var Key: Word; Shift: TShiftState);
  69. begin
  70. if ((Key = VK_DOWN) or (Key = VK_UP)) and
  71. (not (ssAlt in Shift)) and (soDropDown in SaveOn) then
  72. if Items.IndexOf(Text) < 0 then SaveToHistory;
  73. inherited;
  74. end;
  75. procedure THistoryComboBox.SetMaxHistorySize(AMaxHistorySize: Integer);
  76. begin
  77. FMaxHistorySize := AMaxHistorySize;
  78. while Items.Count > FMaxHistorySize do
  79. Items.Delete(Items.Count-1);
  80. end;
  81. procedure THistoryComboBox.DoExit;
  82. begin
  83. inherited;
  84. if soExit in SaveOn then SaveToHistory;
  85. end;
  86. procedure THistoryComboBox.DropDown;
  87. var
  88. ItemWidth: Integer;
  89. begin
  90. inherited;
  91. if soDropDown in SaveOn then SaveToHistory;
  92. // taken from TIECustomComboBox:
  93. ItemWidth := GetMaxItemWidth + 8;
  94. if Items.Count > DropDowncount then
  95. Inc(ItemWidth, 16);
  96. Self.Perform(CB_SETDROPPEDWIDTH, ItemWidth, 0);
  97. end;
  98. procedure THistoryComboBox.Change;
  99. var
  100. Index: Integer;
  101. begin
  102. inherited Change;
  103. if Assigned(OnSetData) then
  104. begin
  105. // note that ItemIndex is not reliable
  106. Index := Items.IndexOf(Text);
  107. if Index >= 0 then OnSetData(Self, Items.Objects[Index]);
  108. end;
  109. end;
  110. procedure THistoryComboBox.SaveToHistory;
  111. var
  112. Data: Pointer;
  113. begin
  114. if Text <> '' then
  115. begin
  116. Data := nil;
  117. if Assigned(OnGetData) then
  118. OnGetData(Self, Data);
  119. HistoryComboBox.SaveToHistory(Items, Text, Data, MaxHistorySize);
  120. ItemIndex := 0;
  121. end;
  122. end;
  123. function THistoryComboBox.StoreSaveOn: Boolean;
  124. begin
  125. Result := (SaveOn <> DefaultHistorySaveOn);
  126. end;
  127. // taken from TIECustomComboBox:
  128. function THistoryComboBox.GetMaxItemWidth: Integer;
  129. var
  130. DC: HDC;
  131. SaveFont: HFont;
  132. Size: TSize;
  133. Index: Integer;
  134. begin
  135. Result := 0;
  136. DC := GetDC(0);
  137. try
  138. SaveFont := SelectObject(DC, Font.Handle);
  139. for Index := 0 to Items.Count - 1 do
  140. begin
  141. GetTextExtentPoint32(DC, PChar(Items[Index]), Length(Items[Index]), Size);
  142. if Size.Cx > Result then Result := Size.Cx;
  143. end;
  144. SelectObject(DC, SaveFont);
  145. finally
  146. ReleaseDC(0, DC);
  147. end;
  148. end;
  149. initialization
  150. end.