123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947 |
- unit TB2ExtItems;
- {
- Toolbar2000
- Copyright (C) 1998-2005 by Jordan Russell
- All rights reserved.
- The contents of this file are subject to the "Toolbar2000 License"; you may
- not use or distribute this file except in compliance with the
- "Toolbar2000 License". A copy of the "Toolbar2000 License" may be found in
- TB2k-LICENSE.txt or at:
- https://jrsoftware.org/files/tb2k/TB2k-LICENSE.txt
- Alternatively, the contents of this file may be used under the terms of the
- GNU General Public License (the "GPL"), in which case the provisions of the
- GPL are applicable instead of those in the "Toolbar2000 License". A copy of
- the GPL may be found in GPL-LICENSE.txt or at:
- https://jrsoftware.org/files/tb2k/GPL-LICENSE.txt
- If you wish to allow use of your version of this file only under the terms of
- the GPL and not to allow others to use your version of this file under the
- "Toolbar2000 License", indicate your decision by deleting the provisions
- above and replace them with the notice and other provisions required by the
- GPL. If you do not delete the provisions above, a recipient may use your
- version of this file under either the "Toolbar2000 License" or the GPL.
- $jrsoftware: tb2k/Source/TB2ExtItems.pas,v 1.63 2005/07/04 02:49:52 jr Exp $
- }
- interface
- {$I TB2Ver.inc}
- uses
- Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
- StdCtrls, CommCtrl, Menus, ActnList,
- TB2Item;
- type
- TTBEditItemOption = (tboUseEditWhenVertical);
- TTBEditItemOptions = set of TTBEditItemOption;
- const
- EditItemDefaultEditOptions = [];
- EditItemDefaultEditWidth = 64;
- { Change reasons for TTBEditItem.Text property }
- tcrSetProperty = 0; // direct assignment to TTBEditItem.Text property
- tcrActionLink = 1; // change comes from an action link
- tcrEditControl = 2; // change is caused by typing in edit area
- type
- TTBEditItem = class;
- TTBEditItemViewer = class;
- TTBAcceptTextEvent = procedure(Sender: TObject; var NewText: String;
- var Accept: Boolean) of object;
- TTBBeginEditEvent = procedure(Sender: TTBEditItem; Viewer: TTBEditItemViewer;
- EditControl: TEdit) of object;
- TTBEditAction = class(TAction)
- private
- FEditOptions: TTBEditItemOptions;
- FEditCaption: String;
- FEditWidth: Integer;
- FOnAcceptText: TTBAcceptTextEvent;
- FText: String;
- procedure SetEditCaption(Value: String);
- procedure SetEditOptions(Value: TTBEditItemOptions);
- procedure SetEditWidth(Value: Integer);
- procedure SetOnAcceptText(Value: TTBAcceptTextEvent);
- procedure SetText(Value: String);
- public
- constructor Create(AOwner: TComponent); override;
- published
- property EditCaption: String read FEditCaption write SetEditCaption;
- property EditOptions: TTBEditItemOptions read FEditOptions write SetEditOptions default EditItemDefaultEditOptions;
- property EditWidth: Integer read FEditWidth write SetEditWidth default EditItemDefaultEditWidth;
- property Text: String read FText write SetText;
- property OnAcceptText: TTBAcceptTextEvent read FOnAcceptText write SetOnAcceptText;
- end;
- TTBEditItemActionLink = class(TTBCustomItemActionLink)
- protected
- procedure AssignClient(AClient: TObject); override;
- function IsEditCaptionLinked: Boolean; virtual;
- function IsEditOptionsLinked: Boolean; virtual;
- function IsEditWidthLinked: Boolean; virtual;
- function IsOnAcceptTextLinked: Boolean; virtual;
- function IsTextLinked: Boolean; virtual;
- procedure SetEditCaption(const Value: String); virtual;
- procedure SetEditOptions(Value: TTBEditItemOptions); virtual;
- procedure SetEditWidth(const Value: Integer); virtual;
- procedure SetOnAcceptText(Value: TTBAcceptTextEvent); virtual;
- procedure SetText(const Value: String); virtual;
- end;
- TTBEditItem = class(TTBCustomItem)
- private
- FCharCase: TEditCharCase;
- FEditCaption: String;
- FEditOptions: TTBEditItemOptions;
- FEditWidth: Integer;
- FExtendedAccept: Boolean;
- FMaxLength: Integer;
- FOnAcceptText: TTBAcceptTextEvent;
- FOnBeginEdit: TTBBeginEditEvent;
- FText: String;
- function IsEditCaptionStored: Boolean;
- function IsEditOptionsStored: Boolean;
- function IsEditWidthStored: Boolean;
- function IsTextStored: Boolean;
- procedure SetCharCase(Value: TEditCharCase);
- procedure SetEditCaption(Value: String);
- procedure SetEditOptions(Value: TTBEditItemOptions);
- procedure SetEditWidth(Value: Integer);
- procedure SetMaxLength(Value: Integer);
- procedure SetText(Value: String);
- protected
- procedure ActionChange(Sender: TObject; CheckDefaults: Boolean); override;
- function DoAcceptText(var NewText: string): Boolean; virtual;
- procedure DoBeginEdit(Viewer: TTBEditItemViewer); virtual;
- procedure DoTextChanging(const OldText: String; var NewText: String; Reason: Integer); virtual;
- procedure DoTextChanged(Reason: Integer); virtual;
- function GetActionLinkClass: TTBCustomItemActionLinkClass; override;
- function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; override;
- function NeedToRecreateViewer(AViewer: TTBItemViewer): Boolean; override;
- property ExtendedAccept: Boolean read FExtendedAccept write FExtendedAccept default False;
- procedure SetTextEx(Value: String; Reason: Integer);
- public
- constructor Create(AOwner: TComponent); override;
- procedure Clear;
- procedure Click; override;
- procedure ChangeScale(M, D: Integer); override;
- published
- property Action;
- property AutoCheck;
- property Caption;
- property CharCase: TEditCharCase read FCharCase write SetCharCase default ecNormal;
- property Checked;
- property DisplayMode;
- property EditCaption: String read FEditCaption write SetEditCaption stored IsEditCaptionStored;
- property EditOptions: TTBEditItemOptions read FEditOptions write SetEditOptions stored IsEditOptionsStored;
- property EditWidth: Integer read FEditWidth write SetEditWidth stored IsEditWidthStored;
- property MaxLength: Integer read FMaxLength write SetMaxLength default 0;
- property Enabled;
- property GroupIndex;
- property HelpContext;
- { MP }
- property HelpKeyword;
- property Hint;
- property ImageIndex;
- property RadioItem;
- property ShortCut;
- property Text: String read FText write SetText stored IsTextStored;
- property Visible;
- property OnAcceptText: TTBAcceptTextEvent read FOnAcceptText write FOnAcceptText;
- property OnBeginEdit: TTBBeginEditEvent read FOnBeginEdit write FOnBeginEdit;
- property OnClick;
- property OnSelect;
- end;
- TEditClass = class of TEdit;
- TTBEditItemViewer = class(TTBItemViewer)
- private
- FEditControl: TEdit;
- FEditControlStatus: set of (ecsContinueLoop, ecsAccept, ecsClose);
- function EditLoop(const CapHandle: HWND): Boolean;
- procedure EditWndProc(var Message: TMessage);
- procedure MouseBeginEdit;
- protected
- procedure CalcSize(const Canvas: TCanvas; var AWidth, AHeight: Integer);
- override;
- function CaptionShown: Boolean; override;
- function DoExecute: Boolean; override;
- function GetAccRole: Integer; override;
- function GetAccValue(var Value: WideString): Boolean; override;
- function GetCaptionText: String; override;
- procedure GetCursor(const Pt: TPoint; var ACursor: HCURSOR); override;
- function GetEditControlClass: TEditClass; virtual;
- procedure GetEditRect(var R: TRect); virtual;
- procedure MouseDown(Shift: TShiftState; X, Y: Integer;
- var MouseDownOnMenu: Boolean); override;
- procedure MouseUp(X, Y: Integer; MouseWasDownOnMenu: Boolean); override;
- procedure Paint(const Canvas: TCanvas; const ClientAreaRect: TRect;
- IsSelected, IsPushed, UseDisabledShadow: Boolean); override;
- function UsesSameWidth: Boolean; override;
- public
- property EditControl: TEdit read FEditControl;
- end;
- implementation
- uses
- TB2Common, TB2Consts;
- const
- EditMenuTextMargin = 3;
- EditMenuMidWidth = 4;
- type
- TControlAccess = class(TControl);
- TEditAccess = class(TEdit);
- { TTBEditAction }
- constructor TTBEditAction.Create(AOwner: TComponent);
- begin
- inherited;
- FEditOptions := EditItemDefaultEditOptions;
- FEditWidth := EditItemDefaultEditWidth;
- DisableIfNoHandler := False;
- end;
- procedure TTBEditAction.SetEditCaption(Value: String);
- var
- I: Integer;
- begin
- if FEditCaption <> Value then begin
- for I := 0 to ClientCount - 1 do
- if TBasicActionLink(Clients[I]) is TTBEditItemActionLink then
- TTBEditItemActionLink(Clients[I]).SetEditCaption(Value);
- FEditCaption := Value;
- Change;
- end;
- end;
- procedure TTBEditAction.SetEditOptions(Value: TTBEditItemOptions);
- var
- I: Integer;
- begin
- if FEditOptions <> Value then begin
- for I := 0 to ClientCount - 1 do
- if TBasicActionLink(Clients[I]) is TTBEditItemActionLink then
- TTBEditItemActionLink(Clients[I]).SetEditOptions(Value);
- FEditOptions := Value;
- Change;
- end;
- end;
- procedure TTBEditAction.SetEditWidth(Value: Integer);
- var
- I: Integer;
- begin
- if FEditWidth <> Value then begin
- for I := 0 to ClientCount - 1 do
- if TBasicActionLink(Clients[I]) is TTBEditItemActionLink then
- TTBEditItemActionLink(Clients[I]).SetEditWidth(Value);
- FEditWidth := Value;
- Change;
- end;
- end;
- procedure TTBEditAction.SetOnAcceptText(Value: TTBAcceptTextEvent);
- var
- I: Integer;
- begin
- if not MethodsEqual(TMethod(FOnAcceptText), TMethod(Value)) then begin
- for I := 0 to ClientCount - 1 do
- if TBasicActionLink(Clients[I]) is TTBEditItemActionLink then
- TTBEditItemActionLink(Clients[I]).SetOnAcceptText(Value);
- FOnAcceptText := Value;
- Change;
- end;
- end;
- procedure TTBEditAction.SetText(Value: String);
- var
- I: Integer;
- begin
- if FText <> Value then begin
- for I := 0 to ClientCount - 1 do
- if TBasicActionLink(Clients[I]) is TTBEditItemActionLink then
- TTBEditItemActionLink(Clients[I]).SetText(Value);
- FText := Value;
- Change;
- end;
- end;
- { TTBEditItemActionLink }
- procedure TTBEditItemActionLink.AssignClient(AClient: TObject);
- begin
- FClient := AClient as TTBEditItem;
- end;
- function TTBEditItemActionLink.IsEditCaptionLinked: Boolean;
- begin
- if Action is TTBEditAction then
- Result := TTBEditItem(FClient).EditCaption = TTBEditAction(Action).EditCaption
- else
- Result := False;
- end;
- function TTBEditItemActionLink.IsEditOptionsLinked: Boolean;
- begin
- if Action is TTBEditAction then
- Result := TTBEditItem(FClient).EditOptions = TTBEditAction(Action).EditOptions
- else
- Result := False;
- end;
- function TTBEditItemActionLink.IsEditWidthLinked: Boolean;
- begin
- if Action is TTBEditAction then
- Result := TTBEditItem(FClient).EditWidth = TTBEditAction(Action).EditWidth
- else
- Result := False;
- end;
- function TTBEditItemActionLink.IsOnAcceptTextLinked: Boolean;
- begin
- if Action is TTBEditAction then
- Result := MethodsEqual(TMethod(TTBEditItem(FClient).OnAcceptText),
- TMethod(TTBEditAction(Action).OnAcceptText))
- else
- Result := False;
- end;
- function TTBEditItemActionLink.IsTextLinked: Boolean;
- begin
- if Action is TTBEditAction then
- Result := TTBEditItem(FClient).Text = TTBEditAction(Action).Text
- else
- Result := False;
- end;
- procedure TTBEditItemActionLink.SetEditCaption(const Value: String);
- begin
- if IsEditCaptionLinked then TTBEditItem(FClient).EditCaption := Value;
- end;
- procedure TTBEditItemActionLink.SetEditOptions(Value: TTBEditItemOptions);
- begin
- if IsEditOptionsLinked then TTBEditItem(FClient).EditOptions := Value;
- end;
- procedure TTBEditItemActionLink.SetEditWidth(const Value: Integer);
- begin
- if IsEditWidthLinked then TTBEditItem(FClient).EditWidth := Value;
- end;
- procedure TTBEditItemActionLink.SetOnAcceptText(Value: TTBAcceptTextEvent);
- begin
- if IsOnAcceptTextLinked then TTBEditItem(FClient).OnAcceptText := Value;
- end;
- procedure TTBEditItemActionLink.SetText(const Value: String);
- begin
- if IsTextLinked then TTBEditItem(FClient).SetTextEx(Value , tcrActionLink);
- end;
- { TTBEditItem }
- constructor TTBEditItem.Create(AOwner: TComponent);
- begin
- inherited;
- FEditOptions := EditItemDefaultEditOptions;
- FEditWidth := EditItemDefaultEditWidth;
- end;
- procedure TTBEditItem.ActionChange(Sender: TObject; CheckDefaults: Boolean);
- begin
- inherited;
- if Action is TTBEditAction then
- with TTBEditAction(Sender) do
- begin
- if not CheckDefaults or (Self.EditCaption = '') then
- Self.EditCaption := EditCaption;
- if not CheckDefaults or (Self.EditOptions = []) then
- Self.EditOptions := EditOptions;
- if not CheckDefaults or (Self.Text = '') then
- Self.SetTextEx(Text, tcrActionLink);
- if not CheckDefaults or not Assigned(Self.OnAcceptText) then
- Self.OnAcceptText := OnAcceptText;
- end;
- end;
- function TTBEditItem.GetActionLinkClass: TTBCustomItemActionLinkClass;
- begin
- Result := TTBEditItemActionLink;
- end;
- function TTBEditItem.GetItemViewerClass(AView: TTBView): TTBItemViewerClass;
- begin
- if not(tboUseEditWhenVertical in EditOptions) and
- (AView.Orientation = tbvoVertical) then
- Result := inherited GetItemViewerClass(AView)
- else
- Result := TTBEditItemViewer;
- end;
- function TTBEditItem.NeedToRecreateViewer(AViewer: TTBItemViewer): Boolean;
- begin
- Result := GetItemViewerClass(AViewer.View) <> AViewer.ClassType;
- end;
- procedure TTBEditItem.Clear;
- begin
- Text := '';
- end;
- procedure TTBEditItem.Click;
- begin
- inherited;
- end;
- procedure TTBEditItem.DoBeginEdit(Viewer: TTBEditItemViewer);
- begin
- if Assigned(FOnBeginEdit) then
- FOnBeginEdit(Self, Viewer, Viewer.EditControl);
- end;
- function TTBEditItem.IsEditOptionsStored: Boolean;
- begin
- Result := (EditOptions <> EditItemDefaultEditOptions) and
- ((ActionLink = nil) or not(ActionLink is TTBEditItemActionLink) or
- not TTBEditItemActionLink(ActionLink).IsEditOptionsLinked);
- end;
- function TTBEditItem.IsEditCaptionStored: Boolean;
- begin
- Result := (ActionLink = nil) or not(ActionLink is TTBEditItemActionLink) or
- not TTBEditItemActionLink(ActionLink).IsEditCaptionLinked;
- end;
- function TTBEditItem.IsEditWidthStored: Boolean;
- begin
- Result := (EditWidth <> EditItemDefaultEditWidth) and
- ((ActionLink = nil) or not(ActionLink is TTBEditItemActionLink) or
- not TTBEditItemActionLink(ActionLink).IsEditWidthLinked);
- end;
- function TTBEditItem.IsTextStored: Boolean;
- begin
- Result := (ActionLink = nil) or not(ActionLink is TTBEditItemActionLink) or
- not TTBEditItemActionLink(ActionLink).IsTextLinked;
- end;
- procedure TTBEditItem.SetCharCase(Value: TEditCharCase);
- begin
- if FCharCase <> Value then begin
- FCharCase := Value;
- Text := Text; { update case }
- end;
- end;
- procedure TTBEditItem.SetEditOptions(Value: TTBEditItemOptions);
- begin
- if FEditOptions <> Value then begin
- FEditOptions := Value;
- Change(True);
- end;
- end;
- procedure TTBEditItem.SetEditCaption(Value: String);
- begin
- if FEditCaption <> Value then begin
- FEditCaption := Value;
- Change(True);
- end;
- end;
- procedure TTBEditItem.SetEditWidth(Value: Integer);
- begin
- if FEditWidth <> Value then begin
- FEditWidth := Value;
- Change(True);
- end;
- end;
- procedure TTBEditItem.SetMaxLength(Value: Integer);
- begin
- if FMaxLength <> Value then begin
- FMaxLength := Value;
- Change(False);
- end;
- end;
- function TTBEditItem.DoAcceptText(var NewText: string): Boolean;
- begin
- Result := True;
- if Assigned(FOnAcceptText) then FOnAcceptText(Self, NewText, Result);
- end;
- procedure TTBEditItem.DoTextChanging(const OldText: String; var NewText: String; Reason: Integer);
- begin
- case FCharCase of
- ecUpperCase: NewText := AnsiUpperCase(NewText);
- ecLowerCase: NewText := AnsiLowerCase(NewText);
- end;
- end;
- procedure TTBEditItem.DoTextChanged(Reason: Integer);
- begin
- end;
- procedure TTBEditItem.SetText(Value: String);
- begin
- DoTextChanging(FText, Value, tcrSetProperty);
- if FText <> Value then begin
- FText := Value;
- Change(False);
- DoTextChanged(tcrSetProperty);
- end;
- end;
- procedure TTBEditItem.SetTextEx(Value: String; Reason: Integer);
- begin
- DoTextChanging(FText, Value, Reason);
- if FText <> Value then begin
- FText := Value;
- Change(False);
- DoTextChanged(Reason);
- end;
- end;
- procedure TTBEditItem.ChangeScale(M, D: Integer);
- begin
- inherited;
- EditWidth := MulDiv(EditWidth, M, D);
- end;
- { TTBEditItemViewer }
- procedure TTBEditItemViewer.EditWndProc(var Message: TMessage);
- var
- Item: TTBEditItem;
- procedure AcceptText;
- var
- S: String;
- begin
- S := FEditControl.Text;
- if Item.DoAcceptText(S) then Item.SetTextEx(S, tcrEditControl);
- end;
- begin
- Item := TTBEditItem(Self.Item);
- if FEditControl = nil then
- Exit;
- if Message.Msg = WM_CHAR then
- case TWMChar(Message).CharCode of
- VK_TAB: begin
- FEditControlStatus := [ecsAccept];
- AcceptText;
- Exit;
- end;
- VK_RETURN: begin
- FEditControlStatus := [ecsAccept, ecsClose];
- AcceptText;
- Exit;
- end;
- VK_ESCAPE: begin
- FEditControlStatus := [];
- Exit;
- end;
- end;
- TEditAccess(FEditControl).WndProc(Message);
- if Message.Msg = WM_KILLFOCUS then begin
- { Someone has stolen the focus from us, so 'cancel mode'. (We have to
- handle WM_KILLFOCUS in addition to the upstream WM_CANCELMODE handling
- since we don't always hold the mouse capture.) }
- View.CancelMode;
- FEditControlStatus := [ecsClose];
- end;
- end;
- function TTBEditItemViewer.GetEditControlClass: TEditClass;
- begin
- Result := TEdit;
- end;
- procedure TTBEditItemViewer.GetEditRect(var R: TRect);
- var
- Item: TTBEditItem;
- DC: HDC;
- begin
- Item := TTBEditItem(Self.Item);
- DC := GetDC(0);
- try
- SelectObject(DC, View.GetFont.Handle);
- R := BoundsRect;
- if not View.IsToolbar and (Item.EditCaption <> '') then begin
- Inc(R.Left, GetTextWidth(DC, Item.EditCaption, True) +
- EditMenuMidWidth + EditMenuTextMargin * 2);
- end;
- finally
- ReleaseDC(0, DC);
- end;
- end;
- procedure TTBEditItemViewer.CalcSize(const Canvas: TCanvas;
- var AWidth, AHeight: Integer);
- var
- Item: TTBEditItem;
- DC: HDC;
- TextHeight, MinHeight: Integer;
- begin
- Item := TTBEditItem(Self.Item);
- DC := Canvas.Handle;
- TextHeight := GetTextHeight(DC);
- AWidth := Item.FEditWidth;
- AHeight := TextHeight;
- if not IsToolbarStyle and (Item.EditCaption <> '') then begin
- Inc(AWidth, GetTextWidth(DC, Item.EditCaption, True) + EditMenuMidWidth +
- EditMenuTextMargin * 2);
- end;
- MinHeight := AHeight + (EditMenuTextMargin * 2) + 1;
- if not IsToolbarStyle then
- Inc(AHeight, DivRoundUp(AHeight, 4));
- if AHeight < MinHeight then
- AHeight := MinHeight;
- end;
- function TTBEditItemViewer.CaptionShown: Boolean;
- begin
- Result := not IsToolbarStyle and inherited CaptionShown;
- end;
- function TTBEditItemViewer.GetCaptionText: String;
- begin
- Result := TTBEditItem(Item).EditCaption;
- end;
- procedure TTBEditItemViewer.Paint(const Canvas: TCanvas;
- const ClientAreaRect: TRect; IsSelected, IsPushed, UseDisabledShadow: Boolean);
- const
- FillColors: array[Boolean] of TColor = (clBtnFace, clWindow);
- TextColors: array[Boolean] of TColor = (clGrayText, clWindowText);
- var
- Item: TTBEditItem;
- S: String;
- R: TRect;
- W: Integer;
- begin
- Item := TTBEditItem(Self.Item);
- R := ClientAreaRect;
- { Caption }
- if not IsToolbarStyle and (Item.EditCaption <> '') then begin
- S := Item.EditCaption;
- W := GetTextWidth(Canvas.Handle, S, True) + EditMenuTextMargin * 2;
- R.Right := R.Left + W;
- if IsSelected then
- Canvas.FillRect(R);
- Inc(R.Left, EditMenuTextMargin);
- DrawItemCaption(Canvas, R, S, UseDisabledShadow, DT_SINGLELINE or
- DT_LEFT or DT_VCENTER);
- R := ClientAreaRect;
- Inc(R.Left, W + EditMenuMidWidth);
- end;
- { Border }
- if IsSelected and Item.Enabled then
- DrawEdge(Canvas.Handle, R, BDR_SUNKENOUTER, BF_RECT);
- InflateRect(R, -1, -1);
- Canvas.Brush.Color := FillColors[not Item.Enabled];
- Canvas.FrameRect(R);
- InflateRect(R, -1, -1);
- { Fill }
- Canvas.Brush.Color := FillColors[Item.Enabled];
- Canvas.FillRect(R);
- InflateRect(R, -1, -1);
- { Text }
- if Item.Text <> '' then begin
- S := Item.Text;
- Canvas.Brush.Style := bsClear; { speed optimization }
- Canvas.Font.Color := TextColors[Item.Enabled];
- DrawText(Canvas.Handle, PChar(S), Length(S), R, DT_SINGLELINE or DT_NOPREFIX);
- end;
- end;
- procedure TTBEditItemViewer.GetCursor(const Pt: TPoint; var ACursor: HCURSOR);
- var
- R: TRect;
- begin
- if not Item.Enabled then
- Exit;
- GetEditRect(R);
- OffsetRect(R, -BoundsRect.Left, -BoundsRect.Top);
- InflateRect(R, -2, -2);
- if PtInRect(R, Pt) then
- ACursor := LoadCursor(0, IDC_IBEAM);
- end;
- function TTBEditItemViewer.EditLoop(const CapHandle: HWND): Boolean;
- procedure ControlMessageLoop;
- function PointInWindow(const Wnd: HWND; const P: TPoint): Boolean;
- var
- W: HWND;
- begin
- Result := False;
- W := WindowFromPoint(P);
- if W = 0 then Exit;
- if W = Wnd then
- Result := True
- else
- if IsChild(Wnd, W) then
- Result := True;
- end;
- function ContinueLoop: Boolean;
- begin
- Result := (ecsContinueLoop in FEditControlStatus) and
- not View.IsModalEnding and FEditControl.Focused and Item.Enabled;
- { Note: View.IsModalEnding is checked since TTBView.CancelMode doesn't
- destroy popup windows; it merely hides them and calls EndModal. So if
- IsModalEnding returns True we can infer that CancelMode was likely
- called. }
- end;
- var
- Msg: TMsg;
- IsKeypadDigit: Boolean;
- V: Integer;
- begin
- try
- while ContinueLoop do begin
- { Examine the next message before popping it out of the queue }
- if not PeekMessage(Msg, 0, 0, 0, PM_NOREMOVE) then begin
- WaitMessage;
- Continue;
- end;
- case Msg.message of
- WM_SYSKEYDOWN: begin
- { Exit immediately if Alt+[key] or F10 are pressed, but not
- Alt+Shift, Alt+`, or Alt+[keypad digit] }
- if (Msg.wParam <> VK_MENU) and (Msg.wParam <> VK_SHIFT) and
- (Msg.wParam <> VK_HANJA) then begin
- IsKeypadDigit := False;
- { This detect digits regardless of whether Num Lock is on: }
- if Lo(LongRec(Msg.lParam).Hi) <> 0 then
- for V := VK_NUMPAD0 to VK_NUMPAD9 do
- if MapVirtualKey(V, 0) = Lo(LongRec(Msg.lParam).Hi) then begin
- IsKeypadDigit := True;
- Break;
- end;
- if not IsKeypadDigit then begin
- FEditControlStatus := [ecsClose];
- Exit;
- end;
- end;
- end;
- WM_SYSKEYUP: begin
- { Exit when Alt is released by itself }
- if Msg.wParam = VK_MENU then begin
- FEditControlStatus := [ecsClose];
- Exit;
- end;
- end;
- WM_LBUTTONDOWN, WM_LBUTTONDBLCLK,
- WM_RBUTTONDOWN, WM_RBUTTONDBLCLK,
- WM_MBUTTONDOWN, WM_MBUTTONDBLCLK,
- WM_NCLBUTTONDOWN, WM_NCLBUTTONDBLCLK,
- WM_NCRBUTTONDOWN, WM_NCRBUTTONDBLCLK,
- WM_NCMBUTTONDOWN, WM_NCMBUTTONDBLCLK: begin
- { If a mouse click outside the edit control is in the queue,
- exit and let the upstream message loop deal with it }
- if Msg.hwnd <> FEditControl.Handle then
- Exit;
- end;
- WM_MOUSEMOVE, WM_NCMOUSEMOVE: begin
- if GetCapture = CapHandle then begin
- if PointInWindow(FEditControl.Handle, Msg.pt) then
- ReleaseCapture;
- end
- else if GetCapture = 0 then begin
- if not PointInWindow(FEditControl.Handle, Msg.pt) then
- SetCapture(CapHandle);
- end;
- if GetCapture = CapHandle then
- SetCursor(LoadCursor(0, IDC_ARROW));
- end;
- end;
- { Now pop the message out of the queue }
- if not PeekMessage(Msg, 0, Msg.message, Msg.message, PM_REMOVE or PM_NOYIELD) then
- Continue;
- if ((Msg.message >= WM_MOUSEFIRST) and (Msg.message <= WM_MOUSELAST)) and
- (Msg.hwnd = CapHandle) then
- { discard, so that the selection doesn't get changed }
- else begin
- TranslateMessage(Msg);
- DispatchMessage(Msg);
- end;
- end;
- finally
- { Make sure there are no outstanding WM_*CHAR messages }
- RemoveMessages(WM_CHAR, WM_DEADCHAR);
- RemoveMessages(WM_SYSCHAR, WM_SYSDEADCHAR);
- end;
- end;
- var
- Item: TTBEditItem;
- R: TRect;
- ActiveWnd, FocusWnd: HWND;
- S: string;
- begin
- Item := TTBEditItem(Self.Item);
- GetEditRect(R);
- if IsRectEmpty(R) then begin
- Result := False;
- Exit;
- end;
- ActiveWnd := GetActiveWindow;
- FocusWnd := GetFocus;
- { Create the edit control }
- InflateRect(R, -3, -4);
- //View.FreeNotification (Self);
- FEditControl := GetEditControlClass.Create(nil);
- try
- FEditControl.Name := Format('%s_edit_control_%p', [ClassName,
- Pointer(FEditControl)]);
- FEditControl.Visible := False;
- FEditControl.BorderStyle := bsNone;
- FEditControl.AutoSize := False;
- FEditControl.Font.Assign(View.GetFont);
- FEditControl.Text := Item.Text;
- FEditControl.CharCase := Item.FCharCase;
- FEditControl.MaxLength := Item.FMaxLength;
- FEditControl.BoundsRect := R;
- FEditControl.WindowProc := EditWndProc;
- FEditControl.ParentWindow := View.Window.Handle;
- FEditControl.SelectAll;
- Item.DoBeginEdit(Self);
- FEditControl.Visible := True;
- FEditControl.SetFocus;
- if GetActiveWindow <> ActiveWnd then
- { don't gray out title bar of old active window }
- SendMessage(ActiveWnd, WM_NCACTIVATE, 1, 0)
- else
- ActiveWnd := 0;
- FEditControlStatus := [ecsContinueLoop];
- // During modal state of the toolbar, Windows logo key is not working.
- // It should be fixed more generically, but here we fix it at least for the most obvious case (= while in edit box)
- TTBModalHandler.UnlockForegroundWindow;
- ControlMessageLoop;
- finally
- TTBModalHandler.LockForegroundWindow;
- S := FEditControl.Text;
- FreeAndNil(FEditControl);
- end;
- with TTBEditItem(Item) do
- if (FEditControlStatus = [ecsContinueLoop]) and ExtendedAccept then
- if DoAcceptText(S) then SetTextEx(S, tcrEditControl);
- { ensure the area underneath the edit control is repainted immediately }
- View.Window.Update;
- { If app is still active, set focus to previous control and restore capture
- to CapHandle if another control hasn't taken it }
- if GetActiveWindow <> 0 then begin
- SetFocus(FocusWnd);
- if GetCapture = 0 then
- SetCapture(CapHandle);
- end;
- if ActiveWnd <> 0 then
- SendMessage(ActiveWnd, WM_NCACTIVATE, Ord(GetActiveWindow = ActiveWnd), 0);
- { The SetFocus call above can change the Z order of windows. If the parent
- window is a popup window, reassert its topmostness. }
- if View.Window is TTBPopupWindow then
- SetWindowPos(View.Window.Handle, HWND_TOPMOST, 0, 0, 0, 0,
- SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE);
- { Send an MSAA "focus" event now that we're returning to the regular modal loop }
- View.NotifyFocusEvent;
- Result := ecsClose in FEditControlStatus;
- if not Result and (GetCapture = CapHandle) then begin
- if ecsAccept in FEditControlStatus then
- { if we are accepting but not closing, Tab must have been pressed }
- View.Selected := View.NextSelectable(View.Selected,
- GetKeyState(VK_SHIFT) >= 0);
- end;
- end;
- function TTBEditItemViewer.DoExecute: Boolean;
- begin
- { Close any delay-close popup menus before entering the edit loop }
- View.CancelChildPopups;
- Result := False;
- if EditLoop(View.GetCaptureWnd) then begin
- View.EndModal;
- if ecsAccept in FEditControlStatus then
- Result := True;
- end;
- end;
- procedure TTBEditItemViewer.MouseBeginEdit;
- begin
- if Item.Enabled then
- Execute(True)
- else begin
- if (View.ParentView = nil) and not View.IsPopup then
- View.EndModal;
- end;
- end;
- procedure TTBEditItemViewer.MouseDown(Shift: TShiftState; X, Y: Integer;
- var MouseDownOnMenu: Boolean);
- begin
- if IsPtInButtonPart(X, Y) then { for TBX... }
- MouseBeginEdit
- else
- inherited;
- end;
- procedure TTBEditItemViewer.MouseUp(X, Y: Integer; MouseWasDownOnMenu: Boolean);
- begin
- if IsPtInButtonPart(X, Y) then { for TBX... }
- MouseBeginEdit
- else
- inherited;
- end;
- function TTBEditItemViewer.UsesSameWidth: Boolean;
- begin
- Result := False;
- end;
- function TTBEditItemViewer.GetAccRole: Integer;
- const
- ROLE_SYSTEM_TEXT = $2a; { from OleAcc.h }
- begin
- Result := ROLE_SYSTEM_TEXT;
- end;
- function TTBEditItemViewer.GetAccValue(var Value: WideString): Boolean;
- begin
- Value := TTBEditItem(Item).Text;
- Result := True;
- end;
- end.
|