Componentes.Terceros.SpTBXLib/internal/2.4.4/1/Source/SpTBXMDIMRU.pas
2010-01-19 16:32:53 +00:00

795 lines
24 KiB
ObjectPascal

unit SpTBXMDIMRU;
{==============================================================================
Version 2.4.4
The contents of this file are subject to the SpTBXLib License; you may
not use or distribute this file except in compliance with the
SpTBXLib License.
A copy of the SpTBXLib License may be found in SpTBXLib-LICENSE.txt or at:
http://www.silverpointdevelopment.com/sptbxlib/SpTBXLib-LICENSE.htm
Alternatively, the contents of this file may be used under the terms of the
Mozilla Public License Version 1.1 (the "MPL v1.1"), in which case the provisions
of the MPL v1.1 are applicable instead of those in the SpTBXLib License.
A copy of the MPL v1.1 may be found in MPL-LICENSE.txt or at:
http://www.mozilla.org/MPL/
If you wish to allow use of your version of this file only under the terms of
the MPL v1.1 and not to allow others to use your version of this file under the
SpTBXLib License, indicate your decision by deleting the provisions
above and replace them with the notice and other provisions required by the
MPL v1.1. If you do not delete the provisions above, a recipient may use your
version of this file under either the SpTBXLib License or the MPL v1.1.
Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the License for
the specific language governing rights and limitations under the License.
The initial developer of this code is Robert Lee.
Requirements:
For Delphi/C++Builder 2009 or newer:
- Jordan Russell's Toolbar 2000
http://www.jrsoftware.org
For Delphi/C++Builder 7-2007:
- Jordan Russell's Toolbar 2000
http://www.jrsoftware.org
- Troy Wolbrink's TNT Unicode Controls
http://www.tntware.com/delphicontrols/unicode/
Development notes:
- All the theme changes and adjustments are marked with '[Theme-Change]'.
History:
2 December 2009 - version 2.4.4
- No changes.
13 September 2009 - version 2.4.3
- Fixed TSpTBXMRUListItem.LoadFromIni/SaveToIni bug, in Delphi
2009, some strings are not stored correctly (Surrogate Pair),
thanks to Totonica for reporting this.
- Fixed incorrect TSpTBXMDIHandler MDI buttons painting when
using the default Windows theme, thanks to Cybrus for
reporting this.
8 May 2009 - version 2.4.2
- Fixed incorrect MRU saving on TSpTBXMRUListItem, the
items were not correctly encoded when saving to an Ini
file, thanks to Dirk for reporting this.
15 March 2009 - version 2.4.1
- No changes.
17 January 2009 - version 2.4
- Added GetMRUFilenames and MRUClick methods to
TSpTBXMRUListItem.
- Added Hints to the items of TSpTBXMRUListItem.
26 September 2008 - version 2.3
- No changes.
29 July 2008 - version 2.2
- No changes.
26 June 2008 - version 2.1
- No changes.
3 May 2008 - version 2.0
- No changes.
2 April 2008 - version 1.9.5
- Fixed incorrect MRU loading on TSpTBXMRUListItem, thanks
to Pete for reporting this.
- Fixed incorrect TSpTBXMRUListItem behavior, MaxItems
had no effect when new files were added, thanks to
Senfore for reporting this.
3 February 2008 - version 1.9.4
- Added HidePathExtension property to TSpTBXMRUListItem.
19 January 2008 - version 1.9.3
- Initial release.
==============================================================================}
interface
{$BOOLEVAL OFF} // Unit depends on short-circuit boolean evaluation
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Menus, ImgList, IniFiles, TB2Item, TB2Toolbar, SpTBXSkins, SpTBXItem;
type
TSpTBXMDIButtonsItem = class;
TSpTBXMRUListClickEvent = procedure(Sender: TObject; const Filename: WideString) of object;
{ TSpTBXMDIHandler }
TSpTBXMDIHandler = class(TComponent)
private
FButtonsItem: TSpTBXMDIButtonsItem;
FSystemMenuItem: TSpTBXSystemMenuItem;
FToolbar: TTBCustomToolbar;
procedure SetToolbar(Value: TTBCustomToolbar);
protected
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
property Toolbar: TTBCustomToolbar read FToolbar write SetToolbar;
end;
{ TSpTBXMDIButtonsItem: should only be used by TSpTBXMDIHandler }
TSpTBXMDIButtonsItem = class(TTBCustomItem)
private
FMinimizeItem, FRestoreItem, FCloseItem: TSpTBXItem;
procedure DrawItem(Sender: TObject; ACanvas: TCanvas;
ARect: TRect; ItemInfo: TSpTBXMenuItemInfo; const PaintStage: TSpTBXPaintStage;
var PaintDefault: Boolean);
procedure DrawItemImage(Sender: TObject; ACanvas: TCanvas;
State: TSpTBXSkinStatesType; const PaintStage: TSpTBXPaintStage;
var AImageList: TCustomImageList; var AImageIndex: Integer;
var ARect: TRect; var PaintDefault: Boolean);
procedure InvalidateSystemMenuItem;
procedure ItemClick(Sender: TObject);
procedure UpdateState(W: HWND; Maximized: Boolean);
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
end;
{ TSpTBXMDIWindowItem }
TSpTBXMDIWindowItem = class(TTBCustomItem)
private
FForm: TForm;
FOnUpdate: TNotifyEvent;
FWindowMenu: TMenuItem;
procedure ItemClick(Sender: TObject);
procedure SetForm(AForm: TForm);
protected
procedure EnabledChanged; override;
procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override;
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
public
constructor Create(AOwner: TComponent); override;
procedure InitiateAction; override;
published
property Enabled;
property OnUpdate: TNotifyEvent read FOnUpdate write FOnUpdate;
end;
{ TSpTBXMRUListItem }
TSpTBXMRUListItem = class(TTBCustomItem)
private
FMaxItems: Integer;
FOnClick: TSpTBXMRUListClickEvent;
FHidePathExtension: Boolean;
procedure ClickHandler(Sender: TObject);
procedure SetHidePathExtension(const Value: Boolean);
procedure SetMaxItems(const Value: Integer);
public
constructor Create(AOwner: TComponent); override;
procedure GetMRUFilenames(MRUFilenames: TStrings);
function IndexOfMRU(Filename: WideString): Integer;
function MRUAdd(Filename: WideString): Integer;
function MRUClick(Filename: WideString): Boolean;
procedure MRURemove(Filename: WideString);
procedure MRUUpdateCaptions;
procedure LoadFromIni(Ini: TCustomIniFile; const Section: string);
procedure SaveToIni(Ini: TCustomIniFile; const Section: string);
published
property HidePathExtension: Boolean read FHidePathExtension write SetHidePathExtension default True;
property MaxItems: Integer read FMaxItems write SetMaxItems default 4;
property OnClick: TSpTBXMRUListClickEvent read FOnClick write FOnClick;
end;
{ TSpTBXMRUItem: should only be used by TSpTBXMRUListItem }
TSpTBXMRUItem = class(TSpTBXCustomItem)
private
FMRUString: WideString;
public
property MRUString: WideString read FMRUString write FMRUString;
end;
implementation
uses
Themes, UxTheme,
{$IFNDEF UNICODE} TntSysUtils, {$ENDIF}
TB2Common, TB2Consts;
type
TTBCustomToolbarAccess = class(TTBCustomToolbar);
TTBCustomItemAccess = class(TTBCustomItem);
//WMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWM
{ TSpTBXMDIHandler }
constructor TSpTBXMDIHandler.Create(AOwner: TComponent);
begin
inherited;
FSystemMenuItem := TSpTBXSystemMenuItem.Create(Self);
FSystemMenuItem.MDISystemMenu := True;
FButtonsItem := TSpTBXMDIButtonsItem.Create(Self);
end;
destructor TSpTBXMDIHandler.Destroy;
begin
SetToolbar(nil);
inherited;
end;
procedure TSpTBXMDIHandler.Notification(AComponent: TComponent; Operation: TOperation);
begin
inherited;
if (AComponent = FToolbar) and (Operation = opRemove) then
Toolbar := nil;
end;
procedure TSpTBXMDIHandler.SetToolbar(Value: TTBCustomToolbar);
var
Rebuild: Boolean;
begin
if FToolbar <> Value then begin
if Assigned(FToolbar) then begin
Rebuild := False;
if TTBCustomToolbarAccess(FToolbar).FMDIButtonsItem = FButtonsItem then begin
TTBCustomToolbarAccess(FToolbar).FMDIButtonsItem := nil;
Rebuild := True;
end;
if TTBCustomToolbarAccess(FToolbar).FMDISystemMenuItem = FSystemMenuItem then begin
TTBCustomToolbarAccess(FToolbar).FMDISystemMenuItem := nil;
Rebuild := True;
end;
if Rebuild and Assigned(FToolbar.View) then
FToolbar.View.RecreateAllViewers;
end;
FToolbar := Value;
if Assigned(Value) then begin
Value.FreeNotification(Self);
TTBCustomToolbarAccess(Value).FMDIButtonsItem := FButtonsItem;
TTBCustomToolbarAccess(Value).FMDISystemMenuItem := FSystemMenuItem;
Value.View.RecreateAllViewers;
end;
end;
end;
//WMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWM
{ TSpTBXMDIButtonsItem }
var
CBTHookHandle: HHOOK;
MDIButtonsItems: TList;
function WindowIsMDIChild(W: HWND): Boolean;
var
I: Integer;
MainForm, ChildForm: TForm;
begin
MainForm := Application.MainForm;
if Assigned(MainForm) then
for I := 0 to MainForm.MDIChildCount-1 do begin
ChildForm := MainForm.MDIChildren[I];
if ChildForm.HandleAllocated and (ChildForm.Handle = W) then begin
Result := True;
Exit;
end;
end;
Result := False;
end;
function CBTHook(Code: Integer; WParam: WPARAM; LParam: LPARAM): LRESULT;
stdcall;
var
Maximizing: Boolean;
WindowPlacement: TWindowPlacement;
I: Integer;
begin
case Code of
HCBT_SETFOCUS: begin
if WindowIsMDIChild(HWND(WParam)) and Assigned(MDIButtonsItems) then begin
for I := 0 to MDIButtonsItems.Count-1 do
TSpTBXMDIButtonsItem(MDIButtonsItems[I]).InvalidateSystemMenuItem;
end;
end;
HCBT_MINMAX: begin
if WindowIsMDIChild(HWND(WParam)) and Assigned(MDIButtonsItems) and
(LParam in [SW_SHOWNORMAL, SW_SHOWMAXIMIZED, SW_MINIMIZE, SW_RESTORE]) then begin
Maximizing := (LParam = SW_MAXIMIZE);
if (LParam = SW_RESTORE) and not IsZoomed(HWND(WParam)) then begin
WindowPlacement.length := SizeOf(WindowPlacement);
GetWindowPlacement(HWND(WParam), @WindowPlacement);
Maximizing := (WindowPlacement.flags and WPF_RESTORETOMAXIMIZED <> 0);
end;
for I := 0 to MDIButtonsItems.Count-1 do
TSpTBXMDIButtonsItem(MDIButtonsItems[I]).UpdateState(HWND(WParam), Maximizing);
end;
end;
HCBT_DESTROYWND: begin
if WindowIsMDIChild(HWND(WParam)) and Assigned(MDIButtonsItems) then begin
for I := 0 to MDIButtonsItems.Count-1 do
TSpTBXMDIButtonsItem(MDIButtonsItems[I]).UpdateState(HWND(WParam), False);
end;
end;
end;
Result := CallNextHookEx(CBTHookHandle, Code, WParam, LParam);
end;
constructor TSpTBXMDIButtonsItem.Create(AOwner: TComponent);
function CreateItem(ImageIndex: Integer): TSpTBXItem;
var
A: TTBCustomItemAccess;
begin
Result := TSpTBXItem.Create(Self);
A := TTBCustomItemAccess(Result);
A.ItemStyle := A.ItemStyle + [tbisRightAlign];
Result.Images := MDIButtonsImgList;
Result.ImageIndex := ImageIndex;
Result.CustomWidth := 17;
Result.OnClick := ItemClick;
Result.OnDrawItem := DrawItem;
Result.OnDrawImage := DrawItemImage;
end;
begin
inherited;
ItemStyle := ItemStyle + [tbisEmbeddedGroup];
FMinimizeItem := CreateItem(2);
FRestoreItem := CreateItem(3);
FCloseItem := CreateItem(0);
Add(FMinimizeItem);
Add(FRestoreItem);
Add(FCloseItem);
UpdateState(0, False);
AddToList(MDIButtonsItems, Self);
if CBTHookHandle = 0 then
CBTHookHandle := SetWindowsHookEx(WH_CBT, CBTHook, 0, GetCurrentThreadId);
end;
destructor TSpTBXMDIButtonsItem.Destroy;
begin
RemoveFromList(MDIButtonsItems, Self);
if (MDIButtonsItems = nil) and (CBTHookHandle <> 0) then begin
UnhookWindowsHookEx(CBTHookHandle);
CBTHookHandle := 0;
end;
inherited;
end;
procedure TSpTBXMDIButtonsItem.DrawItem(Sender: TObject; ACanvas: TCanvas;
ARect: TRect; ItemInfo: TSpTBXMenuItemInfo;
const PaintStage: TSpTBXPaintStage; var PaintDefault: Boolean);
begin
// [Theme-Change]
// Don't draw the items background if the Default theme is used
if (PaintStage = pstPrePaint) and SkinManager.IsDefaultSkin then
PaintDefault := False;
end;
procedure TSpTBXMDIButtonsItem.DrawItemImage(Sender: TObject; ACanvas: TCanvas;
State: TSpTBXSkinStatesType; const PaintStage: TSpTBXPaintStage;
var AImageList: TCustomImageList; var AImageIndex: Integer; var ARect: TRect;
var PaintDefault: Boolean);
const
ButtonIndexFlags: array[0..3] of Integer = (DFCS_CAPTIONCLOSE, DFCS_CAPTIONMAX, DFCS_CAPTIONMIN, DFCS_CAPTIONRESTORE);
NoneFlags: array[TSpTBXSkinStatesType] of Integer = (0, DFCS_INACTIVE, 0, DFCS_PUSHED, DFCS_PUSHED, DFCS_PUSHED);
XPPart: array [0..3] of Integer = (WP_MDICLOSEBUTTON, WP_MAXBUTTON, WP_MDIMINBUTTON, WP_MDIRESTOREBUTTON);
XPFlags: array[TSpTBXSkinStatesType] of Integer = (CBS_NORMAL, CBS_DISABLED, CBS_HOT, CBS_PUSHED, CBS_PUSHED, CBS_PUSHED);
begin
if (PaintStage = pstPrePaint) and (AImageList = MDIButtonsImgList) and
(AImageIndex >= 0) and (AImageIndex <= 3) then
begin
case SkinManager.GetSkinType of
sknNone:
begin
PaintDefault := False;
DrawFrameControl(ACanvas.Handle, ARect, DFC_CAPTION, ButtonIndexFlags[AImageIndex] or NoneFlags[State]);
end;
sknWindows:
begin
PaintDefault := False;
DrawThemeBackground(ThemeServices.Theme[teWindow], ACanvas.Handle, XPPart[AImageIndex], XPFlags[State], ARect, nil);
end;
end;
end;
end;
procedure TSpTBXMDIButtonsItem.UpdateState(W: HWND; Maximized: Boolean);
var
HasMaxChild, VisibilityChanged: Boolean;
procedure UpdateVisibleEnabled(const Item: TTBCustomItem; const AEnabled: Boolean);
begin
if (Item.Visible <> HasMaxChild) or (Item.Enabled <> AEnabled) then begin
Item.Visible := HasMaxChild;
Item.Enabled := AEnabled;
VisibilityChanged := True;
end;
end;
var
MainForm, ActiveMDIChild, ChildForm: TForm;
I: Integer;
begin
HasMaxChild := False;
MainForm := Application.MainForm;
ActiveMDIChild := nil;
if Assigned(MainForm) then begin
for I := 0 to MainForm.MDIChildCount - 1 do begin
ChildForm := MainForm.MDIChildren[I];
if ChildForm.HandleAllocated and
(((ChildForm.Handle = W) and Maximized) or
((ChildForm.Handle <> W) and IsZoomed(ChildForm.Handle))) then begin
HasMaxChild := True;
Break;
end;
end;
ActiveMDIChild := MainForm.ActiveMDIChild;
end;
VisibilityChanged := False;
UpdateVisibleEnabled(TSpTBXMDIHandler(Owner).FSystemMenuItem, True);
UpdateVisibleEnabled(FMinimizeItem, (ActiveMDIChild = nil) or (GetWindowLong(ActiveMDIChild.Handle, GWL_STYLE) and WS_MINIMIZEBOX <> 0));
UpdateVisibleEnabled(FRestoreItem, True);
UpdateVisibleEnabled(FCloseItem, True);
if VisibilityChanged and Assigned((Owner as TSpTBXMDIHandler).FToolbar) then begin
TSpTBXMDIHandler(Owner).FToolbar.View.InvalidatePositions;
TSpTBXMDIHandler(Owner).FToolbar.View.TryValidatePositions;
end;
end;
procedure TSpTBXMDIButtonsItem.ItemClick(Sender: TObject);
var
MainForm, ChildForm: TForm;
Cmd: WPARAM;
SendTo: HWND;
begin
MainForm := Application.MainForm;
if Assigned(MainForm) then begin
ChildForm := MainForm.ActiveMDIChild;
if Assigned(ChildForm) then begin
// Make sure we send the message to a maximized window
SendTo := ChildForm.Handle;
while not IsZoomed(SendTo) do begin
SendTo := GetWindow(SendTo, GW_HWNDNEXT);
if SendTo = 0 then Exit;
end;
if Sender = FRestoreItem then
Cmd := SC_RESTORE
else if Sender = FCloseItem then
Cmd := SC_CLOSE
else
Cmd := SC_MINIMIZE;
SendMessage(SendTo, WM_SYSCOMMAND, Cmd, GetMessagePos);
end;
end;
end;
procedure TSpTBXMDIButtonsItem.InvalidateSystemMenuItem;
var
View: TTBView;
begin
if Assigned((Owner as TSpTBXMDIHandler).FToolbar) then begin
View := TSpTBXMDIHandler(Owner).FToolbar.View;
View.Invalidate(View.Find(TSpTBXMDIHandler(Owner).FSystemMenuItem));
end;
end;
//WMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWM
{ TSpTBXMDIWindowItem }
constructor TSpTBXMDIWindowItem.Create(AOwner: TComponent);
var
Form: TForm;
begin
inherited;
ItemStyle := ItemStyle + [tbisEmbeddedGroup];
Caption := STBMDIWindowItemDefCaption;
FWindowMenu := TMenuItem.Create(Self);
if not (csDesigning in ComponentState) then begin
{ Need to set WindowMenu before MDI children are created. Otherwise the
list incorrectly shows the first 9 child windows, even if window 10+ is
active. }
Form := Application.MainForm;
if (Form = nil) and (Screen.FormCount > 0) then
Form := Screen.Forms[0];
SetForm(Form);
end;
end;
procedure TSpTBXMDIWindowItem.GetChildren(Proc: TGetChildProc; Root: TComponent);
begin
// Do nothing
end;
procedure TSpTBXMDIWindowItem.Notification(AComponent: TComponent; Operation: TOperation);
begin
inherited;
if (Operation = opRemove) and (AComponent = FForm) then
SetForm(nil);
end;
procedure TSpTBXMDIWindowItem.SetForm(AForm: TForm);
begin
if FForm <> AForm then begin
if Assigned(FForm) and (FForm.WindowMenu = FWindowMenu) then
FForm.WindowMenu := nil;
FForm := AForm;
if Assigned(FForm) then
FForm.FreeNotification(Self);
end;
if Assigned(FForm) then
FForm.WindowMenu := FWindowMenu;
end;
procedure TSpTBXMDIWindowItem.EnabledChanged;
var
I: Integer;
begin
inherited;
for I := 0 to Count-1 do
Items[I].Enabled := Enabled;
end;
procedure TSpTBXMDIWindowItem.InitiateAction;
var
MainForm: TForm;
I: Integer;
M: HMENU;
Item: TSpTBXItem;
ItemCount: Integer;
Buf: array[0..1023] of Char;
begin
inherited;
if csDesigning in ComponentState then
Exit;
MainForm := Application.MainForm;
if Assigned(MainForm) then
SetForm(MainForm);
if FForm = nil then
Exit;
if FForm.ClientHandle <> 0 then
{ This is needed, otherwise windows selected on the More Windows dialog
don't move back into the list }
SendMessage(FForm.ClientHandle, WM_MDIREFRESHMENU, 0, 0);
M := FWindowMenu.Handle;
ItemCount := GetMenuItemCount(M) - 1;
if ItemCount < 0 then
ItemCount := 0;
while Count < ItemCount do begin
Item := TSpTBXItem.Create(Self);
Item.Enabled := Enabled;
Item.OnClick := ItemClick;
Add(Item);
end;
while Count > ItemCount do
Items[Count - 1].Free;
for I := 0 to ItemCount - 1 do begin
Item := TSpTBXItem(Items[I]);
Item.Tag := GetMenuItemID(M, I+1);
if GetMenuString(M, I+1, Buf, SizeOf(Buf), MF_BYPOSITION) = 0 then
Buf[0] := #0;
Item.Caption := Buf;
Item.Checked := GetMenuState(M, I+1, MF_BYPOSITION) and MF_CHECKED <> 0;
end;
if Assigned(FOnUpdate) then
FOnUpdate(Self);
end;
procedure TSpTBXMDIWindowItem.ItemClick(Sender: TObject);
var
Form: TForm;
begin
Form := Application.MainForm;
if Assigned(Form) then
PostMessage(Form.Handle, WM_COMMAND, TTBCustomItem(Sender).Tag, 0);
end;
//WMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWM
{ TSpTBXMRUListItem }
procedure TSpTBXMRUListItem.ClickHandler(Sender: TObject);
var
I: Integer;
A: TSpTBXMRUItem;
begin
if Sender is TSpTBXMRUItem then begin
A := TSpTBXMRUItem(Sender);
I := IndexOf(A);
if I > 0 then
Move(I, 0);
MRUUpdateCaptions;
if Assigned(FOnClick) then FOnClick(Self, A.MRUString);
end;
end;
constructor TSpTBXMRUListItem.Create(AOwner: TComponent);
begin
inherited;
ItemStyle := ItemStyle + [tbisEmbeddedGroup];
Caption := STBMRUListItemDefCaption;
Options := Options + [tboShowHint];
FMaxItems := 4;
FHidePathExtension := True;
end;
procedure TSpTBXMRUListItem.GetMRUFilenames(MRUFilenames: TStrings);
var
I: Integer;
begin
MRUFilenames.Clear;
for I := 0 to Count - 1 do
if Items[I] is TSpTBXMRUItem then
MRUFilenames.Add(TSpTBXMRUItem(Items[I]).MRUString);
end;
function TSpTBXMRUListItem.IndexOfMRU(Filename: WideString): Integer;
var
I: Integer;
begin
Result := -1;
for I := 0 to Count - 1 do
if Items[I] is TSpTBXMRUItem then
if SpSameText(TSpTBXMRUItem(Items[I]).MRUString, Filename) then begin
Result := I;
Break;
end;
end;
function TSpTBXMRUListItem.MRUAdd(Filename: WideString): Integer;
var
A: TSpTBXMRUItem;
I: Integer;
begin
Result := -1;
I := IndexOfMRU(Filename);
if I > -1 then begin
// If Filename is already in the MRU list, move it to the top
Move(I, 0);
MRUUpdateCaptions;
end
else begin
// Add the new Filename, if it exceeds the MaxItems limit delete the bottom items
A := TSpTBXMRUItem.Create(Self);
A.MRUString := Filename;
A.Hint := Filename;
A.OnClick := ClickHandler;
Insert(0, A);
while Count > FMaxItems do
Items[Count - 1].Free;
MRUUpdateCaptions;
Result := 0;
end;
end;
function TSpTBXMRUListItem.MRUClick(Filename: WideString): Boolean;
var
I: Integer;
begin
Result := False;
I := IndexOfMRU(Filename);
if I > -1 then begin
Items[I].Click;
Result := True;
end;
end;
procedure TSpTBXMRUListItem.MRURemove(Filename: WideString);
var
I: Integer;
begin
I := IndexOfMRU(Filename);
if I > -1 then begin
Items[I].Free;
MRUUpdateCaptions;
end;
end;
procedure TSpTBXMRUListItem.MRUUpdateCaptions;
var
I: Integer;
A: TSpTBXMRUItem;
S: WideString;
begin
for I := 0 to Count - 1 do
if Items[I] is TSpTBXMRUItem then begin
A := TSpTBXMRUItem(Items[I]);
S := A.MRUString;
if FHidePathExtension then begin
{$IFDEF UNICODE}
S := ExtractFileName(S);
{$ELSE}
S := TntSysUtils.WideExtractFileName(S);
{$ENDIF}
end;
A.Caption := '&' + IntToStr(I + 1) + ' ' + S;
end;
end;
procedure TSpTBXMRUListItem.LoadFromIni(Ini: TCustomIniFile; const Section: string);
var
I: Integer;
S: WideString;
begin
Clear;
for I := FMaxItems downto 1 do begin
S := Ini.ReadString(Section, IntToStr(I), '');
{$IFNDEF UNICODE}
S := UTF8Decode(S);
{$ENDIF}
if S <> '' then
MRUAdd(S);
end;
end;
procedure TSpTBXMRUListItem.SaveToIni(Ini: TCustomIniFile; const Section: string);
var
I: Integer;
A: TSpTBXMRUItem;
S: string;
L: TStringList;
begin
{$IFDEF UNICODE}
// If the IniFile doesn't exist create it with Unicode encoding
// otherwise we can't write Unicode strings.
if (Ini is TIniFile) and not FileExists(Ini.FileName) then begin
L := TStringList.Create;
try
L.SaveToFile(Ini.FileName, TEncoding.Unicode);
finally
L.Free;
end;
end;
{$ENDIF}
for I := 1 to FMaxItems do begin
if I <= Count then begin
A := TSpTBXMRUItem(Items[I - 1]);
{$IFDEF UNICODE}
S := A.MRUString;
{$ELSE}
S := UTF8Encode(A.MRUString);
{$ENDIF}
Ini.WriteString(Section, IntToStr(I), S);
end
else
Ini.DeleteKey(Section, IntToStr(I));
end;
end;
procedure TSpTBXMRUListItem.SetHidePathExtension(const Value: Boolean);
begin
if FHidePathExtension <> Value then begin
FHidePathExtension := Value;
MRUUpdateCaptions;
end;
end;
procedure TSpTBXMRUListItem.SetMaxItems(const Value: Integer);
begin
if FMaxItems <> Value then begin
FMaxItems := Value;
if Count > FMaxItems then begin
while Count > FMaxItems do
Items[Count - 1].Free;
MRUUpdateCaptions;
end;
end;
end;
end.