git-svn-id: https://192.168.0.254/svn/Componentes.Terceros.DevExpressVCL@63 05c56307-c608-d34a-929d-697000501d7a
5939 lines
178 KiB
ObjectPascal
5939 lines
178 KiB
ObjectPascal
|
|
{********************************************************************}
|
|
{ }
|
|
{ Developer Express Visual Component Library }
|
|
{ ExpressEditors }
|
|
{ }
|
|
{ Copyright (c) 1998-2009 Developer Express Inc. }
|
|
{ ALL RIGHTS RESERVED }
|
|
{ }
|
|
{ The entire contents of this file is protected by U.S. and }
|
|
{ International Copyright Laws. Unauthorized reproduction, }
|
|
{ reverse-engineering, and distribution of all or any portion of }
|
|
{ the code contained in this file is strictly prohibited and may }
|
|
{ result in severe civil and criminal penalties and will be }
|
|
{ prosecuted to the maximum extent possible under the law. }
|
|
{ }
|
|
{ RESTRICTIONS }
|
|
{ }
|
|
{ THIS SOURCE CODE AND ALL RESULTING INTERMEDIATE FILES }
|
|
{ (DCU, OBJ, DLL, ETC.) ARE CONFIDENTIAL AND PROPRIETARY TRADE }
|
|
{ SECRETS OF DEVELOPER EXPRESS INC. THE REGISTERED DEVELOPER IS }
|
|
{ LICENSED TO DISTRIBUTE THE EXPRESSEDITORS AND ALL }
|
|
{ ACCOMPANYING VCL CONTROLS AS PART OF AN EXECUTABLE PROGRAM ONLY. }
|
|
{ }
|
|
{ THE SOURCE CODE CONTAINED WITHIN THIS FILE AND ALL RELATED }
|
|
{ FILES OR ANY PORTION OF ITS CONTENTS SHALL AT NO TIME BE }
|
|
{ COPIED, TRANSFERRED, SOLD, DISTRIBUTED, OR OTHERWISE MADE }
|
|
{ AVAILABLE TO OTHER INDIVIDUALS WITHOUT EXPRESS WRITTEN CONSENT }
|
|
{ AND PERMISSION FROM DEVELOPER EXPRESS INC. }
|
|
{ }
|
|
{ CONSULT THE END USER LICENSE AGREEMENT FOR INFORMATION ON }
|
|
{ ADDITIONAL RESTRICTIONS. }
|
|
{ }
|
|
{********************************************************************}
|
|
|
|
unit cxTextEdit;
|
|
|
|
{$I cxVer.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
Windows, Messages,
|
|
{$IFDEF DELPHI6}
|
|
Variants,
|
|
{$ENDIF}
|
|
Classes, Clipbrd, Controls, Forms, Graphics, Menus, StdCtrls, SysUtils, cxClasses,
|
|
cxContainer, cxControls, cxDataUtils, cxEdit, cxDrawTextUtils, cxFormats,
|
|
cxGraphics, cxVariants, cxFilterControlUtils;
|
|
|
|
const
|
|
cxEditDefaultDropDownPageRowCount = 8;
|
|
ekValueOutOfBounds = 1;
|
|
|
|
WM_SPELLCHECKERAUTOCORRECT: Cardinal = WM_DX + 101;
|
|
|
|
type
|
|
TcxEditEchoMode = (eemNormal, eemPassword);
|
|
TcxEditScrollCause = (escKeyboard, escMouseWheel);
|
|
TcxEditValueBound = (evbMin, evbMax);
|
|
TcxTextEditViewStyle = (vsNormal, vsHideCursor, vsButtonsOnly, vsButtonsAutoWidth);
|
|
TcxTextEditCustomDrawHandler = procedure(ACanvas: TcxCanvas; ARect: TRect) of object;
|
|
|
|
TcxCustomTextEdit = class;
|
|
|
|
IcxInnerTextEdit = interface(IcxCustomInnerEdit)
|
|
['{263EBB8D-1EA9-4CAC-8367-ADD74D2A9651}']
|
|
procedure ClearSelection;
|
|
procedure CopyToClipboard;
|
|
function GetAlignment: TAlignment;
|
|
function GetAutoSelect: Boolean;
|
|
function GetCharCase: TEditCharCase;
|
|
function GetEchoMode: TcxEditEchoMode;
|
|
function GetFirstVisibleCharIndex: Integer;
|
|
function GetHideSelection: Boolean;
|
|
function GetImeLastChar: Char;
|
|
function GetImeMode: TImeMode;
|
|
function GetImeName: TImeName;
|
|
function GetInternalUpdating: Boolean;
|
|
function GetMaxLength: Integer;
|
|
function GetMultiLine: Boolean;
|
|
function GetOEMConvert: Boolean;
|
|
function GetOnSelChange: TNotifyEvent;
|
|
function GetPasswordChar: TCaptionChar;
|
|
function GetSelLength: Integer;
|
|
function GetSelStart: Integer;
|
|
function GetSelText: string;
|
|
procedure SelectAll;
|
|
procedure SetAlignment(Value: TAlignment);
|
|
procedure SetAutoSelect(Value: Boolean);
|
|
procedure SetCharCase(Value: TEditCharCase);
|
|
procedure SetEchoMode(Value: TcxEditEchoMode);
|
|
procedure SetHideSelection(Value: Boolean);
|
|
procedure SetInternalUpdating(Value: Boolean);
|
|
procedure SetImeMode(Value: TImeMode);
|
|
procedure SetImeName(const Value: TImeName);
|
|
procedure SetMaxLength(Value: Integer);
|
|
procedure SetOEMConvert(Value: Boolean);
|
|
procedure SetOnSelChange(Value: TNotifyEvent);
|
|
procedure SetPasswordChar(Value: TCaptionChar);
|
|
procedure SetSelLength(Value: Integer);
|
|
procedure SetSelStart(Value: Integer);
|
|
procedure SetSelText(Value: string);
|
|
{$IFDEF DELPHI12}
|
|
function GetTextHint: string;
|
|
procedure SetTextHint(Value: string);
|
|
{$ENDIF}
|
|
property Alignment: TAlignment read GetAlignment write SetAlignment;
|
|
property AutoSelect: Boolean read GetAutoSelect write SetAutoSelect;
|
|
property CharCase: TEditCharCase read GetCharCase write SetCharCase;
|
|
property EchoMode: TcxEditEchoMode read GetEchoMode write SetEchoMode;
|
|
property HideSelection: Boolean read GetHideSelection write SetHideSelection;
|
|
property ImeLastChar: Char read GetImeLastChar;
|
|
property ImeMode: TImeMode read GetImeMode write SetImeMode;
|
|
property ImeName: TImeName read GetImeName write SetImeName;
|
|
property InternalUpdating: Boolean read GetInternalUpdating write SetInternalUpdating;
|
|
property MaxLength: Integer read GetMaxLength write SetMaxLength;
|
|
property MultiLine: Boolean read GetMultiLine;
|
|
property OEMConvert: Boolean read GetOEMConvert write SetOEMConvert;
|
|
property PasswordChar: TCaptionChar read GetPasswordChar write SetPasswordChar;
|
|
property SelLength: Integer read GetSelLength write SetSelLength;
|
|
property SelStart: Integer read GetSelStart write SetSelStart;
|
|
property SelText: string read GetSelText write SetSelText;
|
|
{$IFDEF DELPHI12}
|
|
property TextHint: string read GetTextHint write SetTextHint;
|
|
{$ENDIF}
|
|
property OnSelChange: TNotifyEvent read GetOnSelChange write SetOnSelChange;
|
|
end;
|
|
|
|
{ TcxCustomInnerTextEditHelper }
|
|
|
|
TcxCustomInnerTextEdit = class;
|
|
|
|
TcxCustomInnerTextEditHelper = class(TcxInterfacedPersistent,
|
|
IcxContainerInnerControl, IcxCustomInnerEdit, IcxInnerTextEdit)
|
|
private
|
|
FAlignmentLock: Boolean;
|
|
FEdit: TcxCustomInnerTextEdit;
|
|
FSelLength: Integer;
|
|
FSelStart: Integer;
|
|
function GetUseLeftAlignmentOnEditing: Boolean;
|
|
protected
|
|
property Edit: TcxCustomInnerTextEdit read FEdit;
|
|
property UseLeftAlignmentOnEditing: Boolean read GetUseLeftAlignmentOnEditing;
|
|
public
|
|
constructor Create(AEdit: TcxCustomInnerTextEdit); reintroduce; virtual;
|
|
|
|
// IcxContainerInnerControl
|
|
function GetControlContainer: TcxContainer;
|
|
function GetControl: TWinControl;
|
|
|
|
// IcxCustomInnerEdit
|
|
function CallDefWndProc(AMsg: UINT; WParam: WPARAM;
|
|
LParam: LPARAM): LRESULT;
|
|
function GetEditValue: TcxEditValue;
|
|
function GetOnChange: TNotifyEvent;
|
|
procedure LockBounds(ALock: Boolean);
|
|
procedure SafelySetFocus;
|
|
procedure SetEditValue(const Value: TcxEditValue);
|
|
procedure SetParent(Value: TWinControl);
|
|
procedure SetOnChange(Value: TNotifyEvent);
|
|
|
|
// IcxInnerTextEdit
|
|
procedure ClearSelection;
|
|
procedure CopyToClipboard;
|
|
function GetAlignment: TAlignment;
|
|
function GetAutoSelect: Boolean;
|
|
function GetCharCase: TEditCharCase;
|
|
function GetEchoMode: TcxEditEchoMode;
|
|
function GetFirstVisibleCharIndex: Integer;
|
|
function GetHideSelection: Boolean;
|
|
function GetImeLastChar: Char;
|
|
function GetImeMode: TImeMode;
|
|
function GetImeName: TImeName;
|
|
function GetInternalUpdating: Boolean;
|
|
function GetIsInplace: Boolean;
|
|
function GetMaxLength: Integer;
|
|
function GetMultiLine: Boolean;
|
|
function GetOEMConvert: Boolean;
|
|
function GetOnSelChange: TNotifyEvent;
|
|
function GetPasswordChar: TCaptionChar;
|
|
function GetReadOnly: Boolean;
|
|
function GetSelLength: Integer;
|
|
function GetSelStart: Integer;
|
|
function GetSelText: string;
|
|
procedure SelectAll;
|
|
procedure SetAlignment(Value: TAlignment);
|
|
procedure SetAutoSelect(Value: Boolean);
|
|
procedure SetCharCase(Value: TEditCharCase);
|
|
procedure SetEchoMode(Value: TcxEditEchoMode);
|
|
procedure SetHideSelection(Value: Boolean);
|
|
procedure SetInternalUpdating(Value: Boolean);
|
|
procedure SetImeMode(Value: TImeMode);
|
|
procedure SetImeName(const Value: TImeName);
|
|
procedure SetMaxLength(Value: Integer);
|
|
procedure SetOEMConvert(Value: Boolean);
|
|
procedure SetOnSelChange(Value: TNotifyEvent);
|
|
procedure SetPasswordChar(Value: TCaptionChar);
|
|
procedure SetReadOnly(Value: Boolean);
|
|
procedure SetSelLength(Value: Integer);
|
|
procedure SetSelStart(Value: Integer);
|
|
procedure SetSelText(Value: string);
|
|
{$IFDEF DELPHI12}
|
|
function GetTextHint: string;
|
|
procedure SetTextHint(Value: string);
|
|
{$ENDIF}
|
|
end;
|
|
|
|
{ TcxCustomInnerTextEdit }
|
|
|
|
TcxCustomInnerTextEditPrevState = record
|
|
IsPrevTextSaved: Boolean;
|
|
PrevText: string;
|
|
PrevSelLength, PrevSelStart: Integer;
|
|
end;
|
|
|
|
TcxCustomInnerTextEdit = class(TCustomEdit, IUnknown,
|
|
IcxContainerInnerControl, IcxInnerEditHelper)
|
|
private
|
|
FAlignment: TAlignment;
|
|
FEchoMode: TcxEditEchoMode;
|
|
FDblClickLock: Boolean;
|
|
FDblClickTimer: TcxTimer;
|
|
FHelper: TcxCustomInnerTextEditHelper;
|
|
FImeCharCount: Integer;
|
|
FImeLastChar: Char;
|
|
FInternalUpdating: Boolean;
|
|
FIsCreating: Boolean;
|
|
FLockBoundsCount: Integer;
|
|
FPasswordChar: TCaptionChar;
|
|
FRepaintOnGlass: Boolean;
|
|
FOnSelChange: TNotifyEvent;
|
|
procedure DblClickTimerHandle(Sender: TObject);
|
|
function GetContainer: TcxCustomTextEdit;
|
|
function GetCursorPos: Integer;
|
|
function GetIsDestroying: Boolean;
|
|
procedure InitializeDblClickTimer;
|
|
procedure SetBasedAlignment;
|
|
function NeedAdjustAlignment: Boolean;
|
|
procedure UpdateEchoMode;
|
|
procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;
|
|
procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
|
|
procedure EMSetSel(var Message: TMessage); message EM_SETSEL;
|
|
procedure WMChar(var Message: TWMChar); message WM_CHAR;
|
|
procedure WMClear(var Message: TMessage); message WM_CLEAR;
|
|
procedure WMCut(var Message: TMessage); message WM_CUT;
|
|
procedure WMEraseBkgnd(var Message: TWMEraseBkgnd); message WM_ERASEBKGND;
|
|
procedure WMGetDlgCode(var Message: TWMGetDlgCode); message WM_GETDLGCODE;
|
|
procedure WMIMEChar(var Message: TMessage); message WM_IME_CHAR;
|
|
procedure WMIMEComposition(var Message: TMessage); message WM_IME_COMPOSITION;
|
|
procedure WMKeyDown(var Message: TWMKeyDown); message WM_KEYDOWN;
|
|
procedure WMKillFocus(var Message: TWMKillFocus); message WM_KILLFOCUS;
|
|
procedure WMNCPaint(var Message: TWMNCPaint); message WM_NCPAINT;
|
|
procedure WMPaste(var Message: TMessage); message WM_PASTE;
|
|
procedure WMSetFocus(var Message: TWMSetFocus); message WM_SETFOCUS;
|
|
procedure WMSize(var Message: TWMSize); message WM_SIZE;
|
|
procedure WMUndo(var Message: TWMSize); message WM_UNDO;
|
|
protected
|
|
procedure AdjustAlignment; virtual;
|
|
procedure Change; override; // for Delphi .NET
|
|
procedure Click; override;
|
|
procedure CreateHandle; override;
|
|
procedure CreateParams(var Params: TCreateParams); override;
|
|
procedure CreateWindowHandle(const Params: TCreateParams); override;
|
|
procedure CreateWnd; override;
|
|
procedure DblClick; override;
|
|
function DoMouseWheel(Shift: TShiftState; WheelDelta: Integer;
|
|
MousePos: TPoint): Boolean; override;
|
|
procedure DragOver(Source: TObject; X, Y: Integer; State: TDragState;
|
|
var Accept: Boolean); override;
|
|
function GetBasedAlignment: TAlignment;
|
|
procedure KeyDown(var Key: Word; Shift: TShiftState); override;
|
|
procedure KeyPress(var Key: Char); override;
|
|
procedure KeyUp(var Key: Word; Shift: TShiftState); override;
|
|
procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
|
|
X, Y: Integer); override;
|
|
procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
|
|
procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
|
|
X, Y: Integer); override;
|
|
procedure WndProc(var Message: TMessage); override;
|
|
procedure AdjustMargins; virtual;
|
|
procedure MouseEnter(AControl: TControl); dynamic;
|
|
procedure MouseLeave(AControl: TControl); dynamic;
|
|
procedure RecreateWnd; // for Delphi .NET
|
|
|
|
// IcxContainerInnerControl
|
|
function GetControl: TWinControl;
|
|
function GetControlContainer: TcxContainer;
|
|
|
|
// IcxInnerEditHelper
|
|
function GetHelper: IcxCustomInnerEdit;
|
|
|
|
property Alignment: TAlignment read FAlignment;
|
|
property Container: TcxCustomTextEdit read GetContainer;
|
|
property CursorPos: Integer read GetCursorPos;
|
|
property Helper: TcxCustomInnerTextEditHelper read FHelper;
|
|
property IsDestroying: Boolean read GetIsDestroying;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
procedure DragDrop(Source: TObject; X, Y: Integer); override;
|
|
function ExecuteAction(Action: TBasicAction): Boolean; override;
|
|
function UpdateAction(Action: TBasicAction): Boolean; override;
|
|
function CanFocus: Boolean; override;
|
|
procedure DefaultHandler(var Message); override;
|
|
procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override;
|
|
property AutoSelect;
|
|
property CharCase;
|
|
property HideSelection;
|
|
property ImeMode;
|
|
property ImeName;
|
|
property MaxLength;
|
|
property OEMConvert;
|
|
property ReadOnly;
|
|
property OnChange;
|
|
property OnSelChange: TNotifyEvent read FOnSelChange write FOnSelChange;
|
|
end;
|
|
|
|
{ TcxTextEditPropertiesValues }
|
|
|
|
TcxTextEditPropertiesValues = class(TcxCustomEditPropertiesValues)
|
|
private
|
|
FDisplayFormat: Boolean;
|
|
FEditFormat: Boolean;
|
|
FMaxLength: Boolean;
|
|
function IsDisplayFormatStored: Boolean;
|
|
function IsEditFormatStored: Boolean;
|
|
procedure SetDisplayFormat(Value: Boolean);
|
|
procedure SetEditFormat(Value: Boolean);
|
|
procedure SetMaxLength(Value: Boolean);
|
|
public
|
|
procedure Assign(Source: TPersistent); override;
|
|
procedure RestoreDefaults; override;
|
|
published
|
|
property DisplayFormat: Boolean read FDisplayFormat write SetDisplayFormat
|
|
stored IsDisplayFormatStored;
|
|
property EditFormat: Boolean read FEditFormat write SetEditFormat
|
|
stored IsEditFormatStored;
|
|
property MaxLength: Boolean read FMaxLength write SetMaxLength stored False;
|
|
property MaxValue;
|
|
property MinValue;
|
|
end;
|
|
|
|
{ TcxCustomEditListBox }
|
|
|
|
TcxCustomEditListBox = class(TcxCustomInnerListBox)
|
|
private
|
|
FHotTrack: Boolean;
|
|
FOnSelectItem: TNotifyEvent;
|
|
function GetEdit: TcxCustomTextEdit;
|
|
{$IFNDEF DELPHI6}
|
|
function GetItemIndex: Integer;
|
|
{$ENDIF}
|
|
procedure CMShowingChanged(var Message: TMessage); message CM_SHOWINGCHANGED;
|
|
protected
|
|
procedure Click; override;
|
|
function DoMouseWheel(Shift: TShiftState; WheelDelta: Integer;
|
|
MousePos: TPoint): Boolean; override;
|
|
procedure DrawItem(Index: Integer; Rect: TRect; State: TOwnerDrawState); override;
|
|
function GetItemData(Index: Integer): Longint; override;
|
|
function NeedDrawFocusRect: Boolean; override;
|
|
procedure MeasureItem(Index: Integer; var Height: Integer); override;
|
|
procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
|
|
procedure SetItemData(Index: Integer;
|
|
AData: Longint); override;
|
|
function DoDrawItem(AIndex: Integer; const ARect: TRect;
|
|
AState: TOwnerDrawState): Boolean; virtual;
|
|
procedure DoSelectItem;
|
|
function GetDefaultItemHeight: Integer;
|
|
function GetItem(Index: Integer): string; virtual;
|
|
procedure InternalRecreateWindow;
|
|
procedure RecreateWindow; virtual;
|
|
procedure SetItemCount(Value: Integer);
|
|
procedure SetItemIndex(const Value: Integer); {$IFDEF DELPHI6}override;{$ELSE}virtual;{$ENDIF}
|
|
property Edit: TcxCustomTextEdit read GetEdit;
|
|
property HotTrack: Boolean read FHotTrack write FHotTrack;
|
|
{$IFNDEF DELPHI6}
|
|
property ItemIndex: Integer read GetItemIndex write SetItemIndex;
|
|
{$ENDIF}
|
|
property OnSelectItem: TNotifyEvent read FOnSelectItem write FOnSelectItem;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
function GetHeight(ARowCount: Integer; AMaxHeight: Integer): Integer; virtual;
|
|
function GetItemHeight(AIndex: Integer = -1): Integer; virtual;
|
|
function GetItemWidth(AIndex: Integer): Integer; virtual;
|
|
function IsVisible: Boolean;
|
|
procedure SetScrollWidth(Value: Integer);
|
|
end;
|
|
|
|
TcxCustomEditListBoxClass = class of TcxCustomEditListBox;
|
|
|
|
{ IcxTextEditLookupData }
|
|
|
|
TcxEditLookupDataGoDirection = (egdBegin, egdEnd, egdNext, egdPrev, egdPageUp, egdPageDown);
|
|
|
|
IcxTextEditLookupData = interface
|
|
['{F49C5F08-7758-4362-A360-1DF02354E708}']
|
|
function CanResizeVisualArea(var NewSize: TSize;
|
|
AMaxHeight: Integer = 0; AMaxWidth: Integer = 0): Boolean;
|
|
procedure CloseUp;
|
|
procedure Deinitialize;
|
|
procedure DropDown;
|
|
procedure DroppedDown(const AFindStr: string);
|
|
function Find(const AText: string): Boolean;
|
|
function GetActiveControl: TControl;
|
|
function GetCurrentKey: TcxEditValue;
|
|
function GetDisplayText(const AKey: TcxEditValue): string; overload;
|
|
function GetOnCurrentKeyChanged: TNotifyEvent;
|
|
function GetOnSelectItem: TNotifyEvent;
|
|
function GetVisualAreaPreferredSize(AMaxHeight: Integer; AWidth: Integer = 0): TSize;
|
|
procedure Go(ADirection: TcxEditLookupDataGoDirection; ACircular: Boolean);
|
|
procedure Initialize(AVisualControlsParent: TWinControl);
|
|
function IsEmpty: Boolean;
|
|
function IsMouseOverList(const P: TPoint): Boolean;
|
|
function Locate(var AText, ATail: string; ANext: Boolean): Boolean;
|
|
procedure PositionVisualArea(const AClientRect: TRect);
|
|
procedure PropertiesChanged;
|
|
procedure SelectItem;
|
|
procedure SetCurrentKey(const AKey: TcxEditValue);
|
|
procedure SetOnCurrentKeyChanged(Value: TNotifyEvent);
|
|
procedure SetOnSelectItem(Value: TNotifyEvent);
|
|
procedure TextChanged;
|
|
property ActiveControl: TControl read GetActiveControl;
|
|
property CurrentKey: TcxEditValue read GetCurrentKey write SetCurrentKey;
|
|
property OnCurrentKeyChanged: TNotifyEvent read GetOnCurrentKeyChanged write SetOnCurrentKeyChanged;
|
|
property OnSelectItem: TNotifyEvent read GetOnSelectItem write SetOnSelectItem;
|
|
end;
|
|
|
|
{ TcxCustomTextEditLookupData }
|
|
|
|
TcxCustomTextEditProperties = class;
|
|
|
|
TcxCustomTextEditLookupData = class(TcxInterfacedPersistent, IcxTextEditLookupData)
|
|
private
|
|
FCurrentKey: Integer;
|
|
FItemIndex: Integer;
|
|
FList: TcxCustomEditListBox;
|
|
FOwner: TPersistent;
|
|
FOnCurrentKeyChanged: TNotifyEvent;
|
|
FOnSelectItem: TNotifyEvent;
|
|
function GetEdit: TcxCustomTextEdit;
|
|
function GetItems: TStrings;
|
|
function GetActiveProperties: TcxCustomTextEditProperties;
|
|
function IndexOf(const AText: string): Integer;
|
|
procedure SetItemIndex(Value: Integer);
|
|
procedure SetItems(Value: TStrings);
|
|
protected
|
|
function GetOwner: TPersistent; override;
|
|
procedure DoCurrentKeyChanged;
|
|
procedure DoSelectItem;
|
|
function GetItem(Index: Integer): string; virtual;
|
|
function GetItemCount: Integer; virtual;
|
|
function GetListBoxClass: TcxCustomEditListBoxClass; virtual;
|
|
procedure HandleSelectItem(Sender: TObject); virtual; // TODO test for CLX
|
|
function InternalLocate(var AText, ATail: string; ANext, ASynchronizeWithText: Boolean):
|
|
Boolean; virtual;
|
|
procedure InternalSetItemIndex(Value: Integer);
|
|
procedure ListChanged; virtual;
|
|
procedure SetListItemIndex(Value: Integer);
|
|
property Edit: TcxCustomTextEdit read GetEdit;
|
|
property ItemIndex: Integer read FItemIndex write SetItemIndex stored False;
|
|
property Items: TStrings read GetItems write SetItems;
|
|
property List: TcxCustomEditListBox read FList;
|
|
property ActiveProperties: TcxCustomTextEditProperties read GetActiveProperties;
|
|
public
|
|
constructor Create(AOwner: TPersistent); override;
|
|
function CanResizeVisualArea(var NewSize: TSize;
|
|
AMaxHeight: Integer = 0; AMaxWidth: Integer = 0): Boolean; virtual;
|
|
procedure CloseUp;
|
|
procedure Deinitialize;
|
|
procedure DropDown; virtual;
|
|
procedure DroppedDown(const AFindStr: string); virtual;
|
|
function Find(const AText: string): Boolean; virtual;
|
|
function GetActiveControl: TControl;
|
|
function GetCurrentKey: TcxEditValue;
|
|
function GetDisplayText(const AKey: TcxEditValue): string; overload;
|
|
function GetOnCurrentKeyChanged: TNotifyEvent;
|
|
function GetOnSelectItem: TNotifyEvent;
|
|
function GetVisualAreaPreferredSize(AMaxHeight: Integer; AWidth: Integer = 0): TSize; virtual;
|
|
procedure Go(ADirection: TcxEditLookupDataGoDirection; ACircular: Boolean);
|
|
procedure Initialize(AVisualControlsParent: TWinControl); virtual;
|
|
procedure InternalSetCurrentKey(Value: Integer);
|
|
function IsEmpty: Boolean;
|
|
function IsMouseOverList(const P: TPoint): Boolean;
|
|
function Locate(var AText, ATail: string; ANext: Boolean): Boolean;
|
|
procedure PositionVisualArea(const AClientRect: TRect); virtual;
|
|
procedure PropertiesChanged; virtual;
|
|
procedure SelectItem;
|
|
procedure SetCurrentKey(const AKey: TcxEditValue);
|
|
procedure SetOnCurrentKeyChanged(Value: TNotifyEvent);
|
|
procedure SetOnSelectItem(Value: TNotifyEvent);
|
|
procedure TextChanged; virtual;
|
|
property ActiveControl: TControl read GetActiveControl;
|
|
property CurrentKey: TcxEditValue read GetCurrentKey write SetCurrentKey;
|
|
property OnCurrentKeyChanged: TNotifyEvent read GetOnCurrentKeyChanged write SetOnCurrentKeyChanged;
|
|
property OnSelectItem: TNotifyEvent read GetOnSelectItem write SetOnSelectItem;
|
|
end;
|
|
|
|
{ TcxCustomTextEditViewData }
|
|
|
|
TcxCustomTextEditViewData = class(TcxCustomEditViewData)
|
|
private
|
|
FIsValueEditorWithValueFormatting: Boolean;
|
|
function GetProperties: TcxCustomTextEditProperties;
|
|
function InvertColor(AColor: TColor): TColor;
|
|
protected
|
|
procedure CalculateButtonNativeInfo(AButtonViewInfo: TcxEditButtonViewInfo); override;
|
|
function GetIsEditClass: Boolean; virtual;
|
|
function GetMaxLineCount: Integer; virtual;
|
|
procedure InitCacheData; override;
|
|
function InternalEditValueToDisplayText(AEditValue: TcxEditValue): string; override;
|
|
function InternalGetEditContentSize(ACanvas: TcxCanvas; const AEditValue: TcxEditValue;
|
|
const AEditSizeProperties: TcxEditSizeProperties): TSize; override;
|
|
function IsComboBoxStyle: Boolean; virtual;
|
|
procedure PrepareDrawTextFlags(ACanvas: TcxCanvas;
|
|
AViewInfo: TcxCustomEditViewInfo); virtual;
|
|
public
|
|
procedure Calculate(ACanvas: TcxCanvas; const ABounds: TRect; const P: TPoint;
|
|
Button: TcxMouseButton; Shift: TShiftState; AViewInfo: TcxCustomEditViewInfo;
|
|
AIsMouseEvent: Boolean); override;
|
|
procedure DisplayValueToDrawValue(const ADisplayValue: TcxEditValue;
|
|
AViewInfo: TcxCustomEditViewInfo); virtual;
|
|
procedure EditValueToDrawValue(ACanvas: TcxCanvas; const AEditValue: TcxEditValue;
|
|
AViewInfo: TcxCustomEditViewInfo); override;
|
|
function GetClientExtent(ACanvas: TcxCanvas;
|
|
AViewInfo: TcxCustomEditViewInfo): TRect; override;
|
|
function GetDrawTextFlags: DWORD; virtual;
|
|
function GetDrawTextOffset: TRect; virtual;
|
|
procedure PrepareSelection(AViewInfo: TcxCustomEditViewInfo);
|
|
property Properties: TcxCustomTextEditProperties read GetProperties;
|
|
end;
|
|
|
|
{ TcxCustomTextEditViewInfo }
|
|
|
|
TcxTextOutData = record
|
|
ForceEndEllipsis: Boolean;
|
|
Initialized: Boolean;
|
|
RowCount: Integer;
|
|
SelStart, SelLength: Integer;
|
|
SelBackgroundColor, SelTextColor: TColor;
|
|
TextParams: TcxTextParams;
|
|
TextRect: TRect;
|
|
TextRows: TcxTextRows;
|
|
end;
|
|
|
|
TcxCustomTextEditViewInfo = class(TcxCustomEditViewInfo)
|
|
protected
|
|
procedure InternalPaint(ACanvas: TcxCanvas); override;
|
|
public
|
|
ComboBoxStyle: Boolean;
|
|
CustomDrawHandler: TcxTextEditCustomDrawHandler;
|
|
DrawSelectionBar: Boolean;
|
|
DrawTextFlags: DWORD;
|
|
EditingStyle: TcxEditEditingStyle;
|
|
HasPopupWindow: Boolean;
|
|
IsEditClass: Boolean;
|
|
IsOwnerDrawing: Boolean;
|
|
MaxLineCount: Integer;
|
|
SelStart, SelLength: Integer;
|
|
SelTextColor, SelBackgroundColor: TColor;
|
|
Text: string;
|
|
TextOutData: TcxTextOutData;
|
|
TextRect: TRect;
|
|
destructor Destroy; override;
|
|
function NeedShowHint(ACanvas: TcxCanvas; const P: TPoint;
|
|
const AVisibleBounds: TRect; out AText: TCaption;
|
|
out AIsMultiLine: Boolean; out ATextRect: TRect): Boolean; override;
|
|
procedure Offset(DX, DY: Integer); override;
|
|
procedure DrawText(ACanvas: TcxCanvas); virtual;
|
|
{$IFDEF DELPHI10}
|
|
function GetTextBaseLine: Integer; virtual;
|
|
{$ENDIF}
|
|
end;
|
|
|
|
{ TcxCustomTextEditProperties }
|
|
|
|
TcxNewLookupDisplayTextEvent = procedure(Sender: TObject; const AText: TCaption) of object;
|
|
TcxTextEditChars = set of AnsiChar;
|
|
|
|
TcxCustomTextEditProperties = class(TcxCustomEditProperties, IcxFormatControllerListener)
|
|
private
|
|
FCharCase: TEditCharCase;
|
|
FDisplayFormat: string;
|
|
FEchoMode: TcxEditEchoMode;
|
|
FEditFormat: string;
|
|
FFixedListSelection: Boolean;
|
|
FFormatChanging: Boolean;
|
|
FHideCursor: Boolean;
|
|
FHideSelection: Boolean;
|
|
FImeMode: TImeMode;
|
|
FImeName: TImeName;
|
|
FImmediateUpdateText: Boolean;
|
|
FIncrementalSearch: Boolean;
|
|
FLookupItems: TStringList;
|
|
FMaxLength: Integer;
|
|
FMRUMode: Boolean;
|
|
FOEMConvert: Boolean;
|
|
FPasswordChar: TCaptionChar;
|
|
FUseDisplayFormatWhenEditing: Boolean;
|
|
FValidChars: TcxTextEditChars;
|
|
FOnNewLookupDisplayText: TcxNewLookupDisplayTextEvent;
|
|
function GetAssignedValues: TcxTextEditPropertiesValues;
|
|
function GetDisplayFormat: string;
|
|
function GetEditFormat: string;
|
|
function GetInnerEditMaxLength: Integer;
|
|
function GetLookupItems: TStrings;
|
|
function GetLookupItemsSorted: Boolean;
|
|
function GetMaxLength: Integer;
|
|
function GetViewStyle: TcxTextEditViewStyle;
|
|
function IsDisplayFormatStored: Boolean;
|
|
function IsEditFormatStored: Boolean;
|
|
function IsMaxLengthStored: Boolean;
|
|
procedure LookupItemsChanged(Sender: TObject);
|
|
procedure ReadIsDisplayFormatAssigned(Reader: TReader); // obsolete
|
|
procedure SetAssignedValues(Value: TcxTextEditPropertiesValues);
|
|
procedure SetDisplayFormat(const Value: string);
|
|
procedure SetEchoMode(Value: TcxEditEchoMode);
|
|
procedure SetEditFormat(const Value: string);
|
|
procedure SetFixedListSelection(Value: Boolean);
|
|
procedure SetHideCursor(Value: Boolean);
|
|
procedure SetHideSelection(Value: Boolean);
|
|
procedure SetImeMode(Value: TImeMode);
|
|
procedure SetImeName(const Value: TImeName);
|
|
procedure SetIncrementalSearch(Value: Boolean);
|
|
procedure SetLookupItems(Value: TStrings);
|
|
procedure SetLookupItemsSorted(Value: Boolean);
|
|
procedure SetMaxLength(Value: Integer);
|
|
procedure SetMRUMode(Value: Boolean);
|
|
procedure SetOEMConvert(Value: Boolean);
|
|
procedure SetPasswordChar(Value: TCaptionChar);
|
|
procedure SetUseDisplayFormatWhenEditing(Value: Boolean);
|
|
procedure SetViewStyle(Value: TcxTextEditViewStyle);
|
|
protected
|
|
procedure AlignmentChangedHandler(Sender: TObject); override;
|
|
procedure BaseSetAlignment(Value: TcxEditAlignment); override;
|
|
function CanValidate: Boolean; override;
|
|
procedure DefineProperties(Filer: TFiler); override; // obsolete
|
|
class function GetAssignedValuesClass: TcxCustomEditPropertiesValuesClass; override;
|
|
function GetDisplayFormatOptions: TcxEditDisplayFormatOptions; override;
|
|
function GetValidateErrorText(AErrorKind: TcxEditErrorKind): string; override;
|
|
class function GetViewDataClass: TcxCustomEditViewDataClass; override;
|
|
function HasDisplayValue: Boolean; override;
|
|
|
|
// IcxFormatControllerListener
|
|
procedure FormatChanged; virtual;
|
|
|
|
function CanIncrementalSearch: Boolean;
|
|
procedure CheckEditorValueBounds(var DisplayValue: TcxEditValue;
|
|
var ErrorText: TCaption; var Error: Boolean; AEdit: TcxCustomEdit); virtual;
|
|
function DefaultFocusedDisplayValue: TcxEditValue; virtual;
|
|
function FindLookupText(const AText: string): Boolean; virtual;
|
|
function GetDefaultDisplayFormat: string; virtual;
|
|
function GetDefaultDisplayValue(const AEditValue: TcxEditValue; AEditFocused: Boolean): TcxEditValue;
|
|
function GetDefaultMaxLength: Integer; virtual;
|
|
function GetDropDownPageRowCount: Integer; virtual;
|
|
function GetEditingStyle: TcxEditEditingStyle; virtual;
|
|
class function GetLookupDataClass: TcxInterfacedPersistentClass; virtual;
|
|
function HasDigitGrouping(AIsDisplayValueSynchronizing: Boolean): Boolean; virtual;
|
|
function InternalGetEditFormat(out AIsCurrency, AIsOnGetTextAssigned: Boolean;
|
|
AEdit: TcxCustomTextEdit = nil): string; virtual;
|
|
function IsEditValueNumeric: Boolean; virtual;
|
|
function IsLookupDataVisual: Boolean; virtual;
|
|
function IsMultiLine: Boolean; virtual;
|
|
function IsPopupKey(Key: Word; Shift: TShiftState): Boolean; virtual;
|
|
function IsValueBoundDefined(ABound: TcxEditValueBound): Boolean; virtual;
|
|
function IsValueBoundsDefined: Boolean; virtual;
|
|
procedure LookupDataChanged(Sender: TObject); virtual;
|
|
procedure MaxLengthChanged; virtual;
|
|
procedure SetCharCase(Value: TEditCharCase); virtual;
|
|
function UseLookupData: Boolean; virtual;
|
|
property AssignedValues: TcxTextEditPropertiesValues read GetAssignedValues
|
|
write SetAssignedValues;
|
|
property EditingStyle: TcxEditEditingStyle read GetEditingStyle;
|
|
property FixedListSelection: Boolean read FFixedListSelection
|
|
write SetFixedListSelection default True;
|
|
property FormatChanging: Boolean read FFormatChanging;
|
|
property HideCursor: Boolean read FHideCursor write SetHideCursor
|
|
stored False;
|
|
property MRUMode: Boolean read FMRUMode write SetMRUMode default False;
|
|
public
|
|
constructor Create(AOwner: TPersistent); override;
|
|
destructor Destroy; override;
|
|
procedure Assign(Source: TPersistent); override;
|
|
function CanCompareEditValue: Boolean; override;
|
|
function CompareDisplayValues(
|
|
const AEditValue1, AEditValue2: TcxEditValue): Boolean; override;
|
|
class function GetContainerClass: TcxContainerClass; override;
|
|
function GetDisplayText(const AEditValue: TcxEditValue;
|
|
AFullText: Boolean = False; AIsInplace: Boolean = True): WideString; override;
|
|
function GetEditValueSource(AEditFocused: Boolean): TcxDataEditValueSource; override;
|
|
function GetSupportedOperations: TcxEditSupportedOperations; override;
|
|
class function GetViewInfoClass: TcxContainerViewInfoClass; override;
|
|
function IsEditValueValid(var EditValue: TcxEditValue; AEditFocused: Boolean): Boolean; override;
|
|
function IsResetEditClass: Boolean; override;
|
|
procedure PrepareDisplayValue(const AEditValue: TcxEditValue;
|
|
var DisplayValue: TcxEditValue; AEditFocused: Boolean); override;
|
|
procedure ValidateDisplayValue(var DisplayValue: TcxEditValue; var ErrorText: TCaption;
|
|
var Error: Boolean; AEdit: TcxCustomEdit); override;
|
|
procedure DisplayValueToDisplayText(var ADisplayValue: string); virtual;
|
|
function IsDisplayValueValid(var DisplayValue: TcxEditValue; AEditFocused: Boolean): Boolean; virtual;
|
|
procedure SetMinMaxValues(AMinValue, AMaxValue: Double);
|
|
property ValidChars: TcxTextEditChars read FValidChars write FValidChars;
|
|
// !!!
|
|
property CharCase: TEditCharCase read FCharCase write SetCharCase default ecNormal;
|
|
property DisplayFormat: string read GetDisplayFormat write SetDisplayFormat
|
|
stored IsDisplayFormatStored;
|
|
property EchoMode: TcxEditEchoMode read FEchoMode write SetEchoMode default eemNormal;
|
|
property EditFormat: string read GetEditFormat write SetEditFormat
|
|
stored IsEditFormatStored;
|
|
property HideSelection: Boolean read FHideSelection write SetHideSelection default True;
|
|
property ImeMode: TImeMode read FImeMode write SetImeMode default imDontCare;
|
|
property ImeName: TImeName read FImeName write SetImeName;
|
|
property ImmediateUpdateText: Boolean read FImmediateUpdateText write FImmediateUpdateText default False;
|
|
property IncrementalSearch: Boolean read FIncrementalSearch
|
|
write SetIncrementalSearch default True;
|
|
property LookupItems: TStrings read GetLookupItems write SetLookupItems;
|
|
property LookupItemsSorted: Boolean read GetLookupItemsSorted write
|
|
SetLookupItemsSorted default False;
|
|
property MaxLength: Integer read GetMaxLength write SetMaxLength stored IsMaxLengthStored;
|
|
property MaxValue;
|
|
property MinValue;
|
|
property OEMConvert: Boolean read FOEMConvert write SetOEMConvert default False;
|
|
property PasswordChar: TCaptionChar read FPasswordChar write SetPasswordChar
|
|
default #0;
|
|
property UseDisplayFormatWhenEditing: Boolean
|
|
read FUseDisplayFormatWhenEditing write SetUseDisplayFormatWhenEditing
|
|
default False;
|
|
property ViewStyle: TcxTextEditViewStyle read GetViewStyle write SetViewStyle default vsNormal;
|
|
property OnNewLookupDisplayText: TcxNewLookupDisplayTextEvent read
|
|
FOnNewLookupDisplayText write FOnNewLookupDisplayText;
|
|
end;
|
|
|
|
{ TcxTextEditProperties }
|
|
|
|
TcxTextEditProperties = class(TcxCustomTextEditProperties)
|
|
published
|
|
property Alignment;
|
|
property AssignedValues;
|
|
property AutoSelect;
|
|
property BeepOnError;
|
|
property CharCase;
|
|
property ClearKey;
|
|
property EchoMode;
|
|
property HideSelection;
|
|
property ImeMode;
|
|
property ImeName;
|
|
property IncrementalSearch;
|
|
property LookupItems;
|
|
property LookupItemsSorted;
|
|
property MaxLength;
|
|
property OEMConvert;
|
|
property PasswordChar;
|
|
property ReadOnly;
|
|
property UseLeftAlignmentOnEditing;
|
|
property ValidateOnEnter;
|
|
property OnChange;
|
|
property OnEditValueChanged;
|
|
property OnNewLookupDisplayText;
|
|
property OnValidate;
|
|
end;
|
|
|
|
{ TcxCustomTextEdit }
|
|
|
|
TcxCustomTextEdit = class(TcxCustomEdit, IcxFormatControllerListener)
|
|
private
|
|
FBeepOnEnter: Boolean;
|
|
FDisableRefresh: Boolean;
|
|
FFindSelection: Boolean;
|
|
FInternalTextSetting: Boolean;
|
|
FIsDisplayValueSynchronizing: Boolean;
|
|
FLastFirstVisibleCharIndex: Integer;
|
|
FLastSelLength: Integer;
|
|
FLastSelPosition: Integer;
|
|
FLookupItemsScrolling: Boolean;
|
|
FText: TCaption;
|
|
{$IFDEF CXTEST}
|
|
FHideInnerEdit: Boolean;
|
|
FShowInnerEdit: Boolean;
|
|
FTesting: Boolean;
|
|
{$ENDIF}
|
|
function GetCursorPos: Integer;
|
|
function GetEditingText: TCaption;
|
|
function GetInnerTextEdit: IcxInnerTextEdit;
|
|
function GetILookupData: IcxTextEditLookupData;
|
|
function GetLookupData: TcxCustomTextEditLookupData;
|
|
function GetProperties: TcxCustomTextEditProperties;
|
|
function GetActiveProperties: TcxCustomTextEditProperties;
|
|
function GetSelLength: Integer;
|
|
function GetSelStart: Integer;
|
|
function GetSelText: TCaption;
|
|
function GetViewInfo: TcxCustomTextEditViewInfo;
|
|
procedure SetFindSelection(Value: Boolean);
|
|
procedure SetItemObject(Value: TObject);
|
|
procedure SetProperties(Value: TcxCustomTextEditProperties);
|
|
procedure SetSelLength(Value: Integer);
|
|
procedure SetSelStart(Value: Integer);
|
|
{$IFDEF DELPHI12}
|
|
function GetTextHint: string;
|
|
procedure SetTextHint(Value: string);
|
|
{$ENDIF}
|
|
{$IFDEF CXTEST}
|
|
procedure SetHideInnerEdit(Value: Boolean);
|
|
procedure SetShowInnerEdit(Value: Boolean);
|
|
procedure SetTesting(Value: Boolean);
|
|
{$ENDIF}
|
|
procedure WMClear(var Message: TMessage); message WM_CLEAR;
|
|
procedure WMCommand(var Message: TWMCommand); message WM_COMMAND;
|
|
procedure WMGetText(var Message: TWMGetText); message WM_GETTEXT;
|
|
procedure WMGetTextLength(var Message: TWMGetTextLength); message WM_GETTEXTLENGTH;
|
|
procedure WMSetFocus(var Message: TWMSetFocus); message WM_SETFOCUS;
|
|
procedure WMSetText(var Message: TWMSetText); message WM_SETTEXT;
|
|
protected
|
|
FInnerEditPositionAdjusting: Boolean;
|
|
FIsPopupWindowJustClosed: Boolean;
|
|
FLookupData: TcxInterfacedPersistent;
|
|
FLookupDataTextChangedLocked: Boolean;
|
|
FIsChangeBySpellChecker: Boolean;
|
|
procedure AdjustInnerEditPosition; override;
|
|
function CanKeyDownModifyEdit(Key: Word; Shift: TShiftState): Boolean; override;
|
|
function CanKeyPressModifyEdit(Key: Char): Boolean; override;
|
|
procedure ChangeHandler(Sender: TObject); override;
|
|
procedure DoEditKeyDown(var Key: Word; Shift: TShiftState); override;
|
|
procedure DoEditKeyPress(var Key: Char); override;
|
|
procedure DoExit; override;
|
|
function DoMouseWheel(Shift: TShiftState; WheelDelta: Integer;
|
|
MousePos: TPoint): Boolean; override;
|
|
procedure FillSizeProperties(var AEditSizeProperties: TcxEditSizeProperties); override;
|
|
function GetDisplayValue: string; override;
|
|
function GetInnerControlBounds(const AInnerControlsRegion: TRect;
|
|
AInnerControl: TControl): TcxContainerInnerControlBounds; override;
|
|
function GetInnerEditClass: TControlClass; override;
|
|
procedure Initialize; override;
|
|
function InternalDoEditing: Boolean; override;
|
|
function InternalGetEditingValue: TcxEditValue; override;
|
|
procedure InternalSetDisplayValue(const Value: TcxEditValue); override;
|
|
procedure InternalValidateDisplayValue(const ADisplayValue: TcxEditValue); override;
|
|
function IsTextInputMode: Boolean; virtual;
|
|
function IsValidChar(AChar: Char): Boolean; override;
|
|
procedure KeyPress(var Key: Char); override;
|
|
procedure Loaded; override;
|
|
procedure PropertiesChanged(Sender: TObject); override;
|
|
function RefreshContainer(const P: TPoint; Button: TcxMouseButton; Shift: TShiftState;
|
|
AIsMouseEvent: Boolean): Boolean; override;
|
|
function SetDisplayText(const Value: string): Boolean; override;
|
|
procedure SetInternalDisplayValue(Value: TcxEditValue); override;
|
|
function WantNavigationKeys: Boolean; override;
|
|
procedure LockedInnerEditWindowProc(var Message: TMessage); override;
|
|
procedure UnlockInnerEditRepainting; override;
|
|
procedure WndProc(var Message: TMessage); override;
|
|
|
|
// IcxFormatControllerListener
|
|
procedure FormatChanged; virtual;
|
|
|
|
// SpellChecking
|
|
procedure DoDrawMisspellings; virtual;
|
|
procedure DoLayoutChanged; virtual;
|
|
procedure DoSelectionChanged; virtual;
|
|
procedure DoTextChanged; virtual;
|
|
procedure InternalCheckSelection;
|
|
procedure InternalSpellCheckerHandler(Message: TMessage); virtual;
|
|
procedure RedrawMisspelledWords;
|
|
procedure SpellCheckerSetSelText(const AValue: string; APost: Boolean = False); override;
|
|
|
|
procedure AdjustInnerEdit; virtual;
|
|
function CanChangeSelText(const Value: string; out ANewText: string;
|
|
out ANewSelStart: Integer): Boolean; virtual;
|
|
procedure CheckEditValue; virtual;
|
|
procedure CheckEditorValueBounds; virtual;
|
|
procedure DoOnNewLookupDisplayText(const AText: string); virtual;
|
|
function GetInnerEditHeight: Integer; virtual;
|
|
function GetItemIndex: Integer; virtual;
|
|
function GetItemObject: TObject; virtual;
|
|
function GetScrollLookupDataList(AScrollCause: TcxEditScrollCause): Boolean; virtual;
|
|
procedure HandleSelectItem(Sender: TObject); virtual;
|
|
function InternalGetText: string; virtual;
|
|
function InternalSetText(const Value: string): Boolean; virtual;
|
|
function ItemIndexToLookupKey(AItemIndex: Integer): TcxEditValue; virtual;
|
|
procedure LockLookupDataTextChanged;
|
|
function LookupKeyToEditValue(const AKey: TcxEditValue): TcxEditValue; virtual;
|
|
function LookupKeyToItemIndex(const AKey: TcxEditValue): Integer; virtual;
|
|
function NeedResetInvalidTextWhenPropertiesChanged: Boolean; virtual;
|
|
procedure ResetOnNewDisplayValue; virtual;
|
|
procedure SelChange(Sender: TObject); virtual;
|
|
procedure SetEditingText(const Value: TCaption); virtual;
|
|
procedure SetItemIndex(Value: Integer); virtual;
|
|
procedure SetSelText(const Value: TCaption); virtual;
|
|
procedure SynchronizeDisplayValue; override;
|
|
procedure SynchronizeEditValue; override;
|
|
procedure UndoPerformed; virtual;
|
|
procedure UnlockLookupDataTextChanged;
|
|
procedure UpdateDrawValue; override;
|
|
procedure UpdateDisplayValue; virtual;
|
|
|
|
property BeepOnEnter: Boolean read FBeepOnEnter write FBeepOnEnter default True;
|
|
property InnerTextEdit: IcxInnerTextEdit read GetInnerTextEdit;
|
|
property ItemIndex: Integer read GetItemIndex write SetItemIndex stored False;
|
|
property ItemObject: TObject read GetItemObject write SetItemObject;
|
|
property LookupData: TcxCustomTextEditLookupData read GetLookupData;
|
|
property LookupItemsScrolling: Boolean read FLookupItemsScrolling write FLookupItemsScrolling;
|
|
property ParentColor default False;
|
|
property ViewInfo: TcxCustomTextEditViewInfo read GetViewInfo;
|
|
{$IFDEF DELPHI12}
|
|
property TextHint: string read GetTextHint write SetTextHint;
|
|
{$ENDIF}
|
|
{$IFDEF CXTEST}
|
|
property HideInnerEdit: Boolean read FHideInnerEdit write SetHideInnerEdit; // for test
|
|
property ShowInnerEdit: Boolean read FShowInnerEdit write SetShowInnerEdit; // for test
|
|
property Testing: Boolean read FTesting write SetTesting; // for test
|
|
{$ENDIF}
|
|
public
|
|
{$IFDEF CBUILDER10}
|
|
constructor Create(AOwner: TComponent); override;
|
|
{$ENDIF}
|
|
destructor Destroy; override;
|
|
procedure Activate(var AEditData: TcxCustomEditData); override;
|
|
class function GetPropertiesClass: TcxCustomEditPropertiesClass; override;
|
|
procedure CopyToClipboard; override;
|
|
procedure CutToClipboard; override;
|
|
function IsEditClass: Boolean; override;
|
|
procedure PasteFromClipboard; override;
|
|
procedure PrepareEditValue(const ADisplayValue: TcxEditValue;
|
|
out EditValue: TcxEditValue; AEditFocused: Boolean); override;
|
|
procedure SelectAll; override;
|
|
{$IFDEF DELPHI10}
|
|
function GetTextBaseLine: Integer; override;
|
|
function HasTextBaseLine: Boolean; override;
|
|
{$ENDIF}
|
|
procedure ClearSelection; virtual;
|
|
function DoInnerControlDefaultHandler(var Message: TMessage): Boolean; override;
|
|
function IsChildWindow(AWnd: THandle): Boolean; override;
|
|
procedure SetScrollBarsParameters(AIsScrolling: Boolean = False); override;
|
|
procedure SetSelection(ASelStart: Integer; ASelLength: Integer);
|
|
procedure Undo; virtual;
|
|
property ActiveProperties: TcxCustomTextEditProperties read GetActiveProperties;
|
|
property CursorPos: Integer read GetCursorPos;
|
|
property EditingText: TCaption read GetEditingText write SetEditingText;
|
|
property FindSelection: Boolean read FFindSelection write SetFindSelection;
|
|
property ILookupData: IcxTextEditLookupData read GetILookupData;
|
|
property Properties: TcxCustomTextEditProperties read GetProperties
|
|
write SetProperties;
|
|
property SelLength: Integer read GetSelLength write SetSelLength;
|
|
property SelStart: Integer read GetSelStart write SetSelStart;
|
|
property SelText: TCaption read GetSelText write SetSelText;
|
|
property Text;
|
|
end;
|
|
|
|
{ TcxTextEdit }
|
|
|
|
TcxTextEdit = class(TcxCustomTextEdit)
|
|
private
|
|
function GetActiveProperties: TcxTextEditProperties;
|
|
function GetProperties: TcxTextEditProperties;
|
|
procedure SetProperties(Value: TcxTextEditProperties);
|
|
protected
|
|
function SupportsSpelling: Boolean; override;
|
|
public
|
|
class function GetPropertiesClass: TcxCustomEditPropertiesClass; override;
|
|
property ActiveProperties: TcxTextEditProperties read GetActiveProperties;
|
|
published
|
|
property Anchors;
|
|
property AutoSize;
|
|
property BeepOnEnter;
|
|
property Constraints;
|
|
property DragCursor;
|
|
property DragKind;
|
|
property DragMode;
|
|
property Enabled;
|
|
property ImeMode;
|
|
property ImeName;
|
|
property ParentColor;
|
|
property ParentFont;
|
|
property ParentShowHint;
|
|
property PopupMenu;
|
|
property Properties: TcxTextEditProperties read GetProperties write SetProperties;
|
|
property ShowHint;
|
|
property Style;
|
|
property StyleDisabled;
|
|
property StyleFocused;
|
|
property StyleHot;
|
|
property TabOrder;
|
|
property TabStop;
|
|
property Text;
|
|
{$IFDEF DELPHI12}
|
|
property TextHint;
|
|
{$ENDIF}
|
|
property Visible;
|
|
property OnClick;
|
|
property OnContextPopup;
|
|
property OnDblClick;
|
|
property OnDragDrop;
|
|
property OnDragOver;
|
|
property OnEditing;
|
|
property OnEndDock;
|
|
property OnEndDrag;
|
|
property OnEnter;
|
|
property OnExit;
|
|
property OnKeyDown;
|
|
property OnKeyPress;
|
|
property OnKeyUp;
|
|
property OnMouseDown;
|
|
property OnMouseEnter;
|
|
property OnMouseLeave;
|
|
property OnMouseMove;
|
|
property OnMouseUp;
|
|
property OnStartDock;
|
|
property OnStartDrag;
|
|
end;
|
|
|
|
{ TcxFilterTextEditHelper }
|
|
|
|
TcxFilterTextEditHelper = class(TcxCustomFilterEditHelper)
|
|
public
|
|
class function GetFilterEditClass: TcxCustomEditClass; override;
|
|
class procedure InitializeProperties(AProperties,
|
|
AEditProperties: TcxCustomEditProperties; AHasButtons: Boolean); override;
|
|
class procedure SetFilterValue(AEdit: TcxCustomEdit; AEditProperties: TcxCustomEditProperties;
|
|
AValue: Variant); override;
|
|
end;
|
|
|
|
procedure CheckCharsRegister(var AText: string; ACharCase: TEditCharCase);
|
|
function CheckTextEditState(ATextEdit: IcxInnerTextEdit; const APrevState:
|
|
TcxCustomInnerTextEditPrevState): Boolean;
|
|
procedure DrawEditText(ACanvas: TcxCanvas; AViewInfo: TcxCustomTextEditViewInfo);
|
|
procedure DrawTextEdit(ACanvas: TcxCanvas; AViewInfo: TcxCustomTextEditViewInfo);
|
|
function GetTextEditContentSize(ACanvas: TcxCanvas; AViewData: TcxCustomEditViewData;
|
|
const AText: string; ADrawTextFlags: DWORD; const AEditSizeProperties: TcxEditSizeProperties;
|
|
ALineCount: Integer = 0; ACorrectWidth: Boolean = True): TSize;
|
|
function GetTextEditDrawTextOffset(AViewData: TcxCustomEditViewData): TRect; overload;
|
|
function GetTextEditDrawTextOffset(AAlignment: TAlignment; AIsInplace: Boolean): TRect; overload; // deprecated
|
|
procedure InternalTextOut(ACanvas: TCanvas; AViewInfo: TcxCustomTextEditViewInfo;
|
|
AText: PcxCaptionChar; var R: TRect; AFormat: TcxTextOutFormat; ASelStart,
|
|
ASelLength: Integer; ASelBackgroundColor, ASelTextColor: TColor;
|
|
AMaxLineCount: Integer = 0; ALeftIndent: Integer = 0; ARightIndent: Integer = 0);
|
|
procedure InsertThousandSeparator(var S: string);
|
|
function RemoveExponentialPart(var S: string): string;
|
|
procedure RemoveThousandSeparator(var S: string);
|
|
procedure SaveTextEditState(ATextEdit: IcxInnerTextEdit;
|
|
ASaveText: Boolean;
|
|
var APrevState: TcxCustomInnerTextEditPrevState);
|
|
procedure SeparateDigitGroups(AEdit: TcxCustomTextEdit);
|
|
|
|
implementation
|
|
|
|
uses
|
|
{$IFDEF DELPHI6}
|
|
FMTBcd,
|
|
{$ENDIF}
|
|
Types, cxGeometry, cxEditConsts, cxEditUtils, dxThemeConsts, dxThemeManager,
|
|
cxDWMApi, dxCore;
|
|
|
|
type
|
|
TCanvasAccess = class(TCanvas);
|
|
TControlAccess = class(TControl);
|
|
TWinControlAccess = class(TWinControl);
|
|
//TcxEditDataBindingAccess = class(TcxEditDataBinding)
|
|
|
|
const
|
|
WM_REDRAWMISSPELLINGS: Cardinal = WM_DX + 100;
|
|
|
|
procedure CalculateTextEditViewInfo(ACanvas: TcxCanvas; AViewData: TcxCustomTextEditViewData;
|
|
AViewInfo: TcxCustomTextEditViewInfo; AIsMouseEvent: Boolean);
|
|
begin
|
|
with AViewInfo do
|
|
begin
|
|
TextRect := ClientRect;
|
|
ExtendRect(TextRect, AViewData.GetDrawTextOffset);
|
|
if not IsInplace and (TextRect.Bottom - TextRect.Top < ACanvas.TextHeight('Zg')) then
|
|
begin
|
|
TextRect.Bottom := ACanvas.TextHeight('Zg') + TextRect.Top;
|
|
if TextRect.Bottom > ClientRect.Bottom then
|
|
TextRect.Bottom := ClientRect.Bottom;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure CheckCharsRegister(var AText: string; ACharCase: TEditCharCase);
|
|
begin
|
|
if ACharCase = ecUpperCase then
|
|
AText := AnsiUpperCase(AText)
|
|
else
|
|
if ACharCase = ecLowerCase then
|
|
AText := AnsiLowerCase(AText);
|
|
end;
|
|
|
|
function CheckTextEditState(ATextEdit: IcxInnerTextEdit; const APrevState:
|
|
TcxCustomInnerTextEditPrevState): Boolean;
|
|
begin
|
|
if not ATextEdit.Control.HandleAllocated then
|
|
Result := True
|
|
else
|
|
with APrevState do
|
|
Result := (PrevSelStart <> ATextEdit.SelStart) or
|
|
(PrevSelLength <> ATextEdit.SelLength) or
|
|
IsPrevTextSaved and not InternalCompareString(PrevText, ATextEdit.EditValue, False);
|
|
end;
|
|
|
|
procedure DrawEditText(ACanvas: TcxCanvas; AViewInfo: TcxCustomTextEditViewInfo);
|
|
var
|
|
AText: PcxCaptionChar;
|
|
ATextColor: TColor;
|
|
R: TRect;
|
|
begin
|
|
with AViewInfo do
|
|
begin
|
|
AText := PcxCaptionChar(Text);
|
|
{$IFNDEF NOFLICKER}
|
|
if StrLen(AText) = 0 then
|
|
Exit;
|
|
{$ENDIF}
|
|
|
|
R := TextRect;
|
|
if DrawSelectionBar then
|
|
ATextColor := clHighlightText
|
|
else
|
|
ATextColor := TextColor;
|
|
ACanvas.Font := Font;
|
|
ACanvas.Font.Color := ATextColor;
|
|
PrepareCanvasFont(ACanvas.Canvas);
|
|
InternalTextOut(ACanvas.Canvas, AViewInfo, AText, R, DrawTextFlags,
|
|
SelStart, SelLength, SelBackgroundColor, SelTextColor, MaxLineCount);
|
|
end;
|
|
end;
|
|
|
|
procedure DrawTextEdit(ACanvas: TcxCanvas; AViewInfo: TcxCustomTextEditViewInfo);
|
|
|
|
function GetBackgroundPaintingStyle: TcxEditBackgroundPaintingStyle;
|
|
begin
|
|
with AViewInfo do
|
|
if ComboBoxStyle then
|
|
if EditingStyle in [esFixedList, esNoEdit] then
|
|
Result := bpsComboListEdit
|
|
else
|
|
Result := bpsComboEdit
|
|
else
|
|
Result := bpsSolid;
|
|
end;
|
|
|
|
procedure InternalDrawFocusRect(R: TRect);
|
|
begin
|
|
with AViewInfo, ACanvas do
|
|
if not IsEditClass and Focused and not IsInplace and not HasPopupWindow then
|
|
begin
|
|
if DrawSelectionBar then
|
|
begin
|
|
Canvas.Font.Color := clHighlightText;
|
|
Canvas.Brush.Color := clHighlight;
|
|
end else
|
|
begin
|
|
Canvas.Font.Color := clBtnText;
|
|
Canvas.Brush.Color := AViewInfo.BackgroundColor;
|
|
end;
|
|
TCanvasAccess(Canvas).RequiredState([csFontValid]);
|
|
Canvas.DrawFocusRect(R);
|
|
end;
|
|
end;
|
|
|
|
var
|
|
ARealTransparent: Boolean;
|
|
R: TRect;
|
|
begin
|
|
with AViewInfo, ACanvas do
|
|
begin
|
|
ARealTransparent := Transparent or DrawSelectionBar;
|
|
DrawCustomEdit(ACanvas, AViewInfo, not ARealTransparent, GetBackgroundPaintingStyle);
|
|
R := ClientRect;
|
|
if not IsInplace then
|
|
begin
|
|
if ((NativeState = TC_NONE) or DrawSelectionBar) and not Transparent and
|
|
(AViewInfo.EditingStyle <> esNoEdit) then
|
|
FrameRect(R, BackgroundColor);
|
|
InflateRect(R, -1, -1);
|
|
end;
|
|
if IsOwnerDrawing then
|
|
CustomDrawHandler(ACanvas, R)
|
|
else
|
|
begin
|
|
if DrawSelectionBar then
|
|
begin
|
|
Brush.Color := clHighlight;
|
|
FillRect(R);
|
|
end;
|
|
if IsDBEditPaintCopyDrawing or not HasInnerEdit or not IsEditClass then
|
|
AViewInfo.DrawText(ACanvas);
|
|
end;
|
|
InternalDrawFocusRect(R);
|
|
end;
|
|
end;
|
|
|
|
function GetTextEditContentSize(ACanvas: TcxCanvas; AViewData: TcxCustomEditViewData;
|
|
const AText: string; ADrawTextFlags: DWORD; const AEditSizeProperties: TcxEditSizeProperties;
|
|
ALineCount: Integer = 0; ACorrectWidth: Boolean = True): TSize;
|
|
|
|
function GetAutoHeightSize: TSize;
|
|
var
|
|
AAlignment: TcxEditAlignment;
|
|
AFlags: DWORD;
|
|
ARowCount: Integer;
|
|
ATextParams: TcxTextParams;
|
|
ATextRows: TcxTextRows;
|
|
ASizeCorrection: TSize;
|
|
AWidth: Integer;
|
|
R: TRect;
|
|
begin
|
|
AAlignment := nil;
|
|
if not AViewData.IsInplace and (AViewData is TcxCustomTextEditViewData) then
|
|
with TcxCustomTextEditProperties(AViewData.Properties) do
|
|
if (EditingStyle in [esFixedList, esNoEdit]) and
|
|
not (not AViewData.IsInplace and TcxCustomTextEditViewData(AViewData).IsComboBoxStyle and
|
|
AreVisualStylesMustBeUsed(AViewData.Style.LookAndFeel.NativeStyle, totEdit)) then
|
|
AAlignment := Alignment;
|
|
ACanvas.Font := AViewData.Style.GetVisibleFont;
|
|
AFlags := ADrawTextFlags;
|
|
ASizeCorrection := AViewData.GetEditContentSizeCorrection;
|
|
AWidth := AEditSizeProperties.Width;
|
|
|
|
if ALineCount > 0 then
|
|
begin
|
|
Result.cy := ACanvas.TextHeight('Zg') * ALineCount;
|
|
Result.cx := AEditSizeProperties.Width;
|
|
end
|
|
else
|
|
begin
|
|
if AViewData.IsInplace then
|
|
Dec(AWidth, 2);
|
|
if AAlignment <> nil then
|
|
Dec(AWidth);
|
|
if AWidth <= 0 then
|
|
begin
|
|
Result.cx := 0;
|
|
if (epoAllowZeroHeight in AViewData.PaintOptions) and (Length(AText) = 0) then
|
|
Result.cy := 0
|
|
else
|
|
Result.cy := ACanvas.TextHeight('Zg');
|
|
end
|
|
else
|
|
begin
|
|
Result.cx := AEditSizeProperties.Width;
|
|
if Length(AText) = 0 then
|
|
if epoAllowZeroHeight in AViewData.PaintOptions then
|
|
Result.cy := 0
|
|
else
|
|
Result.cy := ACanvas.TextHeight('Zg')
|
|
else
|
|
begin
|
|
AFlags := AFlags or CXTO_CALCROWCOUNT;
|
|
if AFlags and CXTO_SINGLELINE <> 0 then
|
|
AFlags := AFlags and not CXTO_SINGLELINE or CXTO_WORDBREAK or
|
|
CXTO_EDITCONTROL;
|
|
AFlags := AFlags and not(CXTO_CENTER_VERTICALLY or CXTO_BOTTOM) or CXTO_TOP;
|
|
R := Rect(0, 0, AWidth, MaxInt);
|
|
ATextParams := cxCalcTextParams(ACanvas.Canvas, AFlags);
|
|
cxMakeTextRows(ACanvas.Canvas, PChar(AText), Length(AText), R, ATextParams,
|
|
ATextRows, ARowCount, AEditSizeProperties.MaxLineCount);
|
|
Result.cy := ARowCount * ACanvas.TextHeight('Zg');
|
|
cxResetTextRows(ATextRows);
|
|
end;
|
|
end;
|
|
end;
|
|
if Result.cy > 0 then
|
|
Result.cy := Result.cy + ASizeCorrection.cy;
|
|
end;
|
|
|
|
function GetBestFitSize: TSize;
|
|
var
|
|
AAlignment: TcxEditAlignment;
|
|
AFlags: DWORD;
|
|
ARowCount: Integer;
|
|
ATextParams: TcxTextParams;
|
|
ATextRows: TcxTextRows;
|
|
ATextFlags: Integer;
|
|
ASizeCorrection: TSize;
|
|
R: TRect;
|
|
begin
|
|
AAlignment := nil;
|
|
if not AViewData.IsInplace and (AViewData is TcxCustomTextEditViewData) then
|
|
with TcxCustomTextEditProperties(AViewData.Properties) do
|
|
if (EditingStyle in [esFixedList, esNoEdit]) and
|
|
not (not AViewData.IsInplace and TcxCustomTextEditViewData(AViewData).IsComboBoxStyle and
|
|
AreVisualStylesMustBeUsed(AViewData.Style.LookAndFeel.NativeStyle, totEdit)) then
|
|
AAlignment := Alignment;
|
|
ACanvas.Font := AViewData.Style.GetVisibleFont;
|
|
AFlags := ADrawTextFlags;
|
|
ASizeCorrection := AViewData.GetEditContentSizeCorrection;
|
|
|
|
if (AFlags and CXTO_SINGLELINE <> 0) and not ((epoAutoHeight in AViewData.PaintOptions) and
|
|
(esoAutoHeight in AViewData.Properties.GetSupportedOperations)) then
|
|
begin
|
|
ATextFlags := cxTextOutFlagsToDrawTextFlags(AFlags);
|
|
Result.cy := ACanvas.TextHeight('Zg');
|
|
R := Rect(0, 0, MaxInt, 0);
|
|
if Length(AText) = 0 then
|
|
Result.cx := 0
|
|
else
|
|
begin
|
|
ACanvas.TextExtent(AText, R, ATextFlags);
|
|
Result.cx := R.Right - R.Left;
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
if AFlags and CXTO_SINGLELINE <> 0 then
|
|
AFlags := AFlags and not CXTO_SINGLELINE or
|
|
CXTO_WORDBREAK or CXTO_EDITCONTROL;
|
|
AFlags := AFlags or CXTO_CALCRECT;
|
|
R := Rect(0, 0, MaxInt, MaxInt);
|
|
|
|
ARowCount := ALineCount;
|
|
if ARowCount = 0 then
|
|
ARowCount := AEditSizeProperties.MaxLineCount;
|
|
ATextParams := cxCalcTextParams(ACanvas.Canvas, AFlags);
|
|
cxMakeTextRows(ACanvas.Canvas, PChar(AText), Length(AText), R, ATextParams, ATextRows, ARowCount, ARowCount);
|
|
Result.cx := cxGetLongestTextRowWidth(ATextRows, ARowCount);
|
|
cxResetTextRows(ATextRows);
|
|
Result.cy := ACanvas.TextHeight('Zg');
|
|
if ALineCount > 0 then
|
|
Result.cy := Result.cy * ALineCount;
|
|
end;
|
|
if AAlignment <> nil then
|
|
Result.cx := Result.cx + 1;
|
|
if ACorrectWidth then
|
|
Result.cx := Result.cx + ASizeCorrection.cx;
|
|
if Result.cy > 0 then
|
|
Result.cy := Result.cy + ASizeCorrection.cy;
|
|
end;
|
|
|
|
begin
|
|
if AEditSizeProperties.Width >= 0 then
|
|
Result := GetAutoHeightSize
|
|
else
|
|
Result := GetBestFitSize;
|
|
end;
|
|
|
|
function GetTextEditDrawTextOffset(AViewData: TcxCustomEditViewData): TRect;
|
|
begin
|
|
Result := AViewData.EditContentParams.Offsets;
|
|
if not AViewData.IsInplace and (AViewData is TcxCustomTextEditViewData) then
|
|
with AViewData as TcxCustomTextEditViewData do
|
|
if TcxCustomTextEditProperties(Properties).EditingStyle in [esFixedList, esNoEdit] then
|
|
begin
|
|
if AViewData.VertAlignment = taTopJustify then
|
|
begin
|
|
Inc(Result.Top);
|
|
Dec(Result.Bottom);
|
|
end;
|
|
if AViewData.HorzAlignment = taRightJustify then
|
|
Inc(Result.Right)
|
|
else
|
|
Inc(Result.Left);
|
|
end;
|
|
end;
|
|
|
|
function GetTextEditDrawTextOffset(AAlignment: TAlignment; AIsInplace: Boolean): TRect; // deprecated
|
|
begin
|
|
Result := EditContentDefaultOffsets[AIsInplace];
|
|
end;
|
|
|
|
procedure PrepareTextRows(ACanvas: TCanvas; var TextOutData: TcxTextOutData;
|
|
AText: PcxCaptionChar; var R: TRect; AFormat: TcxTextOutFormat; ASelStart,
|
|
ASelLength: Integer; ASelBackgroundColor, ASelTextColor: TColor;
|
|
AMaxLineCount: Integer = 0; ALeftIndent: Integer = 0; ARightIndent: Integer = 0);
|
|
|
|
procedure InternalPrepareTextRows;
|
|
var
|
|
ATextLength: Integer;
|
|
begin
|
|
TextOutData.RowCount := 0;
|
|
cxResetTextRows(TextOutData.TextRows);
|
|
ATextLength := StrLen(AText);
|
|
if ATextLength = 0 then
|
|
Exit;
|
|
TextOutData.TextParams := cxCalcTextParams(ACanvas.Handle, AFormat);
|
|
TextOutData.TextRect := cxPrepareRect(R, TextOutData.TextParams, ALeftIndent,
|
|
ARightIndent);
|
|
|
|
if not IsRectEmpty(TextOutData.TextRect) then
|
|
begin
|
|
TextOutData.ForceEndEllipsis := not cxMakeTextRows(ACanvas.Handle, AText,
|
|
ATextLength, TextOutData.TextRect, TextOutData.TextParams,
|
|
TextOutData.TextRows, TextOutData.RowCount, AMaxLineCount);
|
|
if TextOutData.RowCount <> 0 then
|
|
begin
|
|
cxPlaceTextRows(ACanvas.Handle, TextOutData.TextRect, TextOutData.TextParams, TextOutData.TextRows, TextOutData.RowCount);
|
|
if (ASelStart < 0) or (ASelStart >= ATextLength) then
|
|
ASelLength := 0
|
|
else
|
|
if (ASelLength + ASelStart) > ATextLength then
|
|
ASelLength := ATextLength - ASelStart;
|
|
|
|
TextOutData.SelStart := ASelStart;
|
|
TextOutData.SelLength := ASelLength;
|
|
TextOutData.SelBackgroundColor := ASelBackgroundColor;
|
|
TextOutData.SelTextColor := ASelTextColor;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
TextOutData.Initialized := True;
|
|
InternalPrepareTextRows;
|
|
end;
|
|
|
|
procedure InternalTextOut(ACanvas: TCanvas; AViewInfo: TcxCustomTextEditViewInfo;
|
|
AText: PcxCaptionChar; var R: TRect; AFormat: TcxTextOutFormat; ASelStart,
|
|
ASelLength: Integer; ASelBackgroundColor, ASelTextColor: TColor;
|
|
AMaxLineCount: Integer = 0; ALeftIndent: Integer = 0; ARightIndent: Integer = 0);
|
|
begin
|
|
if not AViewInfo.TextOutData.Initialized then
|
|
PrepareTextRows(ACanvas, AViewInfo.TextOutData, AText, R, AFormat, ASelStart,
|
|
ASelLength, ASelBackgroundColor, ASelTextColor, AMaxLineCount, ALeftIndent,
|
|
ARightIndent);
|
|
TCanvasAccess(ACanvas).RequiredState([csFontValid]);
|
|
with AViewInfo.TextOutData do
|
|
cxTextRowsOutHighlight(ACanvas.Handle, TextRect, TextParams, TextRows,
|
|
RowCount, SelStart, SelLength, SelBackgroundColor, SelTextColor, ForceEndEllipsis);
|
|
end;
|
|
|
|
procedure PrepareTextEditDrawTextFlags(ACanvas: TcxCanvas; AViewData: TcxCustomTextEditViewData;
|
|
AViewInfo: TcxCustomTextEditViewInfo);
|
|
var
|
|
ADrawTextOffset: TRect;
|
|
AFlags: DWORD;
|
|
R: TRect;
|
|
ATextHeight: Integer;
|
|
ATextParams: TcxTextParams;
|
|
ATextRows: TcxTextRows;
|
|
ARowCount: Integer;
|
|
begin
|
|
if AViewData.Style.GetVisibleFont = nil then
|
|
Exit;
|
|
ACanvas.Font := AViewData.Style.GetVisibleFont;
|
|
with AViewInfo do
|
|
begin
|
|
DrawTextFlags := AViewData.GetDrawTextFlags;
|
|
AFlags := DrawTextFlags and not CXTO_SINGLELINE or
|
|
CXTO_WORDBREAK or CXTO_EDITCONTROL or CXTO_CALCROWCOUNT;
|
|
R := Rect(0, 0, TextRect.Right - TextRect.Left, MaxInt);
|
|
ADrawTextOffset := AViewData.GetDrawTextOffset;
|
|
Inc(R.Right, ADrawTextOffset.Left + ADrawTextOffset.Right);
|
|
Dec(R.Right, AViewData.GetEditContentSizeCorrection.cx);
|
|
Dec(R.Right, AViewData.ContentOffset.Left + AViewData.ContentOffset.Right);
|
|
if TcxCustomTextEditProperties(AViewData.Properties).Alignment.Horz = taRightJustify then
|
|
Inc(R.Right);
|
|
ATextParams := cxCalcTextParams(ACanvas.Canvas, AFlags);
|
|
// TODO optimize
|
|
cxMakeTextRows(ACanvas.Canvas, PChar(Text), Length(Text), R, ATextParams, ATextRows, ARowCount,
|
|
(TextRect.Bottom - TextRect.Top + ATextParams.RowHeight - 1) div ATextParams.RowHeight + 1);
|
|
ATextHeight := ARowCount * ATextParams.RowHeight;
|
|
if ARowCount > 1 then
|
|
begin
|
|
DrawTextFlags := DrawTextFlags and not CXTO_SINGLELINE or
|
|
CXTO_WORDBREAK or CXTO_EDITCONTROL;
|
|
if ATextHeight > TextRect.Bottom - TextRect.Top then
|
|
DrawTextFlags := DrawTextFlags and not CXTO_BOTTOM
|
|
and not CXTO_CENTER_VERTICALLY or CXTO_TOP;
|
|
end;
|
|
cxResetTextRows(ATextRows);
|
|
end;
|
|
end;
|
|
|
|
procedure InsertThousandSeparator(var S: string);
|
|
var
|
|
I, J: Integer;
|
|
ACaption: string;
|
|
APrefix, ASuffix: string;
|
|
begin
|
|
APrefix := TrimRight(S);
|
|
ASuffix := Copy(S, Length(APrefix) + 1, Length(S) - Length(APrefix));
|
|
APrefix := TrimLeft(S);
|
|
APrefix := Copy(S, 1, Length(S) - Length(APrefix));
|
|
S := Trim(S);
|
|
ACaption := RemoveExponentialPart(S);
|
|
RemoveThousandSeparator(S);
|
|
I := Pos(DecimalSeparator, S);
|
|
if I = 0 then
|
|
I := Length(S)
|
|
else
|
|
Dec(I);
|
|
J := 0;
|
|
while (I > 1) and cxIsDigitChar(S[I - 1]) do
|
|
begin
|
|
Inc(J);
|
|
if J = 3 then
|
|
begin
|
|
Insert(ThousandSeparator, S, I);
|
|
J := 0;
|
|
end;
|
|
Dec(I);
|
|
end;
|
|
S := APrefix + S + ACaption + ASuffix;
|
|
end;
|
|
|
|
function RemoveExponentialPart(var S: string): string;
|
|
var
|
|
APos: Integer;
|
|
begin
|
|
APos := Pos('E', UpperCase(S));
|
|
if APos > 0 then
|
|
begin
|
|
Result := Copy(S, APos, Length(S) - APos + 1);
|
|
Delete(S, APos, Length(S) - APos + 1);
|
|
end
|
|
else
|
|
Result := '';
|
|
end;
|
|
|
|
procedure RemoveThousandSeparator(var S: string);
|
|
var
|
|
APos: Integer;
|
|
begin
|
|
repeat
|
|
APos := Pos(ThousandSeparator, S);
|
|
if APos <> 0 then
|
|
Delete(S, APos, 1);
|
|
until APos = 0;
|
|
end;
|
|
|
|
procedure SaveTextEditState(ATextEdit: IcxInnerTextEdit;
|
|
ASaveText: Boolean;
|
|
var APrevState: TcxCustomInnerTextEditPrevState);
|
|
begin
|
|
with APrevState do
|
|
begin
|
|
IsPrevTextSaved := ASaveText;
|
|
if ASaveText then
|
|
PrevText := ATextEdit.EditValue;
|
|
PrevSelStart := ATextEdit.SelStart;
|
|
PrevSelLength := ATextEdit.SelLength;
|
|
end;
|
|
end;
|
|
|
|
procedure SeparateDigitGroups(AEdit: TcxCustomTextEdit);
|
|
|
|
function IsValidNumber(S: string): Boolean;
|
|
var
|
|
AValue: Extended;
|
|
begin
|
|
RemoveThousandSeparator(S);
|
|
Result := (S <> '') and TextToFloat(PChar(S), AValue, fvExtended);
|
|
end;
|
|
|
|
function GetRealCaretPos: Integer;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := 0;
|
|
for I := 1 to AEdit.SelStart do
|
|
if AEdit.Text[I] <> ThousandSeparator then
|
|
Inc(Result);
|
|
end;
|
|
|
|
procedure SetRealCaretPos(APrevCaretPos: Integer);
|
|
var
|
|
I: Integer;
|
|
S: string;
|
|
begin
|
|
S := AEdit.Text;
|
|
for I := 1 to Length(S) do
|
|
begin
|
|
if S[I] <> ThousandSeparator then
|
|
Dec(APrevCaretPos);
|
|
if APrevCaretPos = 0 then
|
|
begin
|
|
AEdit.SelStart := I;
|
|
Break;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
var
|
|
ACaretPos: Integer;
|
|
S: string;
|
|
begin
|
|
S := AEdit.Text;
|
|
InsertThousandSeparator(S);
|
|
if IsValidNumber(S) then
|
|
begin
|
|
ACaretPos := GetRealCaretPos;
|
|
AEdit.SetInternalDisplayValue(S);
|
|
SetRealCaretPos(ACaretPos);
|
|
end;
|
|
end;
|
|
|
|
{ TcxCustomInnerTextEditHelper }
|
|
|
|
constructor TcxCustomInnerTextEditHelper.Create(AEdit: TcxCustomInnerTextEdit);
|
|
begin
|
|
inherited Create(nil);
|
|
FEdit := AEdit;
|
|
FAlignmentLock := False;
|
|
end;
|
|
|
|
// IcxContainerInnerControl
|
|
function TcxCustomInnerTextEditHelper.GetControlContainer: TcxContainer;
|
|
begin
|
|
Result := Edit.Container;
|
|
end;
|
|
|
|
function TcxCustomInnerTextEditHelper.GetControl: TWinControl;
|
|
begin
|
|
Result := Edit;
|
|
end;
|
|
|
|
// IcxCustomInnerEdit
|
|
function TcxCustomInnerTextEditHelper.CallDefWndProc(AMsg: UINT; WParam: WPARAM;
|
|
LParam: LPARAM): LRESULT;
|
|
begin
|
|
Result := CallWindowProc(Edit.DefWndProc, Edit.Handle, AMsg, WParam, LParam);
|
|
end;
|
|
|
|
function TcxCustomInnerTextEditHelper.GetEditValue: TcxEditValue;
|
|
begin
|
|
Result := (Edit.Text);
|
|
end;
|
|
|
|
function TcxCustomInnerTextEditHelper.GetOnChange: TNotifyEvent;
|
|
begin
|
|
Result := Edit.OnChange;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEditHelper.LockBounds(ALock: Boolean);
|
|
begin
|
|
with Edit do
|
|
if ALock then
|
|
Inc(FLockBoundsCount)
|
|
else
|
|
if FLockBoundsCount > 0 then
|
|
Dec(FLockBoundsCount);
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEditHelper.SafelySetFocus;
|
|
var
|
|
APrevAutoSelect: Boolean;
|
|
begin
|
|
with Edit do
|
|
begin
|
|
APrevAutoSelect := AutoSelect;
|
|
AutoSelect := False;
|
|
SetFocus;
|
|
AutoSelect := APrevAutoSelect;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEditHelper.SetEditValue(const Value: TcxEditValue);
|
|
var
|
|
ATextChanged: Boolean;
|
|
AIsDesigning: Boolean;
|
|
begin
|
|
with Edit do
|
|
begin
|
|
AIsDesigning := csDesigning in ComponentState;
|
|
if AIsDesigning then
|
|
ATextChanged := not InternalCompareString(Text, VarToStr(Value), True)
|
|
else
|
|
ATextChanged := False;
|
|
Text := VarToStr(Value);
|
|
if ATextChanged then
|
|
Change;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEditHelper.SetParent(Value: TWinControl);
|
|
begin
|
|
Edit.Parent := Value;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEditHelper.SetOnChange(Value: TNotifyEvent);
|
|
begin
|
|
Edit.OnChange := Value;
|
|
end;
|
|
|
|
// IcxInnerTextEdit
|
|
procedure TcxCustomInnerTextEditHelper.ClearSelection;
|
|
begin
|
|
Edit.ClearSelection;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEditHelper.CopyToClipboard;
|
|
begin
|
|
Edit.CopyToClipboard;
|
|
end;
|
|
|
|
function TcxCustomInnerTextEditHelper.GetAlignment: TAlignment;
|
|
begin
|
|
Result := Edit.FAlignment;
|
|
end;
|
|
|
|
function TcxCustomInnerTextEditHelper.GetAutoSelect: Boolean;
|
|
begin
|
|
Result := Edit.AutoSelect;
|
|
end;
|
|
|
|
function TcxCustomInnerTextEditHelper.GetCharCase: TEditCharCase;
|
|
begin
|
|
Result := Edit.CharCase;
|
|
end;
|
|
|
|
function TcxCustomInnerTextEditHelper.GetEchoMode: TcxEditEchoMode;
|
|
begin
|
|
Result := Edit.FEchoMode;
|
|
end;
|
|
|
|
function TcxCustomInnerTextEditHelper.GetFirstVisibleCharIndex: Integer;
|
|
begin
|
|
Result := LoWord(SendMessage(Edit.Handle, EM_CHARFROMPOS, 0, 0));
|
|
end;
|
|
|
|
function TcxCustomInnerTextEditHelper.GetHideSelection: Boolean;
|
|
begin
|
|
Result := Edit.HideSelection;
|
|
end;
|
|
|
|
function TcxCustomInnerTextEditHelper.GetImeLastChar: Char;
|
|
begin
|
|
if Edit.FImeCharCount = 2 then
|
|
Result := Edit.FImeLastChar
|
|
else
|
|
Result := #0;
|
|
end;
|
|
|
|
function TcxCustomInnerTextEditHelper.GetImeMode: TImeMode;
|
|
begin
|
|
Result := Edit.ImeMode;
|
|
end;
|
|
|
|
function TcxCustomInnerTextEditHelper.GetImeName: TImeName;
|
|
begin
|
|
Result := Edit.ImeName;
|
|
end;
|
|
|
|
function TcxCustomInnerTextEditHelper.GetInternalUpdating: Boolean;
|
|
begin
|
|
Result := Edit.FInternalUpdating;
|
|
end;
|
|
|
|
function TcxCustomInnerTextEditHelper.GetIsInplace: Boolean;
|
|
begin
|
|
Result := Edit.Container.IsInplace;
|
|
end;
|
|
|
|
function TcxCustomInnerTextEditHelper.GetMaxLength: Integer;
|
|
begin
|
|
Result := Edit.MaxLength;
|
|
end;
|
|
|
|
function TcxCustomInnerTextEditHelper.GetMultiLine: Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
function TcxCustomInnerTextEditHelper.GetPasswordChar: TCaptionChar;
|
|
begin
|
|
Result := Edit.FPasswordChar;
|
|
end;
|
|
|
|
function TcxCustomInnerTextEditHelper.GetOEMConvert: Boolean;
|
|
begin
|
|
Result := Edit.OEMConvert;
|
|
end;
|
|
|
|
function TcxCustomInnerTextEditHelper.GetOnSelChange: TNotifyEvent;
|
|
begin
|
|
Result := Edit.OnSelChange;
|
|
end;
|
|
|
|
function TcxCustomInnerTextEditHelper.GetReadOnly: Boolean;
|
|
begin
|
|
Result := Edit.ReadOnly;
|
|
end;
|
|
|
|
function TcxCustomInnerTextEditHelper.GetSelLength: Integer;
|
|
begin
|
|
with Edit do
|
|
if FImeCharCount > 0 then
|
|
Result := Self.FSelLength
|
|
else
|
|
Result := SelLength;
|
|
end;
|
|
|
|
function TcxCustomInnerTextEditHelper.GetSelStart: Integer;
|
|
begin
|
|
with Edit do
|
|
if FImeCharCount > 0 then
|
|
Result := Self.FSelStart
|
|
else
|
|
Result := SelStart;
|
|
end;
|
|
|
|
function TcxCustomInnerTextEditHelper.GetSelText: string;
|
|
begin
|
|
Result := Edit.SelText;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEditHelper.SelectAll;
|
|
begin
|
|
with Edit do
|
|
if HandleAllocated then
|
|
SelectAll;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEditHelper.SetAlignment(Value: TAlignment);
|
|
begin
|
|
if FAlignmentLock then Exit;
|
|
if GetUseLeftAlignmentOnEditing and GetIsInplace then
|
|
Value := taLeftJustify;
|
|
with Edit do
|
|
if Value <> FAlignment then
|
|
begin
|
|
FAlignment := Value;
|
|
FAlignmentLock := True;
|
|
try
|
|
RecreateWnd;
|
|
finally
|
|
FAlignmentLock := False;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEditHelper.SetAutoSelect(Value: Boolean);
|
|
begin
|
|
Edit.AutoSelect := Value;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEditHelper.SetCharCase(Value: TEditCharCase);
|
|
begin
|
|
with Edit do
|
|
begin
|
|
CharCase := Value;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEditHelper.SetEchoMode(Value: TcxEditEchoMode);
|
|
begin
|
|
with Edit do
|
|
if Value <> FEchoMode then
|
|
begin
|
|
FEchoMode := Value;
|
|
UpdateEchoMode;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEditHelper.SetHideSelection(Value: Boolean);
|
|
begin
|
|
Edit.HideSelection := Value;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEditHelper.SetInternalUpdating(Value: Boolean);
|
|
begin
|
|
Edit.FInternalUpdating := Value;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEditHelper.SetImeMode(Value: TImeMode);
|
|
begin
|
|
Edit.ImeMode := Value;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEditHelper.SetImeName(const Value: TImeName);
|
|
begin
|
|
Edit.ImeName := Value;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEditHelper.SetMaxLength(Value: Integer);
|
|
begin
|
|
Edit.MaxLength := Value;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEditHelper.SetOEMConvert(Value: Boolean);
|
|
begin
|
|
Edit.OEMConvert := Value;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEditHelper.SetOnSelChange(Value: TNotifyEvent);
|
|
begin
|
|
Edit.OnSelChange := Value;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEditHelper.SetPasswordChar(Value: TCaptionChar);
|
|
begin
|
|
with Edit do
|
|
if Value <> FPasswordChar then
|
|
begin
|
|
FPasswordChar := Value;
|
|
if FEchoMode = eemPassword then
|
|
UpdateEchoMode;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEditHelper.SetReadOnly(Value: Boolean);
|
|
begin
|
|
Edit.ReadOnly := Value;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEditHelper.SetSelLength(Value: Integer);
|
|
begin
|
|
with Edit do
|
|
if HandleAllocated then
|
|
if FImeCharCount > 0 then
|
|
Self.FSelLength := Value
|
|
else
|
|
SelLength := Value;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEditHelper.SetSelStart(Value: Integer);
|
|
begin
|
|
with Edit do
|
|
begin
|
|
if not HandleAllocated then
|
|
Exit;
|
|
if FImeCharCount > 0 then
|
|
begin
|
|
Self.FSelStart := Value;
|
|
Exit;
|
|
end;
|
|
SelStart := Value;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEditHelper.SetSelText(Value: string);
|
|
begin
|
|
Edit.SelText := Value;
|
|
end;
|
|
|
|
{$IFDEF DELPHI12}
|
|
function TcxCustomInnerTextEditHelper.GetTextHint: string;
|
|
begin
|
|
Result := Edit.TextHint;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEditHelper.SetTextHint(Value: string);
|
|
begin
|
|
Edit.TextHint := Value;
|
|
end;
|
|
{$ENDIF}
|
|
|
|
function TcxCustomInnerTextEditHelper.GetUseLeftAlignmentOnEditing: Boolean;
|
|
begin
|
|
Result := Edit.Container.ActiveProperties.UseLeftAlignmentOnEditing;
|
|
end;
|
|
|
|
{ TcxCustomInnerTextEdit }
|
|
|
|
constructor TcxCustomInnerTextEdit.Create(AOwner: TComponent);
|
|
begin
|
|
FIsCreating := True;
|
|
inherited Create(AOwner);
|
|
InitializeDblClickTimer;
|
|
FHelper := TcxCustomInnerTextEditHelper.Create(Self);
|
|
ControlStyle := ControlStyle + [csDoubleClicks];
|
|
ParentColor := True;
|
|
ParentFont := False;
|
|
FAlignment := cxEditDefaultHorzAlignment;
|
|
FInternalUpdating := False;
|
|
FEchoMode := eemNormal;
|
|
UpdateEchoMode;
|
|
FIsCreating := False;
|
|
end;
|
|
|
|
destructor TcxCustomInnerTextEdit.Destroy;
|
|
begin
|
|
FreeAndNil(FHelper);
|
|
FreeAndNil(FDblClickTimer);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEdit.DragDrop(Source: TObject; X, Y: Integer);
|
|
begin
|
|
Container.DragDrop(Source, Left + X, Top + Y);
|
|
end;
|
|
|
|
function TcxCustomInnerTextEdit.ExecuteAction(Action: TBasicAction): Boolean;
|
|
begin
|
|
Result := inherited ExecuteAction(Action) or
|
|
Container.DataBinding.ExecuteAction(Action);
|
|
end;
|
|
|
|
function TcxCustomInnerTextEdit.UpdateAction(Action: TBasicAction): Boolean;
|
|
begin
|
|
Result := inherited UpdateAction(Action) or
|
|
Container.DataBinding.UpdateAction(Action);
|
|
end;
|
|
|
|
function TcxCustomInnerTextEdit.CanFocus: Boolean;
|
|
begin
|
|
Result := Container.CanFocus;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEdit.DefaultHandler(var Message);
|
|
begin
|
|
if not Container.InnerControlDefaultHandler(TMessage(Message)) then
|
|
inherited DefaultHandler(Message);
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEdit.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
|
|
begin
|
|
if not FIsCreating and (FLockBoundsCount = 0) then
|
|
begin
|
|
Container.LockAlignControls(True);
|
|
try
|
|
inherited SetBounds(ALeft, ATop, AWidth, AHeight);
|
|
finally
|
|
Container.LockAlignControls(False);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEdit.AdjustAlignment;
|
|
begin
|
|
if NeedAdjustAlignment then
|
|
begin
|
|
if Container.IsActiveControl then
|
|
begin
|
|
Helper.SetAlignment(taLeftJustify);
|
|
Container.ShortRefreshContainer(False);
|
|
end
|
|
else
|
|
SetBasedAlignment;
|
|
end;
|
|
end;
|
|
|
|
// for Delphi .NET
|
|
procedure TcxCustomInnerTextEdit.Change;
|
|
begin
|
|
inherited Change;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEdit.Click;
|
|
begin
|
|
inherited Click;
|
|
Container.Click;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEdit.CreateHandle;
|
|
begin
|
|
Container.ClearSavedChildControlRegions;
|
|
inherited CreateHandle;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEdit.CreateParams(var Params: TCreateParams);
|
|
const
|
|
AAlignmentMap: array[TAlignment] of DWORD = (ES_LEFT, ES_RIGHT, ES_CENTER);
|
|
begin
|
|
inherited CreateParams(Params);
|
|
with Params do
|
|
begin
|
|
Style := Style or AAlignmentMap[Alignment];
|
|
Style := Style and (not WS_BORDER);
|
|
Style := Style and (not WS_DLGFRAME);
|
|
Style := Style and (not WS_SIZEBOX);
|
|
Style := Style and (not WS_THICKFRAME);
|
|
Style := Style or ES_AUTOHSCROLL;
|
|
ExStyle := ExStyle and (not WS_EX_CLIENTEDGE);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEdit.CreateWindowHandle(const Params: TCreateParams);
|
|
var
|
|
AParams: TCreateParams;
|
|
begin
|
|
AParams := Params;
|
|
AParams.Caption := '';
|
|
inherited CreateWindowHandle(AParams);
|
|
if HandleAllocated then
|
|
CallWindowProc(DefWndProc, Handle, WM_SETTEXT, 0, Integer(WindowText));
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEdit.CreateWnd;
|
|
begin
|
|
inherited CreateWnd;
|
|
AdjustMargins;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEdit.DblClick;
|
|
begin
|
|
inherited DblClick;
|
|
Container.DblClick;
|
|
end;
|
|
|
|
function TcxCustomInnerTextEdit.DoMouseWheel(Shift: TShiftState; WheelDelta: Integer;
|
|
MousePos: TPoint): Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEdit.DragOver(Source: TObject; X, Y: Integer;
|
|
State: TDragState; var Accept: Boolean);
|
|
begin
|
|
Container.DragOver(Source, Left + X, Top + Y, State, Accept);
|
|
end;
|
|
|
|
function TcxCustomInnerTextEdit.GetBasedAlignment: TAlignment;
|
|
begin
|
|
Result := Container.ActiveProperties.Alignment.Horz;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEdit.KeyDown(var Key: Word; Shift: TShiftState);
|
|
begin
|
|
FDblClickTimer.Enabled := False;
|
|
FInternalUpdating := False;
|
|
try
|
|
Container.KeyDown(Key, Shift);
|
|
finally
|
|
if Key = 0 then
|
|
FInternalUpdating := True;
|
|
end;
|
|
if Key <> 0 then
|
|
inherited KeyDown(Key, Shift);
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEdit.KeyPress(var Key: Char);
|
|
var
|
|
AKey: Word;
|
|
begin
|
|
FInternalUpdating := False;
|
|
try
|
|
AKey := Word(Key);
|
|
if (AKey = VK_TAB) then
|
|
Key := #0;
|
|
Container.KeyPress(Key);
|
|
|
|
AKey := Word(Key);
|
|
if (Container.IsInplace or Container.FIsPopupWindowJustClosed or
|
|
(not Container.BeepOnEnter and (AKey = VK_RETURN))) and
|
|
((AKey = VK_RETURN) or (AKey = VK_ESCAPE)) then
|
|
begin
|
|
Key := #0;
|
|
Container.FIsPopupWindowJustClosed := False;
|
|
end;
|
|
finally
|
|
if Key = #0 then
|
|
FInternalUpdating := True
|
|
end;
|
|
if Key <> #0 then
|
|
inherited KeyPress(Key);
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEdit.KeyUp(var Key: Word; Shift: TShiftState);
|
|
begin
|
|
FInternalUpdating := False;
|
|
try
|
|
if (Key = VK_TAB) then
|
|
Key := 0;
|
|
Container.KeyUp(Key, Shift);
|
|
finally
|
|
if Key = 0 then
|
|
FInternalUpdating := True;
|
|
end;
|
|
if Key <> 0 then
|
|
inherited KeyUp(Key, Shift);
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEdit.MouseDown(Button: TMouseButton;
|
|
Shift: TShiftState; X, Y: Integer);
|
|
begin
|
|
inherited MouseDown(Button, Shift, X, Y);
|
|
with Container do
|
|
begin
|
|
InnerControlMouseDown := True;
|
|
try
|
|
MouseDown(Button, Shift, X + Self.Left, Y + Self.Top);
|
|
finally
|
|
InnerControlMouseDown := False;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEdit.MouseMove(Shift: TShiftState; X, Y: Integer);
|
|
begin
|
|
inherited MouseMove(Shift, X, Y);
|
|
Container.MouseMove(Shift, X + Left, Y + Top);
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEdit.MouseUp(Button: TMouseButton;
|
|
Shift: TShiftState; X, Y: Integer);
|
|
begin
|
|
inherited MouseUp(Button, Shift, X, Y);
|
|
Container.MouseUp(Button, Shift, X + Left, Y + Top);
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEdit.WndProc(var Message: TMessage);
|
|
begin
|
|
if Container.InnerControlMenuHandler(Message) then
|
|
Exit;
|
|
case Message.Msg of
|
|
WM_LBUTTONDOWN:
|
|
if NeedAdjustAlignment and (FAlignment <> taLeftJustify) then
|
|
begin
|
|
ControlState := ControlState + [csLButtonDown];
|
|
SetFocus;
|
|
inherited WndProc(Message);
|
|
FDblClickTimer.Enabled := True;
|
|
FDblClickLock := True;
|
|
end
|
|
else
|
|
begin
|
|
if (Container.DragMode = dmAutomatic) and not Container.IsDesigning then
|
|
Container.BeginAutoDrag
|
|
else
|
|
begin
|
|
if FDblClickTimer.Enabled then
|
|
begin
|
|
Message.Msg := WM_LBUTTONDBLCLK;
|
|
FDblClickTimer.Enabled := False;
|
|
FDblClickTimer.Enabled := True;
|
|
end;
|
|
FDblClickLock := False;
|
|
inherited WndProc(Message);
|
|
end;
|
|
end;
|
|
WM_LBUTTONDBLCLK:
|
|
begin
|
|
if (Container.DragMode = dmAutomatic) and not Container.IsDesigning then
|
|
Container.BeginAutoDrag
|
|
else
|
|
begin
|
|
if not FDblClickTimer.Enabled then
|
|
inherited WndProc(Message);
|
|
end;
|
|
end;
|
|
WM_PAINT:
|
|
begin
|
|
if Container.OnGlass and IsCompositionEnabled then
|
|
begin
|
|
WMPaintWindowOnGlass(Handle);
|
|
Message.Result := 0;
|
|
end
|
|
else
|
|
inherited WndProc(Message);
|
|
end;
|
|
CN_CTLCOLOREDIT, CN_CTLCOLORSTATIC:
|
|
begin
|
|
inherited WndProc(Message);
|
|
if not FRepaintOnGlass and Container.OnGlass and
|
|
IsCompositionEnabled then
|
|
begin
|
|
FRepaintOnGlass := True;
|
|
PostMessage(Handle, CM_BUFFEREDPAINTONGLASS, 0, 0);
|
|
end;
|
|
end;
|
|
CM_BUFFEREDPAINTONGLASS:
|
|
if FRepaintOnGlass then
|
|
begin
|
|
RepaintWindowOnGlass(Handle);
|
|
FRepaintOnGlass := False;
|
|
end;
|
|
else
|
|
inherited WndProc(Message);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEdit.AdjustMargins;
|
|
begin
|
|
SendMessage(Handle, EM_SETMARGINS, EC_LEFTMARGIN + EC_RIGHTMARGIN, 1 shl 16);
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEdit.MouseEnter(AControl: TControl);
|
|
begin
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEdit.MouseLeave(AControl: TControl);
|
|
begin
|
|
Container.ShortRefreshContainer(True);
|
|
end;
|
|
|
|
// for Delphi .NET
|
|
procedure TcxCustomInnerTextEdit.RecreateWnd;
|
|
begin
|
|
inherited RecreateWnd;
|
|
end;
|
|
|
|
// IcxContainerInnerControl
|
|
function TcxCustomInnerTextEdit.GetControl: TWinControl;
|
|
begin
|
|
Result := Self;
|
|
end;
|
|
|
|
function TcxCustomInnerTextEdit.GetControlContainer: TcxContainer;
|
|
begin
|
|
Result := Container;
|
|
end;
|
|
|
|
// IcxInnerEditHelper
|
|
function TcxCustomInnerTextEdit.GetHelper: IcxCustomInnerEdit;
|
|
begin
|
|
Result := Helper;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEdit.DblClickTimerHandle(Sender: TObject);
|
|
begin
|
|
FDblClickTimer.Enabled := False;
|
|
end;
|
|
|
|
function TcxCustomInnerTextEdit.GetContainer: TcxCustomTextEdit;
|
|
begin
|
|
Result := TcxCustomTextEdit(Owner);
|
|
end;
|
|
|
|
function TcxCustomInnerTextEdit.GetCursorPos: Integer;
|
|
var
|
|
X: Integer;
|
|
P: TPoint;
|
|
I, I0, I1: Smallint;
|
|
ATextLength: Integer;
|
|
begin
|
|
ATextLength := Length(Text);
|
|
GetCaretPos(P);
|
|
I0 := 0;
|
|
I1 := ATextLength - 1;
|
|
repeat
|
|
I := (I0 + I1) div 2;
|
|
X := Smallint(SendMessage(Handle, EM_POSFROMCHAR, I, 0) and $FFFF);
|
|
if X < P.X then
|
|
I0 := I
|
|
else
|
|
I1 := I;
|
|
until I1 - I0 < 2;
|
|
if SendMessage(Handle, EM_POSFROMCHAR, I0, 0) and $FFFF = P.X then
|
|
Result := I0
|
|
else if SendMessage(Handle, EM_POSFROMCHAR, I1, 0) and $FFFF = P.X then
|
|
Result := I1
|
|
else
|
|
Result := I1 + 1;
|
|
end;
|
|
|
|
function TcxCustomInnerTextEdit.GetIsDestroying: Boolean;
|
|
begin
|
|
Result := csDestroying in ComponentState;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEdit.InitializeDblClickTimer;
|
|
begin
|
|
FreeAndNil(FDblClickTimer);
|
|
FDblClickTimer := TcxTimer.Create(Self);
|
|
with FDblClickTimer do
|
|
begin
|
|
Enabled := False;
|
|
OnTimer := DblClickTimerHandle;
|
|
Interval := GetDoubleClickTime;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEdit.SetBasedAlignment;
|
|
begin
|
|
Helper.SetAlignment(GetBasedAlignment);
|
|
Container.ShortRefreshContainer(False);
|
|
end;
|
|
|
|
function TcxCustomInnerTextEdit.NeedAdjustAlignment: Boolean;
|
|
begin
|
|
Result := Helper.UseLeftAlignmentOnEditing and (GetBasedAlignment <> taLeftJustify);
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEdit.UpdateEchoMode;
|
|
begin
|
|
if FEchoMode = eemNormal then
|
|
PasswordChar := #0
|
|
else
|
|
if FPasswordChar = #0 then
|
|
PasswordChar := '*'
|
|
else
|
|
PasswordChar := FPasswordChar;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEdit.WMChar(var Message: TWMChar);
|
|
var
|
|
APrevState: TcxCustomInnerTextEditPrevState;
|
|
begin
|
|
SaveTextEditState(Helper, True, APrevState);
|
|
FInternalUpdating := False;
|
|
inherited;
|
|
if FImeCharCount > 0 then
|
|
begin
|
|
Dec(FImeCharCount);
|
|
if (FImeCharCount = 0) and Container.FindSelection then
|
|
begin
|
|
SelStart := Helper.FSelStart;
|
|
SelLength := Helper.FSelLength;
|
|
end;
|
|
end;
|
|
Container.UnlockLookupDataTextChanged;
|
|
if FInternalUpdating then
|
|
Exit;
|
|
if CheckTextEditState(Helper, APrevState) then
|
|
Container.FindSelection := False;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEdit.WMClear(var Message: TMessage);
|
|
begin
|
|
if not ReadOnly then
|
|
with Container do
|
|
begin
|
|
KeyboardAction := True;
|
|
try
|
|
ClearSelection;
|
|
finally
|
|
KeyboardAction := False;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEdit.WMCut(var Message: TMessage);
|
|
begin
|
|
with Container do
|
|
begin
|
|
KeyboardAction := True;
|
|
try
|
|
if not Self.ReadOnly then
|
|
CutToClipboard
|
|
else
|
|
CopyToClipboard;
|
|
finally
|
|
KeyboardAction := False;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEdit.WMEraseBkgnd(var Message: TWMEraseBkgnd);
|
|
begin
|
|
Message.Result := 1;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEdit.WMGetDlgCode(var Message: TWMGetDlgCode);
|
|
begin
|
|
inherited;
|
|
with Message do
|
|
begin
|
|
Result := Result or DLGC_WANTCHARS;
|
|
if Container.TabsNeeded and (GetKeyState(VK_CONTROL) >= 0) then
|
|
Result := Result or DLGC_WANTTAB;
|
|
if Container.IsInplace or Container.HasPopupWindow then
|
|
Result := Result or DLGC_WANTALLKEYS;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEdit.WMIMEChar(var Message: TMessage);
|
|
begin
|
|
if (Message.WParam and $FF00) shr 8 <> 0 then
|
|
begin
|
|
FImeCharCount := 2;
|
|
FImeLastChar := Char(Message.WParam and $FF);
|
|
end
|
|
else
|
|
FImeCharCount := 1;
|
|
|
|
Helper.FSelStart := SelStart;
|
|
Helper.FSelLength := SelLength;
|
|
inherited;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEdit.WMIMEComposition(var Message: TMessage);
|
|
begin
|
|
if Container.DoEditing then
|
|
inherited;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEdit.WMKeyDown(var Message: TWMKeyDown);
|
|
var
|
|
AKey: Word;
|
|
APrevState: TcxCustomInnerTextEditPrevState;
|
|
AShiftState: TShiftState;
|
|
begin
|
|
AShiftState := KeyDataToShiftState(Message.KeyData);
|
|
if Container.HasPopupWindow and Container.ActiveProperties.IsPopupKey(Message.CharCode, AShiftState) then
|
|
with Container.ILookupData do
|
|
if ActiveControl is TWinControl then
|
|
begin
|
|
SendMessage(TWinControl(ActiveControl).Handle, WM_KEYDOWN, TMessage(Message).WParam, TMessage(Message).LParam);
|
|
if Message.Result = 0 then
|
|
Exit;
|
|
end;
|
|
|
|
SaveTextEditState(Helper, True, APrevState);
|
|
FInternalUpdating := False;
|
|
inherited;
|
|
if (Message.CharCode = 0) or FInternalUpdating then
|
|
Exit;
|
|
if not CheckTextEditState(Helper, APrevState) then
|
|
begin
|
|
AKey := Message.CharCode;
|
|
AShiftState := KeyDataToShiftState(Message.KeyData);
|
|
Container.DoAfterKeyDown(AKey, AShiftState);
|
|
Message.CharCode := AKey;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEdit.WMKillFocus(var Message: TWMKillFocus);
|
|
begin
|
|
inherited;
|
|
if not IsDestroying then
|
|
begin
|
|
FDblClickTimer.Enabled := False;
|
|
SetBasedAlignment;
|
|
Container.FocusChanged;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEdit.WMNCPaint(var Message: TWMNCPaint);
|
|
begin
|
|
Message.Result := 0;
|
|
Exit;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEdit.WMPaste(var Message: TMessage);
|
|
begin
|
|
if not ReadOnly then
|
|
with Container do
|
|
begin
|
|
KeyboardAction := True;
|
|
try
|
|
PasteFromClipboard;
|
|
finally
|
|
KeyboardAction := False;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEdit.WMSetFocus(var Message: TWMSetFocus);
|
|
begin
|
|
if not IsDestroying then
|
|
AdjustAlignment;
|
|
inherited;
|
|
if not IsDestroying then
|
|
begin
|
|
if Message.FocusedWnd <> Container.Handle then
|
|
Container.FocusChanged;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEdit.WMSize(var Message: TWMSize);
|
|
begin
|
|
inherited;
|
|
AdjustMargins;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEdit.WMUndo(var Message: TWMSize);
|
|
begin
|
|
inherited;
|
|
Container.UndoPerformed;
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEdit.CMMouseEnter(var Message: TMessage);
|
|
begin
|
|
inherited;
|
|
if Message.lParam = 0 then
|
|
MouseEnter(Self)
|
|
else
|
|
MouseEnter(TControl(Message.lParam));
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEdit.CMMouseLeave(var Message: TMessage);
|
|
begin
|
|
inherited;
|
|
if Message.lParam = 0 then
|
|
MouseLeave(Self)
|
|
else
|
|
MouseLeave(TControl(Message.lParam));
|
|
end;
|
|
|
|
procedure TcxCustomInnerTextEdit.EMSetSel(var Message: TMessage);
|
|
begin
|
|
inherited;
|
|
if Assigned(OnSelChange) then
|
|
OnSelChange(Self);
|
|
end;
|
|
|
|
{ TcxTextEditPropertiesValues }
|
|
|
|
procedure TcxTextEditPropertiesValues.Assign(Source: TPersistent);
|
|
begin
|
|
if Source is TcxTextEditPropertiesValues then
|
|
begin
|
|
BeginUpdate;
|
|
try
|
|
inherited Assign(Source);
|
|
with Source as TcxTextEditPropertiesValues do
|
|
begin
|
|
Self.DisplayFormat := DisplayFormat;
|
|
Self.EditFormat := EditFormat;
|
|
Self.MaxLength := MaxLength;
|
|
end;
|
|
finally
|
|
EndUpdate;
|
|
end;
|
|
end
|
|
else
|
|
inherited Assign(Source);
|
|
end;
|
|
|
|
procedure TcxTextEditPropertiesValues.RestoreDefaults;
|
|
begin
|
|
BeginUpdate;
|
|
try
|
|
inherited RestoreDefaults;
|
|
DisplayFormat := False;
|
|
EditFormat := False;
|
|
MaxLength := False;
|
|
finally
|
|
EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
function TcxTextEditPropertiesValues.IsDisplayFormatStored: Boolean;
|
|
begin
|
|
Result := DisplayFormat and
|
|
(TcxCustomTextEditProperties(Properties).FDisplayFormat = '') and
|
|
IsPropertiesPropertyVisible('DisplayFormat');
|
|
end;
|
|
|
|
function TcxTextEditPropertiesValues.IsEditFormatStored: Boolean;
|
|
begin
|
|
Result := EditFormat and
|
|
(TcxCustomTextEditProperties(Properties).FEditFormat = '') and
|
|
IsPropertiesPropertyVisible('EditFormat');
|
|
end;
|
|
|
|
procedure TcxTextEditPropertiesValues.SetDisplayFormat(Value: Boolean);
|
|
begin
|
|
if Value <> FDisplayFormat then
|
|
begin
|
|
FDisplayFormat := Value;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTextEditPropertiesValues.SetEditFormat(Value: Boolean);
|
|
begin
|
|
if Value <> FEditFormat then
|
|
begin
|
|
FEditFormat := Value;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTextEditPropertiesValues.SetMaxLength(Value: Boolean);
|
|
begin
|
|
if Value <> FMaxLength then
|
|
begin
|
|
FMaxLength := Value;
|
|
TcxCustomTextEditProperties(Properties).MaxLengthChanged;
|
|
end;
|
|
end;
|
|
|
|
{ TcxCustomEditListBox }
|
|
|
|
constructor TcxCustomEditListBox.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FHotTrack := True;
|
|
BorderStyle := bsNone;
|
|
end;
|
|
|
|
function TcxCustomEditListBox.GetHeight(ARowCount: Integer; AMaxHeight: Integer): Integer;
|
|
begin
|
|
Result := ARowCount * GetItemHeight;
|
|
end;
|
|
|
|
function TcxCustomEditListBox.GetItemHeight(AIndex: Integer = -1): Integer;
|
|
begin
|
|
Result := GetDefaultItemHeight;
|
|
end;
|
|
|
|
function TcxCustomEditListBox.GetItemWidth(AIndex: Integer): Integer;
|
|
begin
|
|
Canvas.Font.Assign(Font);
|
|
Result := Canvas.TextWidth(GetItem(AIndex));
|
|
end;
|
|
|
|
function TcxCustomEditListBox.IsVisible: Boolean;
|
|
begin
|
|
Result := HandleAllocated and IsWindowVisible(Handle);
|
|
end;
|
|
|
|
procedure TcxCustomEditListBox.SetScrollWidth(Value: Integer);
|
|
begin
|
|
ScrollWidth := 0;
|
|
ScrollWidth := Value;
|
|
end;
|
|
|
|
procedure TcxCustomEditListBox.Click;
|
|
begin
|
|
inherited Click;
|
|
DoSelectItem;
|
|
end;
|
|
|
|
function TcxCustomEditListBox.DoMouseWheel(Shift: TShiftState; WheelDelta: Integer;
|
|
MousePos: TPoint): Boolean;
|
|
const
|
|
AScrollDirectionMap: array [Boolean] of Integer = (SB_LINEDOWN, SB_LINEUP);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := inherited DoMouseWheel(Shift, WheelDelta, MousePos);
|
|
if Result then
|
|
Exit;
|
|
for I := 0 to Mouse.WheelScrollLines - 1 do
|
|
Result := (SendMessage(Handle, WM_VScroll, AScrollDirectionMap[WheelDelta > 0], 0) = 0);
|
|
end;
|
|
|
|
procedure TcxCustomEditListBox.DrawItem(Index: Integer; Rect: TRect; State: TOwnerDrawState);
|
|
var
|
|
AFlags: Longint;
|
|
AText: string;
|
|
begin
|
|
if DoDrawItem(Index, Rect, State) then
|
|
Exit;
|
|
Canvas.FillRect(Rect);
|
|
if (Index >= 0) and (Index < Items.Count) then
|
|
begin
|
|
AFlags := DrawTextBiDiModeFlags(DT_SINGLELINE or DT_VCENTER or DT_NOPREFIX);
|
|
if not UseRightToLeftAlignment then
|
|
Inc(Rect.Left, 2)
|
|
else
|
|
Dec(Rect.Right, 2);
|
|
AText := GetItem(Index);
|
|
DrawText(Canvas.Handle, PChar(AText), Length(AText), Rect, AFlags);
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomEditListBox.GetItemData(Index: Integer):
|
|
Longint;
|
|
begin
|
|
Result := 0;
|
|
end;
|
|
|
|
function TcxCustomEditListBox.NeedDrawFocusRect: Boolean;
|
|
begin
|
|
Result := Edit.ActiveProperties.EditingStyle in [esFixedList, esNoEdit];
|
|
end;
|
|
|
|
procedure TcxCustomEditListBox.MeasureItem(Index: Integer; var Height: Integer);
|
|
begin
|
|
Height := GetItemHeight;
|
|
end;
|
|
|
|
procedure TcxCustomEditListBox.MouseMove(Shift: TShiftState; X, Y: Integer);
|
|
var
|
|
AItemIndex: Integer;
|
|
begin
|
|
inherited MouseMove(Shift, X, Y);
|
|
if (GetCaptureControl <> Self) and HotTrack then
|
|
begin
|
|
AItemIndex := ItemAtPos(Point(X, Y), False);
|
|
if (AItemIndex <> -1) and (ItemIndex <> AItemIndex) then
|
|
ItemIndex := AItemIndex;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomEditListBox.SetItemData(Index: Integer;
|
|
AData: Longint);
|
|
begin
|
|
end;
|
|
|
|
function TcxCustomEditListBox.DoDrawItem(AIndex: Integer; const ARect: TRect;
|
|
AState: TOwnerDrawState): Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
procedure TcxCustomEditListBox.DoSelectItem;
|
|
begin
|
|
SetExternalScrollBarsParameters;
|
|
if Assigned(FOnSelectItem) then
|
|
FOnSelectItem(Self);
|
|
end;
|
|
|
|
function TcxCustomEditListBox.GetDefaultItemHeight: Integer;
|
|
begin
|
|
Canvas.Font := Font;
|
|
Result := Canvas.TextHeight('Wg');
|
|
end;
|
|
|
|
function TcxCustomEditListBox.GetItem(Index: Integer): string;
|
|
begin
|
|
Result := Items[Index];
|
|
end;
|
|
|
|
procedure TcxCustomEditListBox.InternalRecreateWindow;
|
|
begin
|
|
RecreateWnd;
|
|
end;
|
|
|
|
procedure TcxCustomEditListBox.RecreateWindow;
|
|
begin
|
|
end;
|
|
|
|
procedure TcxCustomEditListBox.SetItemCount(Value: Integer);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
with Items do
|
|
begin
|
|
if Value = Count then
|
|
Exit;
|
|
BeginUpdate;
|
|
try
|
|
if Value > Count then
|
|
for I := 1 to Value - Count do
|
|
Add('')
|
|
else
|
|
for I := 1 to Count - Value do
|
|
Delete(Count - 1);
|
|
finally
|
|
EndUpdate;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomEditListBox.SetItemIndex(const Value: Integer);
|
|
begin
|
|
{$IFDEF DELPHI6}
|
|
inherited SetItemIndex(Value);
|
|
{$ELSE}
|
|
inherited ItemIndex := Value;
|
|
{$ENDIF}
|
|
DoSelectItem;
|
|
end;
|
|
|
|
procedure TcxCustomEditListBox.CMShowingChanged(var Message: TMessage);
|
|
begin
|
|
inherited;
|
|
CallWindowProc(DefWndProc, Handle, WM_SETFOCUS, 0, 0);
|
|
end;
|
|
|
|
function TcxCustomEditListBox.GetEdit: TcxCustomTextEdit;
|
|
begin
|
|
Result := TcxCustomTextEdit(TcxCustomPopupWindow(Owner).OwnerControl);
|
|
end;
|
|
|
|
{$IFNDEF DELPHI6}
|
|
function TcxCustomEditListBox.GetItemIndex: Integer;
|
|
begin
|
|
Result := inherited ItemIndex;
|
|
end;
|
|
{$ENDIF}
|
|
|
|
{ TcxCustomTextEditLookupData }
|
|
|
|
constructor TcxCustomTextEditLookupData.Create(AOwner: TPersistent);
|
|
begin
|
|
inherited Create(nil);
|
|
FOwner:= AOwner;
|
|
FCurrentKey := -1;
|
|
FItemIndex := -1;
|
|
end;
|
|
|
|
function TcxCustomTextEditLookupData.CanResizeVisualArea(var NewSize: TSize;
|
|
AMaxHeight: Integer = 0; AMaxWidth: Integer = 0): Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
procedure TcxCustomTextEditLookupData.CloseUp;
|
|
begin
|
|
if not Edit.EditModeSetting then
|
|
InternalSetItemIndex(FCurrentKey);
|
|
end;
|
|
|
|
procedure TcxCustomTextEditLookupData.Deinitialize;
|
|
begin
|
|
end;
|
|
|
|
procedure TcxCustomTextEditLookupData.DropDown;
|
|
begin
|
|
end;
|
|
|
|
procedure TcxCustomTextEditLookupData.DroppedDown(const AFindStr: string);
|
|
begin
|
|
end;
|
|
|
|
function TcxCustomTextEditLookupData.Find(const AText: string): Boolean;
|
|
begin
|
|
Result := IndexOf(AText) <> -1;
|
|
end;
|
|
|
|
function TcxCustomTextEditLookupData.GetOwner: TPersistent;
|
|
begin
|
|
Result := FOwner;
|
|
end;
|
|
|
|
procedure TcxCustomTextEditLookupData.DoCurrentKeyChanged;
|
|
begin
|
|
if Assigned(FOnCurrentKeyChanged) then
|
|
FOnCurrentKeyChanged(Self);
|
|
end;
|
|
|
|
procedure TcxCustomTextEditLookupData.DoSelectItem;
|
|
begin
|
|
if Assigned(FOnSelectItem) then
|
|
FOnSelectItem(Self);
|
|
end;
|
|
|
|
function TcxCustomTextEditLookupData.GetItem(Index: Integer): string;
|
|
begin
|
|
Result := ActiveProperties.FLookupItems[Index];
|
|
end;
|
|
|
|
function TcxCustomTextEditLookupData.GetItemCount: Integer;
|
|
begin
|
|
Result := ActiveProperties.FLookupItems.Count;
|
|
end;
|
|
|
|
function TcxCustomTextEditLookupData.GetDisplayText(const AKey: TcxEditValue): string;
|
|
begin
|
|
if (AKey < 0) or (AKey >= GetItemCount) then
|
|
Result := ''
|
|
else
|
|
Result := GetItem(AKey);
|
|
end;
|
|
|
|
function TcxCustomTextEditLookupData.GetListBoxClass: TcxCustomEditListBoxClass;
|
|
begin
|
|
Result := nil;
|
|
end;
|
|
|
|
procedure TcxCustomTextEditLookupData.HandleSelectItem(Sender: TObject);
|
|
begin
|
|
FItemIndex := FList.ItemIndex;
|
|
end;
|
|
|
|
function TcxCustomTextEditLookupData.InternalLocate(var AText, ATail: string;
|
|
ANext, ASynchronizeWithText: Boolean): Boolean;
|
|
|
|
procedure CheckCurrentKey;
|
|
var
|
|
ACorrectCurrentKey: Boolean;
|
|
begin
|
|
case ActiveProperties.EditingStyle of
|
|
esEditList:
|
|
ACorrectCurrentKey := ASynchronizeWithText or (AText = '');
|
|
esFixedList:
|
|
ACorrectCurrentKey := ASynchronizeWithText;
|
|
else
|
|
ACorrectCurrentKey := True;
|
|
end;
|
|
if ACorrectCurrentKey then
|
|
InternalSetCurrentKey(-1);
|
|
end;
|
|
|
|
var
|
|
AItem: string;
|
|
AIStart, AItemIndex, I, L: Integer;
|
|
S: string;
|
|
begin
|
|
Result := False;
|
|
if GetItemCount = 0 then
|
|
begin
|
|
CheckCurrentKey;
|
|
Exit;
|
|
end;
|
|
|
|
if ASynchronizeWithText and ActiveProperties.MRUMode then
|
|
begin
|
|
AItemIndex := IndexOf(AText);
|
|
if AItemIndex = -1 then
|
|
InternalSetCurrentKey(-1)
|
|
else
|
|
begin
|
|
Result := True;
|
|
ATail := '';
|
|
InternalSetCurrentKey(AItemIndex);
|
|
end;
|
|
Exit;
|
|
end;
|
|
|
|
if ANext then
|
|
AIStart := ItemIndex
|
|
else
|
|
AIStart := -1;
|
|
I := AIStart;
|
|
L := Length(AText);
|
|
repeat
|
|
Inc(I);
|
|
if (I = GetItemCount) or (I = AIStart) or (L = 0) then
|
|
Break;
|
|
|
|
AItem := GetItem(I);
|
|
S := Copy(AItem, 1, L);
|
|
|
|
if InternalCompareString(AText, S, False) then
|
|
begin
|
|
AText := S;
|
|
ATail := Copy(AItem, L + 1, Length(AItem) - L);
|
|
InternalSetCurrentKey(I);
|
|
Result := True;
|
|
Break;
|
|
end;
|
|
until Result;
|
|
|
|
if not Result then
|
|
CheckCurrentKey;
|
|
end;
|
|
|
|
function TcxCustomTextEditLookupData.GetVisualAreaPreferredSize(AMaxHeight: Integer;
|
|
AWidth: Integer = 0): TSize;
|
|
begin
|
|
Result := cxNullSize;
|
|
end;
|
|
|
|
procedure TcxCustomTextEditLookupData.Go(ADirection: TcxEditLookupDataGoDirection;
|
|
ACircular: Boolean);
|
|
var
|
|
ANewCurrentKey: Integer;
|
|
AItemIndex: Integer;
|
|
begin
|
|
if GetItemCount = 0 then
|
|
Exit;
|
|
ANewCurrentKey := 0;
|
|
if ItemIndex = -1 then
|
|
AItemIndex := CurrentKey
|
|
else
|
|
AItemIndex := ItemIndex;
|
|
case ADirection of
|
|
egdBegin:
|
|
ANewCurrentKey := 0;
|
|
egdEnd:
|
|
ANewCurrentKey := GetItemCount - 1;
|
|
egdPrev:
|
|
begin
|
|
ANewCurrentKey := AItemIndex - 1;
|
|
if (ANewCurrentKey < 0) then
|
|
if ACircular then
|
|
ANewCurrentKey := GetItemCount - 1
|
|
else
|
|
ANewCurrentKey := AItemIndex;
|
|
end;
|
|
egdNext:
|
|
begin
|
|
ANewCurrentKey := AItemIndex + 1;
|
|
if (ANewCurrentKey = GetItemCount) then
|
|
if ACircular then
|
|
ANewCurrentKey := 0
|
|
else
|
|
ANewCurrentKey := AItemIndex;
|
|
end;
|
|
egdPageUp:
|
|
if AItemIndex = -1 then
|
|
if ACircular then
|
|
ANewCurrentKey := GetItemCount - 1
|
|
else
|
|
ANewCurrentKey := AItemIndex
|
|
else
|
|
begin
|
|
ANewCurrentKey := AItemIndex - ActiveProperties.GetDropDownPageRowCount + 1;
|
|
if (ANewCurrentKey < 0) then
|
|
if ACircular then
|
|
if AItemIndex = 0 then
|
|
ANewCurrentKey := GetItemCount - 1
|
|
else
|
|
ANewCurrentKey := 0
|
|
else
|
|
ANewCurrentKey := 0;
|
|
end;
|
|
egdPageDown:
|
|
begin
|
|
if AItemIndex = -1 then
|
|
ANewCurrentKey := AItemIndex + ActiveProperties.GetDropDownPageRowCount
|
|
else
|
|
ANewCurrentKey := AItemIndex + ActiveProperties.GetDropDownPageRowCount - 1;
|
|
if (ANewCurrentKey >= GetItemCount) then
|
|
if ACircular then
|
|
if AItemIndex = GetItemCount - 1 then
|
|
ANewCurrentKey := 0
|
|
else
|
|
ANewCurrentKey := GetItemCount - 1
|
|
else
|
|
ANewCurrentKey := GetItemCount - 1;
|
|
end;
|
|
end;
|
|
if (FList = nil) or not FList.IsVisible or
|
|
ActiveProperties.ImmediateUpdateText and Edit.DoEditing then
|
|
CurrentKey := ANewCurrentKey
|
|
else
|
|
InternalSetItemIndex(ANewCurrentKey);
|
|
end;
|
|
|
|
procedure TcxCustomTextEditLookupData.Initialize(AVisualControlsParent: TWinControl);
|
|
begin
|
|
if (FList = nil) and (GetListBoxClass <> nil) then
|
|
FList := GetListBoxClass.Create(AVisualControlsParent);
|
|
with FList do
|
|
begin
|
|
Color := Edit.ActiveStyle.Color;
|
|
Font := Edit.ActiveStyle.GetVisibleFont;
|
|
Canvas.Font := Font;
|
|
Parent := AVisualControlsParent;
|
|
OnSelectItem := HandleSelectItem;
|
|
SetItemCount(GetItemCount);
|
|
ItemIndex := FItemIndex;
|
|
RecreateWindow;
|
|
end;
|
|
TextChanged;
|
|
end;
|
|
|
|
procedure TcxCustomTextEditLookupData.InternalSetCurrentKey(Value: Integer);
|
|
begin
|
|
if (Value >= -1) and (Value < GetItemCount) then
|
|
begin
|
|
FCurrentKey := Value;
|
|
InternalSetItemIndex(Value);
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomTextEditLookupData.IsEmpty: Boolean;
|
|
begin
|
|
Result := GetItemCount = 0;
|
|
end;
|
|
|
|
function TcxCustomTextEditLookupData.IsMouseOverList(const P: TPoint): Boolean;
|
|
begin
|
|
Result := PtInRect(FList.BoundsRect, FList.ScreenToClient(P));
|
|
end;
|
|
|
|
procedure TcxCustomTextEditLookupData.ListChanged;
|
|
begin
|
|
if FList <> nil then
|
|
FList.SetItemCount(GetItemCount);
|
|
end;
|
|
|
|
procedure TcxCustomTextEditLookupData.SetListItemIndex(Value: Integer);
|
|
begin
|
|
FList.ItemIndex := Value;
|
|
end;
|
|
|
|
function TcxCustomTextEditLookupData.Locate(var AText, ATail: string;
|
|
ANext: Boolean): Boolean;
|
|
begin
|
|
Result := InternalLocate(AText, ATail, ANext, False);
|
|
end;
|
|
|
|
procedure TcxCustomTextEditLookupData.PositionVisualArea(const AClientRect: TRect);
|
|
begin
|
|
with AClientRect do
|
|
begin
|
|
FList.SetBounds(Left, Top, Right - Left, Bottom - Top);
|
|
if FList.HandleAllocated then
|
|
FList.SetScrollWidth(FList.ScrollWidth);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTextEditLookupData.PropertiesChanged;
|
|
begin
|
|
ListChanged;
|
|
end;
|
|
|
|
procedure TcxCustomTextEditLookupData.SelectItem;
|
|
var
|
|
APrevCurrentKey: TcxEditValue;
|
|
begin
|
|
if (FItemIndex = -1) or (CurrentKey <> FItemIndex) and not Edit.DoEditing then
|
|
Exit;
|
|
APrevCurrentKey := CurrentKey;
|
|
CurrentKey := FItemIndex;
|
|
if VarEqualsExact(APrevCurrentKey, CurrentKey) then
|
|
DoSelectItem;
|
|
end;
|
|
|
|
function TcxCustomTextEditLookupData.GetActiveControl: TControl;
|
|
begin
|
|
Result := FList;
|
|
end;
|
|
|
|
function TcxCustomTextEditLookupData.GetCurrentKey: TcxEditValue;
|
|
begin
|
|
Result := FCurrentKey;
|
|
end;
|
|
|
|
function TcxCustomTextEditLookupData.GetOnCurrentKeyChanged: TNotifyEvent;
|
|
begin
|
|
Result := FOnCurrentKeyChanged;
|
|
end;
|
|
|
|
function TcxCustomTextEditLookupData.GetOnSelectItem: TNotifyEvent;
|
|
begin
|
|
Result := FOnSelectItem;
|
|
end;
|
|
|
|
function TcxCustomTextEditLookupData.GetEdit: TcxCustomTextEdit;
|
|
begin
|
|
Result := TcxCustomTextEdit(FOwner);
|
|
end;
|
|
|
|
function TcxCustomTextEditLookupData.GetItems: TStrings;
|
|
begin
|
|
Result := ActiveProperties.FLookupItems;
|
|
end;
|
|
|
|
function TcxCustomTextEditLookupData.GetActiveProperties: TcxCustomTextEditProperties;
|
|
begin
|
|
Result := Edit.ActiveProperties;
|
|
end;
|
|
|
|
function TcxCustomTextEditLookupData.IndexOf(const AText: string): Integer;
|
|
var
|
|
ACount, I: Integer;
|
|
begin
|
|
Result := -1;
|
|
ACount := GetItemCount;
|
|
for I := 0 to ACount - 1 do
|
|
if InternalCompareString(AText, GetItem(I), False) then
|
|
begin
|
|
Result := I;
|
|
Break;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTextEditLookupData.InternalSetItemIndex(Value: Integer);
|
|
begin
|
|
if (Value < -1) or (Value >= GetItemCount) or (Value = FItemIndex) and (Value <> -1) then
|
|
Exit;
|
|
if (FList <> nil) and (GetItemCount > 0) then
|
|
begin
|
|
if Value = -1 then
|
|
SetListItemIndex(0);
|
|
SetListItemIndex(Value);
|
|
end;
|
|
FItemIndex := Value;
|
|
end;
|
|
|
|
procedure TcxCustomTextEditLookupData.SetCurrentKey(const AKey: TcxEditValue);
|
|
var
|
|
APrevCurrentKey: TcxEditValue;
|
|
begin
|
|
APrevCurrentKey := FCurrentKey;
|
|
InternalSetCurrentKey(AKey);
|
|
if Edit <> nil then
|
|
Edit.LockLookupDataTextChanged;
|
|
try
|
|
if not VarEqualsExact(APrevCurrentKey, FCurrentKey) or ((AKey >= 0) and (AKey < GetItemCount) and not InternalCompareString(Edit.Text, GetItem(AKey), True)) then
|
|
DoSelectItem;
|
|
finally
|
|
if Edit <> nil then
|
|
Edit.UnlockLookupDataTextChanged;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTextEditLookupData.SetItemIndex(Value: Integer);
|
|
begin
|
|
if (FList = nil) or not FList.IsVisible or ActiveProperties.ImmediateUpdateText then
|
|
CurrentKey := Value
|
|
else
|
|
InternalSetItemIndex(Value);
|
|
end;
|
|
|
|
procedure TcxCustomTextEditLookupData.SetItems(Value: TStrings);
|
|
begin
|
|
ActiveProperties.FLookupItems.Assign(Value);
|
|
end;
|
|
|
|
procedure TcxCustomTextEditLookupData.SetOnCurrentKeyChanged(Value: TNotifyEvent);
|
|
begin
|
|
FOnCurrentKeyChanged := Value;
|
|
end;
|
|
|
|
procedure TcxCustomTextEditLookupData.SetOnSelectItem(Value: TNotifyEvent);
|
|
begin
|
|
FOnSelectItem := Value;
|
|
end;
|
|
|
|
procedure TcxCustomTextEditLookupData.TextChanged;
|
|
var
|
|
AText, ATail: string;
|
|
begin
|
|
if Edit.EditModeSetting then
|
|
Exit;
|
|
AText := Edit.Text;
|
|
if (ItemIndex >= GetItemCount) or
|
|
not InternalCompareString(GetDisplayText(ItemIndex), AText, False) then
|
|
InternalLocate(AText, ATail, False, True);
|
|
end;
|
|
|
|
{ TcxCustomTextEditViewData }
|
|
|
|
procedure TcxCustomTextEditViewData.Calculate(ACanvas: TcxCanvas; const ABounds: TRect;
|
|
const P: TPoint; Button: TcxMouseButton; Shift: TShiftState; AViewInfo: TcxCustomEditViewInfo;
|
|
AIsMouseEvent: Boolean);
|
|
begin
|
|
inherited Calculate(ACanvas, ABounds, P, Button, Shift, AViewInfo, AIsMouseEvent);
|
|
with AViewInfo as TcxCustomTextEditViewInfo do
|
|
begin
|
|
DrawSelectionBar := False;
|
|
EditingStyle := Properties.EditingStyle;
|
|
IsEditClass := GetIsEditClass;
|
|
if Edit <> nil then
|
|
TcxCustomTextEditViewInfo(AViewInfo).HasPopupWindow := Edit.HasPopupWindow
|
|
else
|
|
TcxCustomTextEditViewInfo(AViewInfo).HasPopupWindow := False;
|
|
CalculateTextEditViewInfo(ACanvas, Self, TcxCustomTextEditViewInfo(AViewInfo), AIsMouseEvent);
|
|
MaxLineCount := Self.GetMaxLineCount;
|
|
TextOutData.Initialized := False;
|
|
end;
|
|
PrepareDrawTextFlags(ACanvas, AViewInfo);
|
|
end;
|
|
|
|
procedure TcxCustomTextEditViewData.DisplayValueToDrawValue(const ADisplayValue: TcxEditValue;
|
|
AViewInfo: TcxCustomEditViewInfo);
|
|
begin
|
|
with TcxCustomTextEditViewInfo(AViewInfo) do
|
|
begin
|
|
Text := ADisplayValue;
|
|
Properties.DisplayValueToDisplayText(Text);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTextEditViewData.EditValueToDrawValue(ACanvas: TcxCanvas;
|
|
const AEditValue: TcxEditValue; AViewInfo: TcxCustomEditViewInfo);
|
|
begin
|
|
if PreviewMode then
|
|
TcxCustomTextEditViewInfo(AViewInfo).Text := ''
|
|
else
|
|
TcxCustomTextEditViewInfo(AViewInfo).Text :=
|
|
string(EditValueToDisplayText(AEditValue));
|
|
PrepareSelection(AViewInfo);
|
|
end;
|
|
|
|
function TcxCustomTextEditViewData.GetClientExtent(ACanvas: TcxCanvas;
|
|
AViewInfo: TcxCustomEditViewInfo): TRect;
|
|
begin
|
|
Result := inherited GetClientExtent(ACanvas, AViewInfo);
|
|
if not IsInplace and IsComboBoxStyle and
|
|
AreVisualStylesMustBeUsed(Style.LookAndFeel.NativeStyle, totEdit) then
|
|
Inc(Result.Right);
|
|
end;
|
|
|
|
function TcxCustomTextEditViewData.GetDrawTextFlags: DWORD;
|
|
const
|
|
AHorzAlignmentFlags: array [TcxEditHorzAlignment] of DWORD = (
|
|
CXTO_LEFT, CXTO_RIGHT, CXTO_CENTER_HORIZONTALLY
|
|
);
|
|
AVertAlignmentFlags: array [TcxEditVertAlignment] of DWORD = (
|
|
CXTO_TOP, CXTO_BOTTOM, CXTO_CENTER_VERTICALLY
|
|
);
|
|
begin
|
|
Result := AHorzAlignmentFlags[HorzAlignment];
|
|
Result := Result or AVertAlignmentFlags[VertAlignment];
|
|
Result := Result or CXTO_SINGLELINE;
|
|
Result := Result or CXTO_PREVENT_LEFT_EXCEED or CXTO_PREVENT_TOP_EXCEED;
|
|
end;
|
|
|
|
function TcxCustomTextEditViewData.GetDrawTextOffset: TRect;
|
|
begin
|
|
Result := GetTextEditDrawTextOffset(Self);
|
|
end;
|
|
|
|
procedure TcxCustomTextEditViewData.PrepareSelection(AViewInfo: TcxCustomEditViewInfo);
|
|
var
|
|
ACustomTextEditViewInfo: TcxCustomTextEditViewInfo;
|
|
begin
|
|
ACustomTextEditViewInfo := TcxCustomTextEditViewInfo(AViewInfo);
|
|
ACustomTextEditViewInfo.SelStart := SelStart;
|
|
ACustomTextEditViewInfo.SelLength := SelLength;
|
|
if SelLength = 0 then
|
|
Exit;
|
|
if SelBackgroundColor = clDefault then
|
|
begin
|
|
if SelTextColor = clDefault then
|
|
begin
|
|
if Style.Color = clHighlight then
|
|
begin
|
|
ACustomTextEditViewInfo.SelBackgroundColor := clBlack;
|
|
ACustomTextEditViewInfo.SelTextColor := clWhite;
|
|
end
|
|
else
|
|
begin
|
|
ACustomTextEditViewInfo.SelBackgroundColor := clHighlight;
|
|
ACustomTextEditViewInfo.SelTextColor := clHighlightText;
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
ACustomTextEditViewInfo.SelTextColor := SelTextColor;
|
|
ACustomTextEditViewInfo.SelBackgroundColor := InvertColor(SelTextColor);
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
ACustomTextEditViewInfo.SelBackgroundColor := SelBackgroundColor;
|
|
if SelTextColor = clDefault then
|
|
ACustomTextEditViewInfo.SelTextColor := InvertColor(SelBackgroundColor)
|
|
else
|
|
ACustomTextEditViewInfo.SelTextColor := SelTextColor;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTextEditViewData.CalculateButtonNativeInfo(AButtonViewInfo: TcxEditButtonViewInfo);
|
|
begin
|
|
inherited CalculateButtonNativeInfo(AButtonViewInfo);
|
|
if NativeStyle and IsCompositionEnabled and not IsInplace and
|
|
(Properties.EditingStyle = esFixedList) and
|
|
AButtonViewInfo.Data.ComboBoxStyle and
|
|
(AButtonViewInfo.Data.NativeState <> CBXS_DISABLED) then
|
|
AButtonViewInfo.Data.NativeState := CBXS_NORMAL;
|
|
end;
|
|
|
|
function TcxCustomTextEditViewData.GetIsEditClass: Boolean;
|
|
begin
|
|
Result := (Edit <> nil) and Edit.IsEditClass;
|
|
end;
|
|
|
|
function TcxCustomTextEditViewData.GetMaxLineCount: Integer;
|
|
begin
|
|
Result := MaxLineCount;
|
|
end;
|
|
|
|
procedure TcxCustomTextEditViewData.InitCacheData;
|
|
begin
|
|
inherited InitCacheData;
|
|
FIsValueEditorWithValueFormatting := Properties.IsValueEditorWithValueFormatting;
|
|
end;
|
|
|
|
function TcxCustomTextEditViewData.InternalEditValueToDisplayText(
|
|
AEditValue: TcxEditValue): string;
|
|
begin
|
|
Result := '';
|
|
try
|
|
if FIsValueEditorWithValueFormatting then
|
|
Result := VarToStr(AEditValue)
|
|
else
|
|
Result := Properties.GetDefaultDisplayValue(AEditValue, InternalFocused);
|
|
finally
|
|
Properties.DisplayValueToDisplayText(string(Result));
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomTextEditViewData.InternalGetEditContentSize(ACanvas: TcxCanvas;
|
|
const AEditValue: TcxEditValue; const AEditSizeProperties: TcxEditSizeProperties): TSize;
|
|
var
|
|
AContentSize: TSize;
|
|
begin
|
|
AContentSize := inherited InternalGetEditContentSize(ACanvas, AEditValue,
|
|
AEditSizeProperties);
|
|
Result := GetTextEditContentSize(ACanvas, Self,
|
|
EditValueToDisplayText(AEditValue), GetDrawTextFlags, AEditSizeProperties);
|
|
CheckSize(Result, AContentSize);
|
|
end;
|
|
|
|
function TcxCustomTextEditViewData.IsComboBoxStyle: Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
procedure TcxCustomTextEditViewData.PrepareDrawTextFlags(ACanvas: TcxCanvas;
|
|
AViewInfo: TcxCustomEditViewInfo);
|
|
begin
|
|
with TcxCustomTextEditViewInfo(AViewInfo) do
|
|
begin
|
|
if not Properties.IsMultiLine and (esoAutoHeight in Properties.GetSupportedOperations) and
|
|
(epoAutoHeight in Self.PaintOptions) then
|
|
PrepareTextEditDrawTextFlags(ACanvas, Self, TcxCustomTextEditViewInfo(AViewInfo))
|
|
else
|
|
DrawTextFlags := GetDrawTextFlags;
|
|
if epoShowEndEllipsis in PaintOptions then
|
|
DrawTextFlags := DrawTextFlags or CXTO_END_ELLIPSIS;
|
|
ComboBoxStyle := IsComboBoxStyle;
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomTextEditViewData.GetProperties: TcxCustomTextEditProperties;
|
|
begin
|
|
Result := TcxCustomTextEditProperties(FProperties);
|
|
end;
|
|
|
|
function TcxCustomTextEditViewData.InvertColor(AColor: TColor): TColor;
|
|
begin
|
|
Result := ColorToRGB(AColor) xor $FFFFFF;
|
|
end;
|
|
|
|
{ TcxCustomTextEditViewInfo }
|
|
|
|
destructor TcxCustomTextEditViewInfo.Destroy;
|
|
begin
|
|
cxResetTextRows(TextOutData.TextRows);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TcxCustomTextEditViewInfo.NeedShowHint(ACanvas: TcxCanvas;
|
|
const P: TPoint; const AVisibleBounds: TRect; out AText: TCaption;
|
|
out AIsMultiLine: Boolean; out ATextRect: TRect): Boolean;
|
|
|
|
function GetRealVisibleBounds: TRect;
|
|
begin
|
|
Result := AVisibleBounds;
|
|
if EqualRect(Result, cxEmptyRect) then
|
|
Result := TextRect
|
|
else
|
|
begin
|
|
OffsetRect(Result, -Left, -Top);
|
|
IntersectRect(Result, TextRect, Result);
|
|
end;
|
|
end;
|
|
|
|
function IsMultiLine(ATextFlags: DWORD): Boolean;
|
|
begin
|
|
Result := (ATextFlags and CXTO_SINGLELINE = 0) and (ATextFlags and CXTO_WORDBREAK <> 0);
|
|
end;
|
|
|
|
function GetCalcTextFlags: Integer;
|
|
begin
|
|
Result := DrawTextFlags and not (CXTO_CENTER_VERTICALLY or CXTO_BOTTOM or CXTO_SINGLELINE) or
|
|
CXTO_CALCRECT;
|
|
end;
|
|
|
|
function IsTextNotFullyVisible(const ARealVisibleBounds: TRect): Boolean;
|
|
var
|
|
R: TRect;
|
|
begin
|
|
ACanvas.Font := Font;
|
|
R := ARealVisibleBounds;
|
|
cxTextOut(ACanvas.Canvas, Text, R, GetCalcTextFlags);
|
|
Result := (R.Bottom > ARealVisibleBounds.Bottom) or (R.Right > ARealVisibleBounds.Right);
|
|
end;
|
|
|
|
var
|
|
ARealVisibleBounds: TRect;
|
|
begin
|
|
ARealVisibleBounds := GetRealVisibleBounds;
|
|
Result := PtInRect(ARealVisibleBounds, Point(P.X - Left, P.Y - Top)) and
|
|
IsTextNotFullyVisible(ARealVisibleBounds);
|
|
if Result then
|
|
begin
|
|
AIsMultiLine := IsMultiLine(DrawTextFlags);
|
|
AText := Text;
|
|
ATextRect := TextRect;
|
|
OffsetRect(ATextRect, Left, Top);
|
|
end
|
|
else
|
|
Result := inherited NeedShowHint(ACanvas, P, AVisibleBounds, AText, AIsMultiLine, ATextRect);
|
|
end;
|
|
|
|
procedure TcxCustomTextEditViewInfo.Offset(DX, DY: Integer);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
inherited Offset(DX, DY);
|
|
OffsetRect(TextRect, DX, DY);
|
|
with TextOutData do
|
|
if Initialized then
|
|
begin
|
|
OffsetRect(TextRect, DX, DY);
|
|
for I := 0 to cxGetTextRowCount(TextRows) - 1 do
|
|
with cxGetTextRow(TextRows, I)^ do
|
|
begin
|
|
TextOriginX := TextOriginX + DX;
|
|
TextOriginY := TextOriginY + DY;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTextEditViewInfo.DrawText(ACanvas: TcxCanvas);
|
|
begin
|
|
DrawEditText(ACanvas, Self);
|
|
end;
|
|
|
|
{$IFDEF DELPHI10}
|
|
function TcxCustomTextEditViewInfo.GetTextBaseLine: Integer;
|
|
var
|
|
ACanvas: TcxScreenCanvas;
|
|
ATextMetric: TTextMetric;
|
|
begin
|
|
ACanvas := TcxScreenCanvas.Create;
|
|
try
|
|
ACanvas.Font := Font;
|
|
GetTextMetrics(ACanvas.Handle, ATextMetric);
|
|
case EditProperties.Alignment.Vert of
|
|
taTopJustify:
|
|
Result := TextRect.Top + ATextMetric.tmAscent + 1;
|
|
taBottomJustify:
|
|
Result := TextRect.Bottom - ATextMetric.tmDescent + 1;
|
|
else
|
|
Result := TextRect.Top + (TextRect.Bottom - TextRect.Top - ATextMetric.tmHeight) div 2 + ATextMetric.tmAscent + 1;
|
|
end;
|
|
finally
|
|
ACanvas.Free;
|
|
end;
|
|
end;
|
|
{$ENDIF}
|
|
|
|
procedure TcxCustomTextEditViewInfo.InternalPaint(ACanvas: TcxCanvas);
|
|
begin
|
|
DrawTextEdit(ACanvas, Self);
|
|
end;
|
|
|
|
{ TcxCustomTextEditProperties }
|
|
|
|
constructor TcxCustomTextEditProperties.Create(AOwner: TPersistent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FCharCase := ecNormal;
|
|
FEchoMode := eemNormal;
|
|
FFixedListSelection := True;
|
|
FHideSelection := True;
|
|
FImeMode := imDontCare;
|
|
FIncrementalSearch := True;
|
|
FLookupItems := TStringList.Create;
|
|
FLookupItems.Duplicates := dupAccept;
|
|
FLookupItems.OnChange := LookupItemsChanged;
|
|
cxFormatController.AddListener(Self);
|
|
end;
|
|
|
|
destructor TcxCustomTextEditProperties.Destroy;
|
|
begin
|
|
cxFormatController.RemoveListener(Self);
|
|
FreeAndNil(FLookupItems);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TcxCustomTextEditProperties.Assign(Source: TPersistent);
|
|
begin
|
|
if Source is TcxCustomTextEditProperties then
|
|
begin
|
|
BeginUpdate;
|
|
try
|
|
inherited Assign(Source);
|
|
with Source as TcxCustomTextEditProperties do
|
|
begin
|
|
Self.CharCase := CharCase;
|
|
Self.EchoMode := EchoMode;
|
|
Self.FixedListSelection := FixedListSelection;
|
|
Self.HideCursor := HideCursor;
|
|
Self.HideSelection := HideSelection;
|
|
Self.ImmediateUpdateText := ImmediateUpdateText;
|
|
Self.IncrementalSearch := IncrementalSearch;
|
|
Self.MRUMode := MRUMode;
|
|
Self.ValidChars := ValidChars;
|
|
|
|
Self.LookupItemsSorted := False;
|
|
Self.LookupItems.Assign(LookupItems);
|
|
Self.LookupItemsSorted := LookupItemsSorted;
|
|
|
|
Self.AssignedValues.DisplayFormat := False;
|
|
if AssignedValues.DisplayFormat then
|
|
Self.DisplayFormat := DisplayFormat;
|
|
|
|
Self.AssignedValues.EditFormat := False;
|
|
if AssignedValues.EditFormat then
|
|
Self.EditFormat := EditFormat;
|
|
|
|
Self.AssignedValues.MaxLength := False;
|
|
if AssignedValues.MaxLength then
|
|
Self.MaxLength := MaxLength;
|
|
|
|
Self.OEMConvert := OEMConvert;
|
|
Self.ImeMode := ImeMode;
|
|
Self.ImeName := ImeName;
|
|
Self.PasswordChar := PasswordChar;
|
|
Self.UseDisplayFormatWhenEditing := UseDisplayFormatWhenEditing;
|
|
Self.OnNewLookupDisplayText := OnNewLookupDisplayText;
|
|
end;
|
|
finally
|
|
EndUpdate;
|
|
end
|
|
end
|
|
else
|
|
inherited Assign(Source);
|
|
end;
|
|
|
|
function TcxCustomTextEditProperties.CanCompareEditValue: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
function TcxCustomTextEditProperties.CompareDisplayValues(
|
|
const AEditValue1, AEditValue2: TcxEditValue): Boolean;
|
|
var
|
|
AText1, AText2: string;
|
|
begin
|
|
AText1 := GetDisplayText(AEditValue1, True);
|
|
AText2 := GetDisplayText(AEditValue2, True);
|
|
Result := InternalCompareString(AText1, AText2, True);
|
|
end;
|
|
|
|
class function TcxCustomTextEditProperties.GetContainerClass: TcxContainerClass;
|
|
begin
|
|
Result := TcxTextEdit;
|
|
end;
|
|
|
|
function TcxCustomTextEditProperties.GetDisplayText(const AEditValue: TcxEditValue;
|
|
AFullText: Boolean = False; AIsInplace: Boolean = True): WideString;
|
|
var
|
|
AText: string;
|
|
begin
|
|
AText := '';
|
|
try
|
|
if IsValueEditorWithValueFormatting then
|
|
AText := VarToStr(AEditValue)
|
|
else
|
|
AText := GetDefaultDisplayValue(AEditValue,
|
|
not AIsInplace and not IsEditValueConversionDependOnFocused);
|
|
finally
|
|
DisplayValueToDisplayText(AText);
|
|
Result := AText;
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomTextEditProperties.GetSupportedOperations: TcxEditSupportedOperations;
|
|
begin
|
|
Result := inherited GetSupportedOperations + [esoAutoHeight, esoEditing,
|
|
esoFiltering, esoHorzAlignment, esoIncSearch, esoSorting];
|
|
end;
|
|
|
|
class function TcxCustomTextEditProperties.GetViewInfoClass: TcxContainerViewInfoClass;
|
|
begin
|
|
Result := TcxCustomTextEditViewInfo;
|
|
end;
|
|
|
|
function TcxCustomTextEditProperties.IsEditValueValid(var EditValue: TcxEditValue; AEditFocused: Boolean): Boolean;
|
|
begin
|
|
Result := VarIsNull(EditValue) or not VarIsStr(EditValue) or
|
|
IsDisplayValueValid(EditValue, AEditFocused);
|
|
end;
|
|
|
|
procedure TcxCustomTextEditProperties.PrepareDisplayValue(const AEditValue: TcxEditValue;
|
|
var DisplayValue: TcxEditValue; AEditFocused: Boolean);
|
|
|
|
procedure InternalPrepareDisplayValue(AValue: Variant);
|
|
|
|
var
|
|
AEditFormat: string;
|
|
AIsCurrency, AIsOnGetTextAssigned: Boolean;
|
|
S: string;
|
|
{$IFDEF DELPHI6}
|
|
APrecision: Integer;
|
|
V: TBcd;
|
|
{$ENDIF}
|
|
begin
|
|
if AEditFocused then
|
|
begin
|
|
AEditFormat := InternalGetEditFormat(AIsCurrency, AIsOnGetTextAssigned);
|
|
|
|
{$IFDEF DELPHI6}
|
|
if IDefaultValuesProvider = nil then
|
|
APrecision := cxEditDefaultPrecision
|
|
else
|
|
APrecision := IDefaultValuesProvider.DefaultPrecision;
|
|
{$ENDIF}
|
|
|
|
if AIsCurrency then
|
|
{$IFDEF DELPHI6}
|
|
begin
|
|
DisplayValue := VarToStr(AValue);
|
|
if TryStrToBcd(DisplayValue, V) then
|
|
DisplayValue := BcdToStrF(V, ffFixed, APrecision, CurrencyDecimals);
|
|
end
|
|
{$ELSE}
|
|
DisplayValue := FloatToStrF(AValue, ffFixed, cxEditDefaultPrecision, CurrencyDecimals)
|
|
{$ENDIF}
|
|
else
|
|
if AEditFormat = '' then
|
|
begin
|
|
{$IFDEF DELPHI6}
|
|
S := VarToStr(AValue);
|
|
if TryStrToBcd(S, V) then
|
|
S := BcdToStrF(V, ffGeneral, APrecision, 0);
|
|
{$ELSE}
|
|
S := FloatToStrF(AValue, ffGeneral, cxEditDefaultPrecision, 0);
|
|
{$ENDIF}
|
|
if HasDigitGrouping(False) then
|
|
InsertThousandSeparator(S);
|
|
DisplayValue := S;
|
|
end
|
|
else
|
|
DisplayValue := FormatFloat(AEditFormat, AValue);
|
|
end
|
|
else
|
|
if DisplayFormat <> '' then
|
|
DisplayValue := FormatFloat(DisplayFormat, AValue)
|
|
else
|
|
DisplayValue := VarToStr(AValue);
|
|
end;
|
|
|
|
begin
|
|
if IsEditValueNumeric then
|
|
begin
|
|
if VarIsSoftNull(AEditValue) then
|
|
DisplayValue := ''
|
|
else
|
|
if not VarIsNumericEx(AEditValue) and not VarIsStr(AEditValue) then
|
|
raise EConvertError.CreateFmt(cxGetResourceString(@cxSEditNumericValueConvertError), [])
|
|
else
|
|
InternalPrepareDisplayValue(AEditValue);
|
|
end
|
|
else
|
|
if VarIsArray(AEditValue) then
|
|
DisplayValue := ''
|
|
else
|
|
DisplayValue := VarToStr(AEditValue);
|
|
end;
|
|
|
|
procedure TcxCustomTextEditProperties.ValidateDisplayValue(var DisplayValue: TcxEditValue;
|
|
var ErrorText: TCaption; var Error: Boolean; AEdit: TcxCustomEdit);
|
|
begin
|
|
if IsEditValueNumeric and IsValueBoundsDefined then
|
|
CheckEditorValueBounds(DisplayValue, ErrorText, Error, AEdit);
|
|
inherited ValidateDisplayValue(DisplayValue, ErrorText, Error, AEdit);
|
|
end;
|
|
|
|
procedure TcxCustomTextEditProperties.DisplayValueToDisplayText(
|
|
var ADisplayValue: string);
|
|
|
|
function GetPasswordChar: TCaptionChar;
|
|
begin
|
|
if PasswordChar = #0 then
|
|
Result := '*'
|
|
else
|
|
Result := PasswordChar;
|
|
end;
|
|
|
|
begin
|
|
if EchoMode <> eemNormal then
|
|
ADisplayValue := StringOfChar(GetPasswordChar, Length(ADisplayValue))
|
|
else
|
|
if CharCase <> ecNormal then
|
|
CheckCharsRegister(ADisplayValue, CharCase);
|
|
end;
|
|
|
|
function TcxCustomTextEditProperties.IsDisplayValueValid(var DisplayValue: TcxEditValue; AEditFocused: Boolean): Boolean;
|
|
var
|
|
AText: string;
|
|
begin
|
|
AText := VarToStr(DisplayValue);
|
|
Result := not((AText <> '') and (EditingStyle in [esEditList, esFixedList]) and
|
|
UseLookupData and not FindLookupText(AText));
|
|
if Result then
|
|
begin
|
|
CheckCharsRegister(AText, CharCase);
|
|
DisplayValue := AText;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTextEditProperties.SetMinMaxValues(AMinValue, AMaxValue: Double);
|
|
begin
|
|
FillMinMaxValues(AMinValue, AMaxValue);
|
|
end;
|
|
|
|
procedure TcxCustomTextEditProperties.AlignmentChangedHandler(Sender: TObject);
|
|
begin
|
|
BeginUpdate;
|
|
try
|
|
inherited AlignmentChangedHandler(Sender);
|
|
finally
|
|
EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTextEditProperties.BaseSetAlignment(Value: TcxEditAlignment);
|
|
begin
|
|
BeginUpdate;
|
|
try
|
|
inherited BaseSetAlignment(Value);
|
|
finally
|
|
EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomTextEditProperties.CanValidate: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
// obsolete
|
|
procedure TcxCustomTextEditProperties.DefineProperties(Filer: TFiler);
|
|
begin
|
|
inherited DefineProperties(Filer);
|
|
Filer.DefineProperty('IsDisplayFormatAssigned', ReadIsDisplayFormatAssigned,
|
|
nil, False);
|
|
end;
|
|
|
|
class function TcxCustomTextEditProperties.GetAssignedValuesClass: TcxCustomEditPropertiesValuesClass;
|
|
begin
|
|
Result := TcxTextEditPropertiesValues;
|
|
end;
|
|
|
|
function TcxCustomTextEditProperties.GetDisplayFormatOptions: TcxEditDisplayFormatOptions;
|
|
begin
|
|
Result := [dfoSupports];
|
|
end;
|
|
|
|
function TcxCustomTextEditProperties.GetValidateErrorText(AErrorKind: TcxEditErrorKind): string;
|
|
begin
|
|
if AErrorKind = ekValueOutOfBounds then
|
|
Result := cxGetResourceString(@cxSEditValueOutOfBounds)
|
|
else
|
|
Result := inherited GetValidateErrorText(AErrorKind);
|
|
end;
|
|
|
|
class function TcxCustomTextEditProperties.GetViewDataClass: TcxCustomEditViewDataClass;
|
|
begin
|
|
Result := TcxCustomTextEditViewData;
|
|
end;
|
|
|
|
function TcxCustomTextEditProperties.GetEditingStyle: TcxEditEditingStyle;
|
|
begin
|
|
if FHideCursor then
|
|
Result := esNoEdit
|
|
else
|
|
Result := esEdit;
|
|
end;
|
|
|
|
class function TcxCustomTextEditProperties.GetLookupDataClass: TcxInterfacedPersistentClass;
|
|
begin
|
|
Result := TcxCustomTextEditLookupData;
|
|
end;
|
|
|
|
function TcxCustomTextEditProperties.HasDigitGrouping(
|
|
AIsDisplayValueSynchronizing: Boolean): Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
function TcxCustomTextEditProperties.GetEditValueSource(AEditFocused: Boolean): TcxDataEditValueSource;
|
|
begin
|
|
Result := evsText;
|
|
end;
|
|
|
|
function TcxCustomTextEditProperties.HasDisplayValue: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
procedure TcxCustomTextEditProperties.FormatChanged;
|
|
begin
|
|
FFormatChanging := True;
|
|
try
|
|
Changed;
|
|
finally
|
|
FFormatChanging := False;
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomTextEditProperties.IsResetEditClass: Boolean;
|
|
begin
|
|
Result := EditingStyle <> esNoEdit;
|
|
end;
|
|
|
|
function TcxCustomTextEditProperties.CanIncrementalSearch: Boolean;
|
|
begin
|
|
Result := (EditingStyle = esEdit) and IncrementalSearch or
|
|
(EditingStyle in [esEditList, esFixedList])
|
|
end;
|
|
|
|
procedure TcxCustomTextEditProperties.CheckEditorValueBounds(var DisplayValue: TcxEditValue;
|
|
var ErrorText: TCaption; var Error: Boolean; AEdit: TcxCustomEdit);
|
|
var
|
|
AEditValue: TcxEditValue;
|
|
begin
|
|
AEdit.PrepareEditValue(DisplayValue, AEditValue, AEdit.InternalFocused);
|
|
if (VarIsNumericEx(AEditValue) or VarIsDate(AEditValue)) and
|
|
(IsValueBoundDefined(evbMin) and (AEditValue < MinValue) or
|
|
IsValueBoundDefined(evbMax) and (AEditValue > MaxValue)) then
|
|
begin
|
|
Error := True;
|
|
ErrorText := GetValidateErrorText(ekValueOutOfBounds);
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomTextEditProperties.DefaultFocusedDisplayValue: TcxEditValue;
|
|
begin
|
|
Result := '';
|
|
end;
|
|
|
|
function TcxCustomTextEditProperties.FindLookupText(const AText: string): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := False;
|
|
for I := 0 to FLookupItems.Count - 1 do
|
|
if InternalCompareString(AText, FLookupItems[I], False) then
|
|
begin
|
|
Result := True;
|
|
Break;
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomTextEditProperties.GetDefaultDisplayFormat: string;
|
|
begin
|
|
Result := '';
|
|
end;
|
|
|
|
function TcxCustomTextEditProperties.GetDefaultDisplayValue(const AEditValue: TcxEditValue;
|
|
AEditFocused: Boolean): TcxEditValue;
|
|
var
|
|
AValue: TcxEditValue;
|
|
begin
|
|
AValue := AEditValue;
|
|
if IsEditValueValid(AValue, AEditFocused) then
|
|
PrepareDisplayValue(AValue, Result, AEditFocused)
|
|
else
|
|
if VarIsDate(AEditValue) then
|
|
Result := DateTimeToStr(AEditValue)
|
|
else
|
|
Result := VarToStr(AEditValue)
|
|
end;
|
|
|
|
function TcxCustomTextEditProperties.GetDefaultMaxLength: Integer;
|
|
begin
|
|
if IDefaultValuesProvider = nil then
|
|
Result := 0
|
|
else
|
|
Result := IDefaultValuesProvider.DefaultMaxLength;
|
|
end;
|
|
|
|
function TcxCustomTextEditProperties.GetDropDownPageRowCount: Integer;
|
|
begin
|
|
Result := cxEditDefaultDropDownPageRowCount;
|
|
end;
|
|
|
|
function TcxCustomTextEditProperties.InternalGetEditFormat(
|
|
out AIsCurrency, AIsOnGetTextAssigned: Boolean;
|
|
AEdit: TcxCustomTextEdit = nil): string;
|
|
begin
|
|
AIsCurrency := False;
|
|
AIsOnGetTextAssigned := False;
|
|
Result := '';
|
|
if AssignedValues.EditFormat then
|
|
Result := FEditFormat
|
|
else
|
|
begin
|
|
if not ((AEdit <> nil) and AEdit.IsInplace) and (IDefaultValuesProvider <> nil) and
|
|
IDefaultValuesProvider.IsOnGetTextAssigned then
|
|
begin
|
|
AIsOnGetTextAssigned := True;
|
|
Exit;
|
|
end;
|
|
if (IDefaultValuesProvider <> nil) and
|
|
(IDefaultValuesProvider.DefaultEditFormat <> '') then
|
|
Result := IDefaultValuesProvider.DefaultEditFormat
|
|
else
|
|
begin
|
|
if AssignedValues.DisplayFormat then
|
|
Result := DisplayFormat
|
|
else
|
|
if (IDefaultValuesProvider <> nil) and (IDefaultValuesProvider.DefaultDisplayFormat <> '') then
|
|
Result := IDefaultValuesProvider.DefaultDisplayFormat
|
|
else
|
|
if GetDefaultDisplayFormat <> '' then
|
|
Result := GetDefaultDisplayFormat
|
|
else
|
|
if IDefaultValuesProvider <> nil then
|
|
AIsCurrency := not(dfoNoCurrencyValue in DisplayFormatOptions) and
|
|
IDefaultValuesProvider.IsCurrency;
|
|
if not UseDisplayFormatWhenEditing then
|
|
Result := '';
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomTextEditProperties.IsEditValueNumeric: Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
function TcxCustomTextEditProperties.IsLookupDataVisual: Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
function TcxCustomTextEditProperties.IsMultiLine: Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
function TcxCustomTextEditProperties.IsPopupKey(Key: Word; Shift: TShiftState): Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
function TcxCustomTextEditProperties.IsValueBoundDefined(
|
|
ABound: TcxEditValueBound): Boolean;
|
|
begin
|
|
if Integer(AssignedValues.MinValue) + Integer(AssignedValues.MaxValue) = 1 then
|
|
Result := (ABound = evbMin) and AssignedValues.MinValue or
|
|
(ABound = evbMax) and AssignedValues.MaxValue
|
|
else
|
|
Result := MinValue < MaxValue;
|
|
end;
|
|
|
|
function TcxCustomTextEditProperties.IsValueBoundsDefined: Boolean;
|
|
begin
|
|
Result := IsValueBoundDefined(evbMin) or IsValueBoundDefined(evbMax);
|
|
end;
|
|
|
|
procedure TcxCustomTextEditProperties.LookupDataChanged(Sender: TObject);
|
|
begin
|
|
Changed;
|
|
end;
|
|
|
|
procedure TcxCustomTextEditProperties.MaxLengthChanged;
|
|
begin
|
|
Changed;
|
|
end;
|
|
|
|
procedure TcxCustomTextEditProperties.SetCharCase(Value: TEditCharCase);
|
|
begin
|
|
if Value <> FCharCase then
|
|
begin
|
|
FCharCase := Value;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomTextEditProperties.UseLookupData: Boolean;
|
|
begin
|
|
Result := GetLookupDataClass <> nil;
|
|
end;
|
|
|
|
function TcxCustomTextEditProperties.GetAssignedValues: TcxTextEditPropertiesValues;
|
|
begin
|
|
Result := TcxTextEditPropertiesValues(FAssignedValues);
|
|
end;
|
|
|
|
function TcxCustomTextEditProperties.GetDisplayFormat: string;
|
|
begin
|
|
if AssignedValues.DisplayFormat then
|
|
Result := FDisplayFormat
|
|
else
|
|
if (IDefaultValuesProvider = nil) or
|
|
(IDefaultValuesProvider.DefaultDisplayFormat = '') then
|
|
Result := GetDefaultDisplayFormat
|
|
else
|
|
Result := IDefaultValuesProvider.DefaultDisplayFormat;
|
|
end;
|
|
|
|
function TcxCustomTextEditProperties.GetEditFormat: string;
|
|
var
|
|
A: Boolean;
|
|
begin
|
|
Result := InternalGetEditFormat(A, A);
|
|
end;
|
|
|
|
function TcxCustomTextEditProperties.GetInnerEditMaxLength: Integer;
|
|
begin
|
|
Result := GetMaxLength;
|
|
end;
|
|
|
|
function TcxCustomTextEditProperties.GetLookupItems: TStrings;
|
|
begin
|
|
Result := FLookupItems;
|
|
end;
|
|
|
|
function TcxCustomTextEditProperties.GetLookupItemsSorted: Boolean;
|
|
begin
|
|
Result := FLookupItems.Sorted;
|
|
end;
|
|
|
|
function TcxCustomTextEditProperties.GetMaxLength: Integer;
|
|
begin
|
|
if AssignedValues.MaxLength then
|
|
Result := FMaxLength
|
|
else
|
|
Result := GetDefaultMaxLength;
|
|
end;
|
|
|
|
function TcxCustomTextEditProperties.GetViewStyle: TcxTextEditViewStyle;
|
|
const
|
|
AViewStyleMap: array[TcxEditButtonsViewStyle] of TcxTextEditViewStyle =
|
|
(vsNormal, vsButtonsOnly, vsButtonsAutoWidth);
|
|
begin
|
|
if ButtonsViewStyle <> bvsNormal then
|
|
Result := AViewStyleMap[ButtonsViewStyle]
|
|
else
|
|
if HideCursor then
|
|
Result := vsHideCursor
|
|
else
|
|
Result := vsNormal;
|
|
end;
|
|
|
|
function TcxCustomTextEditProperties.IsDisplayFormatStored: Boolean;
|
|
begin
|
|
Result := AssignedValues.DisplayFormat;
|
|
end;
|
|
|
|
function TcxCustomTextEditProperties.IsEditFormatStored: Boolean;
|
|
begin
|
|
Result := AssignedValues.EditFormat;
|
|
end;
|
|
|
|
function TcxCustomTextEditProperties.IsMaxLengthStored: Boolean;
|
|
begin
|
|
Result := AssignedValues.MaxLength;
|
|
end;
|
|
|
|
procedure TcxCustomTextEditProperties.LookupItemsChanged(Sender: TObject);
|
|
begin
|
|
Changed;
|
|
end;
|
|
|
|
procedure TcxCustomTextEditProperties.ReadIsDisplayFormatAssigned(Reader: TReader);
|
|
begin
|
|
AssignedValues.DisplayFormat := Reader.ReadBoolean;
|
|
end;
|
|
|
|
procedure TcxCustomTextEditProperties.SetDisplayFormat(const Value: string);
|
|
begin
|
|
if AssignedValues.DisplayFormat and (Value = FDisplayFormat) then
|
|
Exit;
|
|
|
|
AssignedValues.FDisplayFormat := True;
|
|
FDisplayFormat := Value;
|
|
Changed;
|
|
end;
|
|
|
|
// obsolete
|
|
procedure TcxCustomTextEditProperties.SetAssignedValues(
|
|
Value: TcxTextEditPropertiesValues);
|
|
begin
|
|
FAssignedValues.Assign(Value);
|
|
end;
|
|
|
|
procedure TcxCustomTextEditProperties.SetEchoMode(Value: TcxEditEchoMode);
|
|
begin
|
|
if Value <> FEchoMode then
|
|
begin
|
|
FEchoMode := Value;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTextEditProperties.SetEditFormat(const Value: string);
|
|
begin
|
|
if AssignedValues.EditFormat and (Value = FEditFormat) then
|
|
Exit;
|
|
|
|
AssignedValues.FEditFormat := True;
|
|
FEditFormat := Value;
|
|
Changed;
|
|
end;
|
|
|
|
procedure TcxCustomTextEditProperties.SetFixedListSelection(Value: Boolean);
|
|
begin
|
|
if Value <> FFixedListSelection then
|
|
begin
|
|
FFixedListSelection := Value;
|
|
if EditingStyle = esFixedList then
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTextEditProperties.SetHideCursor(Value: Boolean);
|
|
begin
|
|
if Value <> FHideCursor then
|
|
begin
|
|
FHideCursor := Value;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTextEditProperties.SetHideSelection(Value: Boolean);
|
|
begin
|
|
if Value <> FHideSelection then
|
|
begin
|
|
FHideSelection := Value;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTextEditProperties.SetImeMode(Value: TImeMode);
|
|
begin
|
|
if FImeMode <> Value then
|
|
begin
|
|
FImeMode := Value;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTextEditProperties.SetImeName(const Value: TImeName);
|
|
begin
|
|
if FImeName <> Value then
|
|
begin
|
|
FImeName := Value;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTextEditProperties.SetIncrementalSearch(Value: Boolean);
|
|
begin
|
|
if Value <> FIncrementalSearch then
|
|
begin
|
|
FIncrementalSearch := Value;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTextEditProperties.SetLookupItems(Value: TStrings);
|
|
begin
|
|
FLookupItems.Assign(Value);
|
|
end;
|
|
|
|
procedure TcxCustomTextEditProperties.SetLookupItemsSorted(Value: Boolean);
|
|
begin
|
|
FLookupItems.Sorted := Value;
|
|
end;
|
|
|
|
procedure TcxCustomTextEditProperties.SetMaxLength(Value: Integer);
|
|
begin
|
|
if Value < 0 then
|
|
Value := 0;
|
|
if AssignedValues.MaxLength and (Value = FMaxLength) then
|
|
Exit;
|
|
|
|
AssignedValues.FMaxLength := True;
|
|
FMaxLength := Value;
|
|
MaxLengthChanged;
|
|
end;
|
|
|
|
procedure TcxCustomTextEditProperties.SetMRUMode(Value: Boolean);
|
|
begin
|
|
if Value <> FMRUMode then
|
|
begin
|
|
FMRUMode := Value;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTextEditProperties.SetOEMConvert(Value: Boolean);
|
|
begin
|
|
if Value <> FOEMConvert then
|
|
begin
|
|
FOEMConvert := Value;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTextEditProperties.SetPasswordChar(Value: TCaptionChar);
|
|
begin
|
|
if Value <> FPasswordChar then
|
|
begin
|
|
FPasswordChar := Value;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTextEditProperties.SetUseDisplayFormatWhenEditing(
|
|
Value: Boolean);
|
|
begin
|
|
if Value <> FUseDisplayFormatWhenEditing then
|
|
begin
|
|
FUseDisplayFormatWhenEditing := Value;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTextEditProperties.SetViewStyle(Value: TcxTextEditViewStyle);
|
|
const
|
|
AButtonsViewStyleMap: array[TcxTextEditViewStyle] of TcxEditButtonsViewStyle =
|
|
(bvsNormal, bvsNormal, bvsButtonsOnly, bvsButtonsAutoWidth);
|
|
begin
|
|
if Value <> ViewStyle then
|
|
begin
|
|
BeginUpdate;
|
|
try
|
|
ButtonsViewStyle := AButtonsViewStyleMap[Value];
|
|
HideCursor := Value <> vsNormal;
|
|
finally
|
|
EndUpdate;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
{ TcxCustomTextEdit }
|
|
|
|
{$IFDEF CBUILDER10}
|
|
constructor TcxCustomTextEdit.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
end;
|
|
{$ENDIF}
|
|
|
|
destructor TcxCustomTextEdit.Destroy;
|
|
begin
|
|
FText := Text;
|
|
cxFormatController.RemoveListener(Self);
|
|
FreeAndNil(FLookupData);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.Activate(var AEditData: TcxCustomEditData);
|
|
begin
|
|
inherited Activate(AEditData);
|
|
if HandleAllocated then
|
|
begin
|
|
SelStart := 0;
|
|
if ActiveProperties.AutoSelect then
|
|
SelectAll;
|
|
end;
|
|
end;
|
|
|
|
class function TcxCustomTextEdit.GetPropertiesClass: TcxCustomEditPropertiesClass;
|
|
begin
|
|
Result := TcxCustomTextEditProperties;
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.CopyToClipboard;
|
|
begin
|
|
if ActiveProperties.EditingStyle in [esFixedList, esNoEdit] then
|
|
SelectAll;
|
|
if SelLength > 0 then
|
|
InnerTextEdit.CopyToClipboard;
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.CutToClipboard;
|
|
var
|
|
ANewSelStart: Integer;
|
|
ANewText, S: string;
|
|
APrevKeyboardAction: Boolean;
|
|
begin
|
|
if SelLength = 0 then
|
|
Exit;
|
|
if Focused then
|
|
begin
|
|
APrevKeyboardAction := KeyboardAction;
|
|
KeyboardAction := True;
|
|
try
|
|
S := '';
|
|
if CanChangeSelText(S, ANewText, ANewSelStart) then
|
|
InnerEdit.CallDefWndProc(WM_CUT, 0, 0);
|
|
finally
|
|
KeyboardAction := APrevKeyboardAction;
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
InnerTextEdit.CopyToClipboard;
|
|
SelText := '';
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomTextEdit.IsEditClass: Boolean;
|
|
begin
|
|
{$IFDEF CXTEST}
|
|
if FHideInnerEdit or FShowInnerEdit then
|
|
begin
|
|
Result := not FHideInnerEdit and FShowInnerEdit;
|
|
Exit;
|
|
end;
|
|
{$ENDIF}
|
|
Result := (ActiveProperties.EditingStyle in [esEdit, esEditList])
|
|
and not PropertiesChangeLocked and not IsDesigning;
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.PasteFromClipboard;
|
|
var
|
|
ANewSelStart: Integer;
|
|
ANewText, S: string;
|
|
APrevKeyboardAction: Boolean;
|
|
begin
|
|
if Clipboard.HasFormat(CF_TEXT) then
|
|
if Focused then
|
|
begin
|
|
APrevKeyboardAction := KeyboardAction;
|
|
KeyboardAction := True;
|
|
try
|
|
S := Clipboard.AsText;
|
|
if CanChangeSelText(S, ANewText, ANewSelStart) then
|
|
InnerEdit.CallDefWndProc(WM_PASTE, 0, 0);
|
|
finally
|
|
KeyboardAction := APrevKeyboardAction;
|
|
end;
|
|
end
|
|
else
|
|
SelText := Clipboard.AsText;
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.PrepareEditValue(const ADisplayValue: TcxEditValue;
|
|
out EditValue: TcxEditValue; AEditFocused: Boolean);
|
|
begin
|
|
EditValue := ADisplayValue;
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.SelectAll;
|
|
begin
|
|
InnerTextEdit.SelectAll;
|
|
end;
|
|
|
|
{$IFDEF DELPHI10}
|
|
function TcxCustomTextEdit.GetTextBaseLine: Integer;
|
|
begin
|
|
Result := ViewInfo.GetTextBaseLine;
|
|
end;
|
|
|
|
function TcxCustomTextEdit.HasTextBaseLine: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
{$ENDIF}
|
|
|
|
procedure TcxCustomTextEdit.ClearSelection;
|
|
var
|
|
APrevKeyboardAction: Boolean;
|
|
APrevSelStart: Integer;
|
|
AText: string;
|
|
begin
|
|
if SelLength = 0 then
|
|
Exit;
|
|
APrevKeyboardAction := KeyboardAction;
|
|
KeyboardAction := Focused or FIsChangeBySpellChecker;
|
|
try
|
|
AText := DisplayValue;
|
|
Delete(AText, SelStart + 1, SelLength);
|
|
APrevSelStart := SelStart;
|
|
if SetDisplayText(AText) then
|
|
SelStart := APrevSelStart;
|
|
finally
|
|
KeyboardAction := APrevKeyboardAction;
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomTextEdit.DoInnerControlDefaultHandler(var Message: TMessage): Boolean;
|
|
begin
|
|
InternalSpellCheckerHandler(Message);
|
|
Result := inherited DoInnerControlDefaultHandler(Message);
|
|
end;
|
|
|
|
function TcxCustomTextEdit.IsChildWindow(AWnd: THandle): Boolean;
|
|
begin
|
|
Result := inherited IsChildWindow(AWnd) or
|
|
(Assigned(dxISpellChecker) and dxISpellChecker.IsSpellCheckerDialogControl(AWnd));
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.SetScrollBarsParameters(AIsScrolling: Boolean = False);
|
|
begin
|
|
inherited SetScrollBarsParameters(AIsScrolling);
|
|
InternalCheckSelection;
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.SetSelection(ASelStart: Integer; ASelLength: Integer);
|
|
begin
|
|
SelStart := ASelStart;
|
|
SelLength := ASelLength;
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.Undo;
|
|
begin
|
|
Reset;
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.AdjustInnerEditPosition;
|
|
var
|
|
AInnerEditBounds: TRect;
|
|
AInnerEditHeight, AInnerEditTop: Integer;
|
|
R: TRect;
|
|
begin
|
|
if (InnerTextEdit = nil) or FInnerEditPositionAdjusting then
|
|
Exit;
|
|
FInnerEditPositionAdjusting := True;
|
|
try
|
|
AInnerEditHeight := GetInnerEditHeight;
|
|
AInnerEditTop := 0;
|
|
R := ViewInfo.ClientRect;
|
|
case TcxCustomTextEditProperties(ActiveProperties).Alignment.Vert of
|
|
taTopJustify:
|
|
AInnerEditTop := R.Top + ContentParams.Offsets.Top;
|
|
taBottomJustify:
|
|
AInnerEditTop := R.Bottom - AInnerEditHeight - ContentParams.Offsets.Bottom;
|
|
taVCenter:
|
|
AInnerEditTop := R.Top + ContentParams.Offsets.Top + (R.Bottom - R.Top - AInnerEditHeight - ContentParams.Offsets.Top - ContentParams.Offsets.Bottom) div 2;
|
|
end;
|
|
if AInnerEditTop < R.Top + ContentParams.Offsets.Top then
|
|
AInnerEditTop := R.Top + ContentParams.Offsets.Top;
|
|
with ContentParams.Offsets do
|
|
AInnerEditBounds := Rect(R.Left + Left, AInnerEditTop,
|
|
R.Right - R.Left + 1 - (Left + Right), AInnerEditHeight);
|
|
with AInnerEditBounds do
|
|
if not EqualRect(InnerEdit.Control.BoundsRect, Rect(Left, Top, Left + Right, Top + Bottom)) then
|
|
InnerEdit.Control.SetBounds(Left, Top, Right, Bottom);
|
|
if IsInplace then
|
|
begin
|
|
Inc(R.Top);
|
|
Dec(R.Bottom);
|
|
end;
|
|
if not IsInplace and (ViewInfo.NativeState <> TC_NONE) and
|
|
ViewInfo.ComboBoxStyle and (ActiveProperties.EditingStyle in [esEdit, esEditList]) then
|
|
begin
|
|
Dec(R.Right);
|
|
Dec(R.Bottom);
|
|
end;
|
|
AlignControls(InnerEdit.Control, R);
|
|
finally
|
|
FInnerEditPositionAdjusting := False;
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomTextEdit.CanKeyDownModifyEdit(Key: Word; Shift: TShiftState): Boolean;
|
|
begin
|
|
Result := inherited CanKeyDownModifyEdit(Key, Shift);
|
|
Result := Result or (Key = VK_DELETE);
|
|
if ActiveProperties.UseLookupData and not ILookupData.IsEmpty and
|
|
GetScrollLookupDataList(escKeyboard) then
|
|
case Key of
|
|
VK_DOWN, VK_UP:
|
|
Result := not(ssAlt in Shift) and not HasPopupWindow;
|
|
VK_PRIOR, VK_NEXT:
|
|
Result := not HasPopupWindow;
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomTextEdit.CanKeyPressModifyEdit(Key: Char): Boolean;
|
|
begin
|
|
Result := (Key = #8) or (Key = #22) or (Key = #24) or IsTextChar(Key);
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.ChangeHandler(Sender: TObject);
|
|
begin
|
|
LockChangeEvents(True);
|
|
try
|
|
inherited ChangeHandler(Sender);
|
|
if not ViewInfo.IsEditClass then
|
|
UpdateDrawValue;
|
|
if Focused and ActiveProperties.IsEditValueNumeric and
|
|
ActiveProperties.HasDigitGrouping(FIsDisplayValueSynchronizing) then
|
|
SeparateDigitGroups(Self);
|
|
finally
|
|
LockChangeEvents(False);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.DoEditKeyDown(var Key: Word; Shift: TShiftState);
|
|
var
|
|
AEditingStyle: TcxEditEditingStyle;
|
|
AFindSelection: Boolean;
|
|
APrevCurrentKey: TcxEditValue;
|
|
APrevKey: Word;
|
|
begin
|
|
AEditingStyle := ActiveProperties.EditingStyle;
|
|
if (AEditingStyle = esFixedList) and not IsSpecialKey(Key, Shift) then
|
|
case Key of
|
|
VK_LEFT, VK_RIGHT, VK_DELETE:
|
|
begin
|
|
FindSelection := False;
|
|
DoAfterKeyDown(Key, Shift);
|
|
Key := 0;
|
|
end;
|
|
end;
|
|
|
|
InnerTextEdit.InternalUpdating := True;
|
|
APrevKey := Key;
|
|
AFindSelection := FindSelection;
|
|
inherited DoEditKeyDown(Key, Shift);
|
|
if (TranslateKey(APrevKey) = VK_RETURN) and AFindSelection then
|
|
SelectAll;
|
|
if Key = 0 then
|
|
Exit;
|
|
|
|
case Key of
|
|
VK_LEFT, VK_RIGHT:
|
|
begin
|
|
if not(ssShift in Shift) and (SelLength > 0) then
|
|
begin
|
|
if Key = VK_RIGHT then
|
|
SelStart := SelStart + SelLength
|
|
else
|
|
SelStart := SelStart;
|
|
SelLength := 0;
|
|
Key := 0;
|
|
end;
|
|
FindSelection := False;
|
|
end;
|
|
|
|
VK_DOWN, VK_UP, VK_PRIOR, VK_NEXT, VK_HOME, VK_END:
|
|
begin
|
|
if ((Key <> VK_HOME) and (Key <> VK_END) or (AEditingStyle = esFixedList)) and
|
|
ActiveProperties.UseLookupData and GetScrollLookupDataList(escKeyboard) and
|
|
not ILookupData.IsEmpty then
|
|
begin
|
|
LockChangeEvents(True);
|
|
LookupItemsScrolling := True;
|
|
try
|
|
APrevCurrentKey := ILookupData.CurrentKey;
|
|
LockClick(True);
|
|
try
|
|
case Key of
|
|
VK_PRIOR:
|
|
if ssCtrl in Shift then
|
|
ILookupData.Go(egdBegin, False)
|
|
else
|
|
ILookupData.Go(egdPageUp, False);
|
|
VK_NEXT:
|
|
if ssCtrl in Shift then
|
|
ILookupData.Go(egdEnd, False)
|
|
else
|
|
ILookupData.Go(egdPageDown, False);
|
|
VK_UP:
|
|
ILookupData.Go(egdPrev, False);
|
|
VK_DOWN:
|
|
ILookupData.Go(egdNext, False);
|
|
VK_HOME:
|
|
ILookupData.Go(egdBegin, False);
|
|
VK_END:
|
|
ILookupData.Go(egdEnd, False);
|
|
end;
|
|
finally
|
|
LockClick(False);
|
|
end;
|
|
if not VarEqualsExact(APrevCurrentKey, ILookupData.CurrentKey) then
|
|
begin
|
|
DoClick;
|
|
if CanPostEditValue and ActiveProperties.ImmediatePost and
|
|
ValidateEdit(True) then
|
|
InternalPostEditValue;
|
|
end;
|
|
Key := 0;
|
|
finally
|
|
LookupItemsScrolling := False;
|
|
LockChangeEvents(False);
|
|
end;
|
|
end;
|
|
if (Key <> VK_HOME) and (Key <> VK_END) and not InnerTextEdit.MultiLine then
|
|
begin
|
|
if Key <> 0 then
|
|
DoAfterKeyDown(Key, Shift);
|
|
Key := 0;
|
|
end;
|
|
end;
|
|
|
|
VK_DELETE:
|
|
begin
|
|
if AEditingStyle = esEditList then
|
|
begin
|
|
DoAfterKeyDown(Key, Shift);
|
|
Key := 0;
|
|
end
|
|
else
|
|
FindSelection := False;
|
|
end;
|
|
end;
|
|
if (Key = VK_END) and (SelLength = 0) and (AEditingStyle <> esFixedList) then
|
|
FindSelection := False;
|
|
|
|
if Key <> 0 then
|
|
InnerTextEdit.InternalUpdating := False;
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.DoEditKeyPress(var Key: Char);
|
|
|
|
function FillFromList(var AFindText: string): Boolean;
|
|
var
|
|
ATail: string;
|
|
L: Integer;
|
|
S: string;
|
|
begin
|
|
S := AFindText;
|
|
if InnerTextEdit.ImeLastChar <> #0 then
|
|
S := S + InnerTextEdit.ImeLastChar;
|
|
Result := ILookupData.Locate(S, ATail, False);
|
|
if Result then
|
|
begin
|
|
AFindText := S;
|
|
if InnerTextEdit.ImeLastChar <> #0 then
|
|
begin
|
|
L := Length(AFindText);
|
|
Insert(Copy(AFindText, L, 1), ATail, 1);
|
|
Delete(AFindText, L, 1);
|
|
end;
|
|
end;
|
|
FFindSelection := Result;
|
|
if AFindText = '' then
|
|
begin
|
|
if ActiveProperties.EditingStyle <> esFixedList then
|
|
InternalSetDisplayValue('');
|
|
FFindSelection := False;
|
|
end;
|
|
if Result then
|
|
begin
|
|
DataBinding.DisplayValue := AFindText + ATail;
|
|
SelStart := Length(AFindText);
|
|
SelLength := Length(ATail);
|
|
end;
|
|
UpdateDrawValue;
|
|
end;
|
|
|
|
function CanContinueIncrementalSearch: Boolean;
|
|
begin
|
|
Result := ActiveProperties.EditingStyle in [esEditList, esFixedList];
|
|
if not Result then
|
|
Result := (SelLength = 0) and (SelStart = Length(DisplayValue)) or
|
|
FindSelection or (SelLength > 0);
|
|
end;
|
|
|
|
var
|
|
AEditingStyle: TcxEditEditingStyle;
|
|
AFindText: string;
|
|
AFound: Boolean;
|
|
APrevCurrentKey: TcxEditValue;
|
|
APrevFindSelection: Boolean;
|
|
begin
|
|
InnerTextEdit.InternalUpdating := True;
|
|
inherited DoEditKeyPress(Key);
|
|
if Key = #0 then
|
|
Exit;
|
|
|
|
UnlockLookupDataTextChanged;
|
|
KeyboardAction := True;
|
|
AEditingStyle := ActiveProperties.EditingStyle;
|
|
if AEditingStyle = esFixedList then
|
|
case Key of
|
|
#8:
|
|
if not ActiveProperties.FixedListSelection then
|
|
begin
|
|
Key := #0;
|
|
FindSelection := False;
|
|
end;
|
|
end;
|
|
|
|
APrevCurrentKey := ILookupData.CurrentKey;
|
|
APrevFindSelection := FindSelection;
|
|
AFound := False;
|
|
LockClick(True);
|
|
try
|
|
if Key = #8 then
|
|
begin
|
|
if ActiveProperties.UseLookupData and ActiveProperties.CanIncrementalSearch then
|
|
begin
|
|
if (AEditingStyle = esEditList) and (Length(DisplayValue) > 0) and not FindSelection then
|
|
begin
|
|
SelLength := Length(DisplayValue) - SelStart;
|
|
FindSelection := True;
|
|
end;
|
|
if FindSelection then
|
|
begin
|
|
AFindText := Copy(DisplayValue, 1, Length(DisplayValue) - SelLength);
|
|
SetLength(AFindText, Length(AFindText) - Length(AnsiLastChar(AFindText)));
|
|
LockLookupDataTextChanged;
|
|
AFound := FillFromList(AFindText);
|
|
end;
|
|
if AEditingStyle = esFixedList then
|
|
Key := #0;
|
|
end;
|
|
end
|
|
else
|
|
if IsTextChar(Key) then
|
|
begin
|
|
if ActiveProperties.UseLookupData then
|
|
begin
|
|
if ActiveProperties.CanIncrementalSearch and CanContinueIncrementalSearch then
|
|
begin
|
|
LockLookupDataTextChanged;
|
|
AFound := False;
|
|
AFindText := DisplayValue;
|
|
if SelLength > 0 then
|
|
AFindText := Copy(AFindText, 1, SelStart) + Key
|
|
else
|
|
if AEditingStyle = esFixedList then
|
|
if FindSelection then
|
|
begin
|
|
AFindText := AFindText + Key;
|
|
AFound := FillFromList(AFindText);
|
|
if not AFound then
|
|
AFindText := Key;
|
|
end
|
|
else
|
|
AFindText := Key
|
|
else
|
|
Insert(Key, AFindText, SelStart + 1);
|
|
if not AFound then
|
|
AFound := FillFromList(AFindText);
|
|
if (AEditingStyle = esFixedList) and not ActiveProperties.FixedListSelection and not AFound then
|
|
begin
|
|
AFindText := Key;
|
|
AFound := FillFromList(AFindText);
|
|
end;
|
|
end;
|
|
if (AEditingStyle in [esEditList, esFixedList]) and not AFound then
|
|
begin
|
|
Key := #0;
|
|
if (AEditingStyle = esEditList) and (DisplayValue <> '') or
|
|
(AEditingStyle = esFixedList) and ActiveProperties.FixedListSelection and APrevFindSelection then
|
|
FindSelection := True;
|
|
end;
|
|
end;
|
|
end;
|
|
finally
|
|
LockClick(False);
|
|
KeyboardAction := False;
|
|
if ActiveProperties.UseLookupData and not VarEqualsExact(APrevCurrentKey,
|
|
ILookupData.CurrentKey) then
|
|
DoClick;
|
|
end;
|
|
if AFound then
|
|
Key := #0;
|
|
if Key <> #0 then
|
|
InnerTextEdit.InternalUpdating := False;
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.DoExit;
|
|
begin
|
|
inherited DoExit;
|
|
FindSelection := False;
|
|
end;
|
|
|
|
function TcxCustomTextEdit.DoMouseWheel(Shift: TShiftState; WheelDelta: Integer;
|
|
MousePos: TPoint): Boolean;
|
|
const
|
|
AGoDirectionMap: array [Boolean] of TcxEditLookupDataGoDirection = (egdNext, egdPrev);
|
|
var
|
|
APrevCurrentKey: TcxEditValue;
|
|
begin
|
|
Result := inherited DoMouseWheel(Shift, WheelDelta, MousePos);
|
|
if Result then
|
|
Exit;
|
|
|
|
Result := GetScrollLookupDataList(escMouseWheel) and not HasPopupWindow and
|
|
ActiveProperties.UseLookupData and not ILookupData.IsEmpty and HandleMouseWheel(Shift);
|
|
if not(Result and DoEditing) then
|
|
Exit;
|
|
|
|
APrevCurrentKey := ILookupData.CurrentKey;
|
|
LockChangeEvents(True);
|
|
LookupItemsScrolling := True;
|
|
try
|
|
LockClick(True);
|
|
try
|
|
ILookupData.Go(AGoDirectionMap[WheelDelta > 0], False);
|
|
finally
|
|
LockClick(False);
|
|
if not VarEqualsExact(APrevCurrentKey, ILookupData.CurrentKey) then
|
|
begin
|
|
DoClick;
|
|
if CanPostEditValue and ActiveProperties.ImmediatePost and ValidateEdit(True) then
|
|
InternalPostEditValue;
|
|
end;
|
|
end;
|
|
finally
|
|
LookupItemsScrolling := False;
|
|
LockChangeEvents(False);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.FillSizeProperties(var AEditSizeProperties: TcxEditSizeProperties);
|
|
begin
|
|
if ViewInfo = nil then
|
|
Exit;
|
|
AEditSizeProperties := DefaultcxEditSizeProperties;
|
|
AEditSizeProperties.MaxLineCount := 1;
|
|
end;
|
|
|
|
function TcxCustomTextEdit.GetInnerControlBounds(const AInnerControlsRegion: TRect;
|
|
AInnerControl: TControl): TcxContainerInnerControlBounds;
|
|
begin
|
|
if IsEditClass then
|
|
Result := inherited GetInnerControlBounds(AInnerControlsRegion, AInnerControl)
|
|
else
|
|
begin
|
|
Result.IsEmpty := False;
|
|
Result.Rect := cxEmptyRect;
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomTextEdit.GetDisplayValue: string;
|
|
begin
|
|
if InnerEdit = nil then
|
|
Result := ''
|
|
else
|
|
Result := InnerEdit.EditValue;
|
|
end;
|
|
|
|
function TcxCustomTextEdit.GetInnerEditClass: TControlClass;
|
|
begin
|
|
Result := TcxCustomInnerTextEdit;
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.Initialize;
|
|
var
|
|
ALookupDataClass: TcxInterfacedPersistentClass;
|
|
begin
|
|
inherited Initialize;
|
|
FBeepOnEnter := True;
|
|
FFindSelection := False;
|
|
|
|
if InnerTextEdit <> nil then
|
|
begin
|
|
TControlAccess(InnerTextEdit.Control).Color := clWindow;
|
|
InnerTextEdit.OnSelChange := SelChange;
|
|
end;
|
|
Width := 121;
|
|
Height := 21;
|
|
|
|
ALookupDataClass := Properties.GetLookupDataClass;
|
|
if ALookupDataClass <> nil then
|
|
begin
|
|
FLookupData := ALookupDataClass.Create(Self);
|
|
ILookupData.OnSelectItem := HandleSelectItem;
|
|
end;
|
|
|
|
cxFormatController.AddListener(Self);
|
|
end;
|
|
|
|
function TcxCustomTextEdit.InternalDoEditing: Boolean;
|
|
begin
|
|
Result := ActiveProperties.EditingStyle <> esNoEdit;
|
|
end;
|
|
|
|
function TcxCustomTextEdit.InternalGetEditingValue: TcxEditValue;
|
|
begin
|
|
Result := Text;
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.InternalSetDisplayValue(const Value: TcxEditValue);
|
|
begin
|
|
DataBinding.DisplayValue := Value;
|
|
if not KeyboardAction then
|
|
begin
|
|
ResetOnNewDisplayValue;
|
|
SynchronizeEditValue;
|
|
EditModified := False;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.InternalValidateDisplayValue(const ADisplayValue: TcxEditValue);
|
|
//var
|
|
// APrevFindSelection: Boolean;
|
|
begin
|
|
// APrevFindSelection := FindSelection;
|
|
// try
|
|
if (ActiveProperties.EditingStyle = esEdit) and ActiveProperties.UseLookupData and
|
|
not ILookupData.Find(ADisplayValue) then
|
|
DoOnNewLookupDisplayText(ADisplayValue);
|
|
inherited InternalValidateDisplayValue(ADisplayValue);
|
|
// finally
|
|
// FindSelection := APrevFindSelection;
|
|
// end;
|
|
end;
|
|
|
|
function TcxCustomTextEdit.IsTextInputMode: Boolean;
|
|
begin
|
|
with ActiveProperties do
|
|
Result := (EchoMode = eemNormal) and CanModify;
|
|
end;
|
|
|
|
function TcxCustomTextEdit.IsValidChar(AChar: Char): Boolean;
|
|
begin
|
|
Result := inherited IsValidChar(AChar) or
|
|
(AnsiChar(AChar) in ActiveProperties.ValidChars);
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.KeyPress(var Key: Char);
|
|
begin
|
|
if (Word(Key) = VK_ESCAPE) and IsEditValueResetting and
|
|
FIsPopupWindowJustClosed and not HasPopupWindow then
|
|
FIsPopupWindowJustClosed := False;
|
|
inherited KeyPress(Key);
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.Loaded;
|
|
begin
|
|
inherited Loaded;
|
|
ShortRefreshContainer(False);
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.PropertiesChanged(Sender: TObject);
|
|
begin
|
|
if InnerTextEdit <> nil then
|
|
InnerTextEdit.Alignment := ActiveProperties.FAlignment.Horz;
|
|
if ActiveProperties.UseLookupData then
|
|
ILookupData.PropertiesChanged;
|
|
if ActiveProperties.UseLookupData and not FLookupDataTextChangedLocked then
|
|
ILookupData.TextChanged;
|
|
if not PropertiesChangeLocked and not IsEditClass then
|
|
UpdateDrawValue;
|
|
|
|
if InnerTextEdit = nil then
|
|
Exit;
|
|
|
|
ImeMode := ActiveProperties.ImeMode;
|
|
ImeName := ActiveProperties.ImeName;
|
|
with InnerTextEdit do
|
|
begin
|
|
Alignment := ActiveProperties.Alignment.Horz;
|
|
AutoSelect := ActiveProperties.AutoSelect and not IsInplace;
|
|
CharCase := ActiveProperties.FCharCase;
|
|
EchoMode := ActiveProperties.FEchoMode;
|
|
HideSelection := ActiveProperties.FHideSelection;
|
|
ImeMode := ActiveProperties.ImeMode;
|
|
ImeName := ActiveProperties.ImeName;
|
|
MaxLength := ActiveProperties.GetInnerEditMaxLength;
|
|
OEMConvert := ActiveProperties.OEMConvert;
|
|
PasswordChar := ActiveProperties.PasswordChar;
|
|
end;
|
|
|
|
CheckEditValue;
|
|
if not IsPosting then
|
|
UpdateDisplayValue;
|
|
UpdateDrawValue;
|
|
inherited PropertiesChanged(Sender);
|
|
if InnerTextEdit <> nil then
|
|
InnerTextEdit.Control.Invalidate;
|
|
end;
|
|
|
|
function TcxCustomTextEdit.RefreshContainer(const P: TPoint; Button: TcxMouseButton;
|
|
Shift: TShiftState; AIsMouseEvent: Boolean): Boolean;
|
|
begin
|
|
Result := False;
|
|
if (not HandleAllocated) or (csDestroying in ComponentState) then Exit;
|
|
Result := inherited RefreshContainer(P, Button, Shift, AIsMouseEvent);
|
|
if Result then
|
|
AdjustInnerEdit;
|
|
end;
|
|
|
|
function TcxCustomTextEdit.SetDisplayText(const Value: string): Boolean;
|
|
var
|
|
ADisplayValue: TcxEditValue;
|
|
begin
|
|
ADisplayValue := Value;
|
|
Result := ActiveProperties.IsDisplayValueValid(ADisplayValue, InternalFocused);
|
|
if Result then
|
|
Result := not(KeyboardAction and not DoEditing);
|
|
if Result then
|
|
InternalSetDisplayValue(ADisplayValue);
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.SetInternalDisplayValue(Value: TcxEditValue);
|
|
begin
|
|
if InnerEdit <> nil then
|
|
InnerEdit.EditValue := Value;
|
|
end;
|
|
|
|
function TcxCustomTextEdit.WantNavigationKeys: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.LockedInnerEditWindowProc(var Message: TMessage);
|
|
begin
|
|
if Message.Msg = WM_SETFOCUS then
|
|
begin
|
|
if InnerTextEdit.AutoSelect then
|
|
SelectAll;
|
|
end
|
|
else
|
|
inherited LockedInnerEditWindowProc(Message);
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.UnlockInnerEditRepainting;
|
|
var
|
|
APrevAutoSelect: Boolean;
|
|
begin
|
|
inherited UnlockInnerEditRepainting;
|
|
APrevAutoSelect := InnerTextEdit.AutoSelect;
|
|
InnerTextEdit.AutoSelect := False;
|
|
SendMessage(InnerEdit.Control.Handle, WM_SETFOCUS, 0, 0);
|
|
InnerTextEdit.AutoSelect := APrevAutoSelect;
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.WndProc(var Message: TMessage);
|
|
var
|
|
ASaveHideSelection: Boolean;
|
|
begin
|
|
if (Message.Msg = WM_SPELLCHECKERAUTOCORRECT) and (InnerControl <> nil) and
|
|
InnerControl.HandleAllocated then
|
|
with PdxSpellCheckerAutoCorrectWordRange(Message.LParam)^ do
|
|
begin
|
|
ASaveHideSelection := ActiveProperties.HideSelection;
|
|
ActiveProperties.HideSelection := True;
|
|
try
|
|
Self.SelStart := SelStart;
|
|
Self.SelLength := SelLength;
|
|
SendMessageW(InnerControl.Handle, EM_REPLACESEL, 1, Longint(PWideChar(Replacement)));
|
|
Self.SelStart := NewSelStart;
|
|
finally
|
|
ActiveProperties.HideSelection := ASaveHideSelection;
|
|
end;
|
|
end;
|
|
inherited WndProc(Message);
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.FormatChanged;
|
|
begin
|
|
ActiveProperties.Changed;
|
|
SynchronizeDisplayValue;
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.AdjustInnerEdit;
|
|
var
|
|
AFont: TFont;
|
|
begin
|
|
if (InnerTextEdit = nil) or FIsCreating then
|
|
Exit;
|
|
InnerEdit.LockBounds(True);
|
|
try
|
|
with TControlAccess(InnerTextEdit.Control) do
|
|
begin
|
|
Color := ViewInfo.BackgroundColor;
|
|
AFont := TFont.Create;
|
|
try
|
|
AFont.Assign(ActiveStyle.GetVisibleFont);
|
|
AFont.Color := ViewInfo.TextColor;
|
|
AssignFonts(Font, AFont);
|
|
finally
|
|
FreeAndNil(AFont);
|
|
end;
|
|
end;
|
|
finally
|
|
InnerEdit.LockBounds(False);
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomTextEdit.CanChangeSelText(const Value: string;
|
|
out ANewText: string; out ANewSelStart: Integer): Boolean;
|
|
var
|
|
ADisplayValue: TcxEditValue;
|
|
AEditingStyle: TcxEditEditingStyle;
|
|
AValue: string;
|
|
begin
|
|
AValue := string(PChar(Value));
|
|
Result := False;
|
|
AEditingStyle := ActiveProperties.EditingStyle;
|
|
if KeyboardAction and (AEditingStyle = esNoEdit) then
|
|
Exit;
|
|
if AEditingStyle in [esFixedList, esNoEdit] then
|
|
SelectAll;
|
|
if KeyboardAction and (AEditingStyle in [esEdit, esNoEdit]) and (ActiveProperties.MaxLength > 0) then
|
|
begin
|
|
ANewText := Copy(Text, 1, SelStart) + AValue;
|
|
ANewSelStart := Length(WideString(ANewText));
|
|
if ANewSelStart > ActiveProperties.MaxLength then
|
|
ANewSelStart := ActiveProperties.MaxLength;
|
|
ANewSelStart := Length(string(Copy(WideString(ANewText), 1, ANewSelStart)));
|
|
if ANewSelStart < SelStart then
|
|
Exit;
|
|
|
|
ANewText := ANewText + Copy(Text, SelStart + SelLength + 1, Length(Text) - SelStart - SelLength);
|
|
if Length(WideString(ANewText)) > ActiveProperties.MaxLength then
|
|
ANewText := Copy(WideString(ANewText), 1, ActiveProperties.MaxLength);
|
|
end else
|
|
begin
|
|
if ActiveProperties.EditingStyle <> esFixedList then
|
|
begin
|
|
ANewText := Text;
|
|
ANewText := Copy(ANewText, 1, SelStart) + AValue +
|
|
Copy(ANewText, SelStart + SelLength + 1, Length(ANewText) - SelLength - SelStart);
|
|
end
|
|
else
|
|
ANewText := AValue;
|
|
ANewSelStart := SelStart + Length(AValue);
|
|
end;
|
|
ADisplayValue := ANewText;
|
|
Result := ActiveProperties.IsDisplayValueValid(ADisplayValue, InternalFocused) and
|
|
not (KeyboardAction and not DoEditing);
|
|
if Result then
|
|
ANewText := VarToStr(ADisplayValue);
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.CheckEditValue;
|
|
begin
|
|
if DataBinding.CanCheckEditorValue and ActiveProperties.IsEditValueNumeric and
|
|
not PropertiesChangeLocked and ActiveProperties.IsValueBoundsDefined then
|
|
CheckEditorValueBounds;
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.CheckEditorValueBounds;
|
|
begin
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.DoOnNewLookupDisplayText(const AText: string);
|
|
begin
|
|
with Properties do
|
|
if Assigned(OnNewLookupDisplayText) then
|
|
OnNewLookupDisplayText(Self, AText);
|
|
if RepositoryItem <> nil then
|
|
with ActiveProperties do
|
|
if Assigned(OnNewLookupDisplayText) then
|
|
OnNewLookupDisplayText(Self, AText);
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.DoDrawMisspellings;
|
|
begin
|
|
if Assigned(dxISpellChecker) then
|
|
dxISpellChecker.DrawMisspellings(InnerControl);
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.DoSelectionChanged;
|
|
begin
|
|
if Assigned(dxISpellChecker) then
|
|
dxISpellChecker.SelectionChanged(InnerControl);
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.DoLayoutChanged;
|
|
begin
|
|
FLastFirstVisibleCharIndex := InnerTextEdit.GetFirstVisibleCharIndex;
|
|
if Assigned(dxISpellChecker) then
|
|
dxISpellChecker.LayoutChanged(InnerControl);
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.DoTextChanged;
|
|
begin
|
|
if Assigned(dxISpellChecker) then
|
|
dxISpellChecker.TextChanged(InnerControl);
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.InternalCheckSelection;
|
|
begin
|
|
if InnerControl.HandleAllocated then
|
|
begin
|
|
if FLastFirstVisibleCharIndex <> InnerTextEdit.GetFirstVisibleCharIndex then
|
|
DoLayoutChanged
|
|
else
|
|
if (InnerTextEdit.SelStart <> FLastSelPosition) or
|
|
(InnerTextEdit.SelLength <> FLastSelLength) then
|
|
begin
|
|
FLastSelPosition := InnerTextEdit.SelStart;
|
|
FLastSelLength := InnerTextEdit.SelLength;
|
|
DoSelectionChanged;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.InternalSpellCheckerHandler(Message: TMessage);
|
|
begin
|
|
case Message.Msg of
|
|
WM_SETFOCUS:
|
|
if Assigned(dxISpellChecker) then
|
|
dxISpellChecker.CheckStart(InnerControl);
|
|
WM_KILLFOCUS:
|
|
if Assigned(dxISpellChecker) then
|
|
dxISpellChecker.CheckFinish;
|
|
WM_SETFONT, WM_SIZE:
|
|
DoLayoutChanged;
|
|
WM_LBUTTONUP, WM_MBUTTONUP, WM_RBUTTONUP, WM_KEYUP:
|
|
InternalCheckSelection;
|
|
CN_CTLCOLOREDIT:
|
|
if not InnerTextEdit.MultiLine then
|
|
RedrawMisspelledWords;
|
|
WM_CTLCOLOREDIT:
|
|
if InnerTextEdit.MultiLine then
|
|
RedrawMisspelledWords;
|
|
WM_PAINT:
|
|
RedrawMisspelledWords;
|
|
WM_UNDO, EM_UNDO:
|
|
if Assigned(dxISpellChecker) then
|
|
dxISpellChecker.Undo;
|
|
else
|
|
if Message.Msg = WM_REDRAWMISSPELLINGS then
|
|
DoDrawMisspellings;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.RedrawMisspelledWords;
|
|
begin
|
|
if InnerControl.HandleAllocated then
|
|
PostMessage(InnerControl.Handle, WM_REDRAWMISSPELLINGS, 0, 0);
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.SpellCheckerSetSelText(
|
|
const AValue: string; APost: Boolean = False);
|
|
begin
|
|
FIsChangeBySpellChecker := True;
|
|
try
|
|
SelText := AValue;
|
|
if APost and not IsInplace and CanPostEditValue and not Focused then
|
|
begin
|
|
LockChangeEvents(True);
|
|
try
|
|
SpellCheckerSetValue(DisplayValue);
|
|
InternalPostEditValue;
|
|
finally
|
|
LockChangeEvents(False);
|
|
end;
|
|
end;
|
|
ModifiedAfterEnter := True;
|
|
finally
|
|
FIsChangeBySpellChecker := False;
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomTextEdit.GetInnerEditHeight: Integer;
|
|
begin
|
|
Result := cxScreenCanvas.FontHeight(TControlAccess(InnerTextEdit.Control).Font)
|
|
end;
|
|
|
|
function TcxCustomTextEdit.GetItemIndex: Integer;
|
|
begin
|
|
Result := LookupKeyToItemIndex(ILookupData.CurrentKey);
|
|
end;
|
|
|
|
function TcxCustomTextEdit.GetItemObject: TObject;
|
|
begin
|
|
if ItemIndex <> -1 then
|
|
Result := ActiveProperties.LookupItems.Objects[ItemIndex]
|
|
else
|
|
Result := nil;
|
|
end;
|
|
|
|
function TcxCustomTextEdit.GetScrollLookupDataList(AScrollCause: TcxEditScrollCause): Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.HandleSelectItem(Sender: TObject);
|
|
var
|
|
ANewEditValue: TcxEditValue;
|
|
AEditValueChanged: Boolean;
|
|
begin
|
|
ANewEditValue := LookupKeyToEditValue(ILookupData.CurrentKey);
|
|
AEditValueChanged := not VarEqualsExact(EditValue, ANewEditValue);
|
|
if AEditValueChanged and not DoEditing then
|
|
Exit;
|
|
SaveModified;
|
|
LockLookupDataTextChanged;
|
|
try
|
|
InternalEditValue := ANewEditValue;
|
|
finally
|
|
UnlockLookupDataTextChanged;
|
|
RestoreModified;
|
|
end;
|
|
if AEditValueChanged then
|
|
ModifiedAfterEnter := True;
|
|
SelectAll;
|
|
ShortRefreshContainer(False);
|
|
end;
|
|
|
|
function TcxCustomTextEdit.InternalGetText: string;
|
|
begin
|
|
Result := DisplayValue;
|
|
end;
|
|
|
|
function TcxCustomTextEdit.InternalSetText(const Value: string): Boolean;
|
|
begin
|
|
Result := SetDisplayText(Value);
|
|
end;
|
|
|
|
function TcxCustomTextEdit.ItemIndexToLookupKey(AItemIndex: Integer): TcxEditValue;
|
|
begin
|
|
Result := AItemIndex;
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.LockLookupDataTextChanged;
|
|
begin
|
|
FLookupDataTextChangedLocked := True;
|
|
end;
|
|
|
|
function TcxCustomTextEdit.LookupKeyToEditValue(const AKey: TcxEditValue): TcxEditValue;
|
|
var
|
|
AText: string;
|
|
begin
|
|
AText := ILookupData.GetDisplayText(AKey);
|
|
PrepareEditValue(AText, Result, False);
|
|
end;
|
|
|
|
function TcxCustomTextEdit.LookupKeyToItemIndex(const AKey: TcxEditValue): Integer;
|
|
begin
|
|
Result := AKey;
|
|
end;
|
|
|
|
function TcxCustomTextEdit.NeedResetInvalidTextWhenPropertiesChanged: Boolean;
|
|
begin
|
|
Result := not IsInplace and not DataBinding.IDefaultValuesProvider.IsDataStorage;
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.ResetOnNewDisplayValue;
|
|
begin
|
|
if ActiveProperties.UseLookupData then
|
|
FindSelection := False;
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.SelChange(Sender: TObject);
|
|
begin
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.SetEditingText(const Value: TCaption);
|
|
begin
|
|
if DoEditing then
|
|
begin
|
|
Text := Value;
|
|
ModifiedAfterEnter := True;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.SetItemIndex(Value: Integer);
|
|
var
|
|
ANewEditValue: TcxEditValue;
|
|
APrevItemIndex: Integer;
|
|
begin
|
|
APrevItemIndex := ItemIndex;
|
|
LockClick(True);
|
|
try
|
|
ILookupData.CurrentKey := ItemIndexToLookupKey(Value);
|
|
ANewEditValue := LookupKeyToEditValue(ILookupData.CurrentKey);
|
|
if not VarEqualsExact(EditValue, ANewEditValue) then
|
|
EditValue := ANewEditValue;
|
|
finally
|
|
LockClick(False);
|
|
end;
|
|
if ItemIndex <> APrevItemIndex then
|
|
begin
|
|
EditModified := False;
|
|
Click;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.SynchronizeDisplayValue;
|
|
var
|
|
ADisplayValue, AEditValue: TcxEditValue;
|
|
AIsEditValueValid: Boolean;
|
|
begin
|
|
if ActiveProperties.CanValidate then
|
|
begin
|
|
AEditValue := EditValue;
|
|
AIsEditValueValid := ActiveProperties.IsEditValueValid(AEditValue, InternalFocused);
|
|
if not AIsEditValueValid and not Focused then
|
|
try
|
|
if VarIsDate(EditValue) then
|
|
ADisplayValue := DateTimeToStr(EditValue)
|
|
else
|
|
ADisplayValue := VarToStr(EditValue)
|
|
except
|
|
on EVariantError do
|
|
ADisplayValue := '';
|
|
end
|
|
else
|
|
if AIsEditValueValid then
|
|
PrepareDisplayValue(AEditValue, ADisplayValue, InternalFocused)
|
|
else
|
|
ADisplayValue := ActiveProperties.DefaultFocusedDisplayValue;
|
|
end
|
|
else
|
|
PrepareDisplayValue(EditValue, ADisplayValue, InternalFocused);
|
|
SaveModified;
|
|
FIsDisplayValueSynchronizing := True;
|
|
try
|
|
DataBinding.DisplayValue := ADisplayValue;
|
|
finally
|
|
FIsDisplayValueSynchronizing := False;
|
|
RestoreModified;
|
|
ResetOnNewDisplayValue;
|
|
UpdateDrawValue;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.SynchronizeEditValue;
|
|
var
|
|
APrevEditValue: TcxEditValue;
|
|
ACompareEditValue, AEditValueChanged: Boolean;
|
|
begin
|
|
ACompareEditValue := ActiveProperties.CanCompareEditValue;
|
|
if ACompareEditValue then
|
|
APrevEditValue := EditValue
|
|
else
|
|
APrevEditValue := Null;
|
|
PrepareEditValue(DisplayValue, FEditValue, InternalFocused);
|
|
|
|
if ACompareEditValue then
|
|
AEditValueChanged := not InternalVarEqualsExact(APrevEditValue, FEditValue)
|
|
else
|
|
AEditValueChanged := False;
|
|
if KeyboardAction then
|
|
ModifiedAfterEnter := True
|
|
else
|
|
EditModified := False;
|
|
if AEditValueChanged then
|
|
begin
|
|
DoEditValueChanged;
|
|
if not ActiveProperties.HasDisplayValue then
|
|
DoChange;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.UndoPerformed;
|
|
begin
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.UnlockLookupDataTextChanged;
|
|
begin
|
|
FLookupDataTextChangedLocked := False;
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.UpdateDrawValue;
|
|
|
|
procedure SetTextSelection;
|
|
var
|
|
AEditingStyle: TcxEditEditingStyle;
|
|
begin
|
|
AEditingStyle := ActiveProperties.EditingStyle;
|
|
if AEditingStyle in [esFixedList, esNoEdit] then
|
|
with ViewInfo do
|
|
if (AEditingStyle = esNoEdit) or not FindSelection or not ActiveProperties.FixedListSelection then
|
|
SelLength := 0
|
|
else
|
|
begin
|
|
if DrawSelectionBar then
|
|
begin
|
|
SelStart := 0;
|
|
SelLength := Length(Text) - Self.SelLength;
|
|
SelBackgroundColor := clHighlightText;
|
|
SelTextColor := clHighlight;
|
|
end else
|
|
begin
|
|
SelStart := Self.SelStart;
|
|
SelLength := Self.SelLength;
|
|
SelBackgroundColor := clHighlight;
|
|
SelTextColor := clHighlightText;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
var
|
|
AViewData: TcxCustomTextEditViewData;
|
|
begin
|
|
AViewData := TcxCustomTextEditViewData(CreateViewData);
|
|
try
|
|
AViewData.DisplayValueToDrawValue(DisplayValue, ViewInfo);
|
|
finally
|
|
AViewData.Free;
|
|
end;
|
|
if HandleAllocated then
|
|
begin
|
|
CalculateViewInfo(False);
|
|
SetTextSelection;
|
|
InvalidateRect(Rect(0, 0, Width, Height), False);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.UpdateDisplayValue;
|
|
var
|
|
ADisplayValue: TcxEditValue;
|
|
begin
|
|
if PropertiesChangeLocked then
|
|
Exit;
|
|
|
|
if ActiveProperties.EditingStyle in [esEditList, esFixedList] then
|
|
begin
|
|
if ModifiedAfterEnter and not IsEditValidated or NeedResetInvalidTextWhenPropertiesChanged then
|
|
begin
|
|
ADisplayValue := DisplayValue;
|
|
if not ActiveProperties.IsDisplayValueValid(ADisplayValue, True) then
|
|
begin
|
|
SaveModified;
|
|
DataBinding.DisplayValue := ActiveProperties.DefaultFocusedDisplayValue;
|
|
RestoreModified;
|
|
if not ModifiedAfterEnter then
|
|
SynchronizeEditValue;
|
|
end;
|
|
end
|
|
else
|
|
SynchronizeDisplayValue;
|
|
end
|
|
else
|
|
if not ModifiedAfterEnter then
|
|
DataBinding.UpdateDisplayValue;
|
|
end;
|
|
|
|
function TcxCustomTextEdit.GetCursorPos: Integer;
|
|
begin
|
|
if InnerTextEdit.Control is TcxCustomInnerTextEdit then
|
|
Result := TcxCustomInnerTextEdit(InnerTextEdit.Control).CursorPos
|
|
else
|
|
Result := 0;
|
|
end;
|
|
|
|
function TcxCustomTextEdit.GetEditingText: TCaption;
|
|
begin
|
|
Result := Text;
|
|
end;
|
|
|
|
function TcxCustomTextEdit.GetInnerTextEdit: IcxInnerTextEdit;
|
|
begin
|
|
Result := InnerEdit as IcxInnerTextEdit;
|
|
end;
|
|
|
|
function TcxCustomTextEdit.GetILookupData: IcxTextEditLookupData;
|
|
begin
|
|
Result := FLookupData as IcxTextEditLookupData;
|
|
end;
|
|
|
|
function TcxCustomTextEdit.GetLookupData: TcxCustomTextEditLookupData;
|
|
begin
|
|
Result := TcxCustomTextEditLookupData(FLookupData);
|
|
end;
|
|
|
|
function TcxCustomTextEdit.GetProperties: TcxCustomTextEditProperties;
|
|
begin
|
|
Result := TcxCustomTextEditProperties(FProperties);
|
|
end;
|
|
|
|
function TcxCustomTextEdit.GetActiveProperties: TcxCustomTextEditProperties;
|
|
begin
|
|
Result := TcxCustomTextEditProperties(InternalGetActiveProperties);
|
|
end;
|
|
|
|
function TcxCustomTextEdit.GetSelLength: Integer;
|
|
var
|
|
AEditingStyle: TcxEditEditingStyle;
|
|
begin
|
|
AEditingStyle := ActiveProperties.EditingStyle;
|
|
if (AEditingStyle = esFixedList) and not FindSelection or (AEditingStyle = esNoEdit) then
|
|
Result := 0
|
|
else
|
|
Result := InnerTextEdit.SelLength;
|
|
end;
|
|
|
|
function TcxCustomTextEdit.GetSelStart: Integer;
|
|
var
|
|
AEditingStyle: TcxEditEditingStyle;
|
|
begin
|
|
AEditingStyle := ActiveProperties.EditingStyle;
|
|
if (AEditingStyle = esFixedList) and not FindSelection or (AEditingStyle = esNoEdit) then
|
|
Result := 0
|
|
else
|
|
Result := InnerTextEdit.SelStart;
|
|
end;
|
|
|
|
function TcxCustomTextEdit.GetSelText: TCaption;
|
|
var
|
|
AEditingStyle: TcxEditEditingStyle;
|
|
begin
|
|
AEditingStyle := ActiveProperties.EditingStyle;
|
|
if (AEditingStyle = esFixedList) and not FindSelection or (AEditingStyle = esNoEdit) then
|
|
Result := ''
|
|
else
|
|
Result := InnerTextEdit.SelText;
|
|
end;
|
|
|
|
function TcxCustomTextEdit.GetViewInfo: TcxCustomTextEditViewInfo;
|
|
begin
|
|
Result := TcxCustomTextEditViewInfo(FViewInfo);
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.SetFindSelection(Value: Boolean);
|
|
begin
|
|
if not HandleAllocated or (Value = FindSelection) or FDisableRefresh then
|
|
Exit;
|
|
FFindSelection := Value;
|
|
CalculateViewInfo(False);
|
|
UpdateDrawValue;
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.SetItemObject(Value: TObject);
|
|
begin
|
|
ItemIndex := ActiveProperties.LookupItems.IndexOfObject(Value);
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.SetProperties(Value: TcxCustomTextEditProperties);
|
|
begin
|
|
FProperties.Assign(Value);
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.SetSelLength(Value: Integer);
|
|
begin
|
|
if ActiveProperties.EditingStyle <> esNoEdit then
|
|
InnerTextEdit.SelLength := Value;
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.SetSelStart(Value: Integer);
|
|
begin
|
|
if ActiveProperties.EditingStyle <> esNoEdit then
|
|
InnerTextEdit.SelStart := Value;
|
|
end;
|
|
|
|
{$IFDEF DELPHI12}
|
|
function TcxCustomTextEdit.GetTextHint: string;
|
|
begin
|
|
Result := InnerTextEdit.TextHint;
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.SetTextHint(Value: string);
|
|
begin
|
|
InnerTextEdit.TextHint := Value;
|
|
end;
|
|
{$ENDIF}
|
|
|
|
{$IFDEF CXTEST}
|
|
procedure TcxCustomTextEdit.SetHideInnerEdit(Value: Boolean);
|
|
begin
|
|
if Value <> FHideInnerEdit then
|
|
begin
|
|
FHideInnerEdit := Value;
|
|
PropertiesChanged(ActiveProperties);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.SetShowInnerEdit(Value: Boolean);
|
|
begin
|
|
if Value <> FShowInnerEdit then
|
|
begin
|
|
FShowInnerEdit := Value;
|
|
PropertiesChanged(ActiveProperties);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.SetTesting(Value: Boolean);
|
|
begin
|
|
if Value <> FTesting then
|
|
begin
|
|
FTesting := Value;
|
|
ShortRefreshContainer(False);
|
|
end;
|
|
end;
|
|
{$ENDIF}
|
|
|
|
procedure TcxCustomTextEdit.SetSelText(const Value: TCaption);
|
|
var
|
|
ANewSelStart: Integer;
|
|
ANewText: string;
|
|
APrevKeyboardAction: Boolean;
|
|
begin
|
|
APrevKeyboardAction := KeyboardAction;
|
|
KeyboardAction := Focused or FIsChangeBySpellChecker;
|
|
try
|
|
if CanChangeSelText(Value, ANewText, ANewSelStart) then
|
|
begin
|
|
InternalSetDisplayValue(ANewText);
|
|
SelStart := ANewSelStart;
|
|
end;
|
|
finally
|
|
KeyboardAction := APrevKeyboardAction;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.WMClear(var Message: TMessage);
|
|
begin
|
|
KeyboardAction := True;
|
|
try
|
|
if (not ActiveProperties.ReadOnly) and DataBinding.IsDataAvailable then
|
|
ClearSelection;
|
|
finally
|
|
KeyboardAction := False;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.WMCommand(var Message: TWMCommand);
|
|
begin
|
|
inherited;
|
|
case Message.NotifyCode of
|
|
EN_CHANGE:
|
|
DoTextChanged;
|
|
EN_VSCROLL, EN_HSCROLL:
|
|
DoLayoutChanged;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.WMGetText(var Message: TWMGetText);
|
|
var
|
|
S: string;
|
|
begin
|
|
if Message.TextMax > 0 then
|
|
begin
|
|
if FProperties = nil then
|
|
S := FText
|
|
else
|
|
S := InternalGetText;
|
|
|
|
if Length(S) > Message.TextMax - 1 then
|
|
SetLength(S, Message.TextMax - 1);
|
|
StrLCopy(Message.Text, PChar(S), Message.TextMax - 1);
|
|
Message.Result := Length(S);
|
|
end
|
|
else
|
|
Message.Result := 0;
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.WMGetTextLength(var Message: TWMGetTextLength);
|
|
begin
|
|
if FProperties = nil then
|
|
Message.Result := Length(FText)
|
|
else
|
|
Message.Result := Length(InternalGetText);
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.WMSetFocus(var Message: TWMSetFocus);
|
|
begin
|
|
if HasInnerEdit and not IsInplace then
|
|
InnerControl.HandleNeeded;
|
|
inherited;
|
|
end;
|
|
|
|
procedure TcxCustomTextEdit.WMSetText(var Message: TWMSetText);
|
|
begin
|
|
if FInternalTextSetting then
|
|
inherited
|
|
else
|
|
begin
|
|
Message.Result := 0;
|
|
FInternalTextSetting := True;
|
|
try
|
|
if InternalSetText(string(Message.Text)) then
|
|
Message.Result := 1;
|
|
finally
|
|
FInternalTextSetting := False;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
{ TcxTextEdit }
|
|
|
|
class function TcxTextEdit.GetPropertiesClass: TcxCustomEditPropertiesClass;
|
|
begin
|
|
Result := TcxTextEditProperties;
|
|
end;
|
|
|
|
function TcxTextEdit.GetActiveProperties: TcxTextEditProperties;
|
|
begin
|
|
Result := TcxTextEditProperties(InternalGetActiveProperties);
|
|
end;
|
|
|
|
function TcxTextEdit.GetProperties: TcxTextEditProperties;
|
|
begin
|
|
Result := TcxTextEditProperties(FProperties);
|
|
end;
|
|
|
|
function TcxTextEdit.SupportsSpelling: Boolean;
|
|
begin
|
|
Result := IsTextInputMode;
|
|
end;
|
|
|
|
procedure TcxTextEdit.SetProperties(Value: TcxTextEditProperties);
|
|
begin
|
|
FProperties.Assign(Value);
|
|
end;
|
|
|
|
{ TcxFilterTextEditHelper }
|
|
|
|
class function TcxFilterTextEditHelper.GetFilterEditClass: TcxCustomEditClass;
|
|
begin
|
|
Result := TcxTextEdit;
|
|
end;
|
|
|
|
class procedure TcxFilterTextEditHelper.InitializeProperties(AProperties,
|
|
AEditProperties: TcxCustomEditProperties; AHasButtons: Boolean);
|
|
begin
|
|
inherited InitializeProperties(AProperties, AEditProperties, AHasButtons);
|
|
with TcxCustomTextEditProperties(AProperties) do
|
|
begin
|
|
AutoSelect := True;
|
|
HideSelection := True;
|
|
ViewStyle := vsNormal;
|
|
end;
|
|
end;
|
|
|
|
class procedure TcxFilterTextEditHelper.SetFilterValue(AEdit: TcxCustomEdit;
|
|
AEditProperties: TcxCustomEditProperties; AValue: Variant);
|
|
begin
|
|
AEdit.EditValue := AValue;
|
|
end;
|
|
|
|
initialization
|
|
WM_REDRAWMISSPELLINGS := RegisterWindowMessage('WM_REDRAWMISSPELLINGS');
|
|
WM_SPELLCHECKERAUTOCORRECT := RegisterWindowMessage('WM_SPELLCHECKERAUTOCORRECT');
|
|
GetRegisteredEditProperties.Register(TcxTextEditProperties, scxSEditRepositoryTextItem);
|
|
FilterEditsController.Register(TcxTextEditProperties, TcxFilterTextEditHelper);
|
|
|
|
finalization
|
|
FilterEditsController.Unregister(TcxTextEditProperties, TcxFilterTextEditHelper);
|
|
|
|
end.
|