{********************************************************************} { } { Developer Express Visual Component Library } { ExpressEditors } { } { Copyright (c) 1998-2008 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; 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 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); 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; 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 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 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); 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; procedure InitializeDblClickTimer; function NeadAdjustAlignment: Boolean; procedure UpdateEchoMode; 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; procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER; procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE; procedure EMSetSel(var Message: TMessage); message EM_SETSEL; 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; 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; {$IFDEF DELPHI5} function CanFocus: Boolean; override; {$ENDIF} 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; FHideInnerEdit: Boolean; FInternalTextSetting: Boolean; FIsDisplayValueSynchronizing: Boolean; FLookupItemsScrolling: Boolean; FShowInnerEdit: Boolean; FTesting: Boolean; FText: TCaption; 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 SetHideInnerEdit(Value: Boolean); procedure SetItemObject(Value: TObject); procedure SetProperties(Value: TcxCustomTextEditProperties); procedure SetSelLength(Value: Integer); procedure SetSelStart(Value: Integer); procedure SetShowInnerEdit(Value: Boolean); procedure SetTesting(Value: Boolean); procedure WMClear(var Message: TMessage); message WM_CLEAR; procedure WMGetText(var Message: TWMGetText); message WM_GETTEXT; procedure WMGetTextLength(var Message: TWMGetTextLength); message WM_GETTEXTLENGTH; procedure WMSetText(var Message: TWMSetText); message WM_SETTEXT; protected FInnerEditPositionAdjusting: Boolean; FIsPopupWindowJustClosed: Boolean; FLookupData: TcxInterfacedPersistent; FLookupDataTextChangedLocked: 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 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; // IcxFormatControllerListener procedure FormatChanged; virtual; 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 HideInnerEdit: Boolean read FHideInnerEdit write SetHideInnerEdit; // for test 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 ShowInnerEdit: Boolean read FShowInnerEdit write SetShowInnerEdit; // for test property Testing: Boolean read FTesting write SetTesting; // for test property ViewInfo: TcxCustomTextEditViewInfo read GetViewInfo; 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; 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); 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; 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} cxEditConsts, cxEditUtils, dxThemeConsts, dxThemeManager, cxDWMApi; type TCanvasAccess = class(TCanvas); TControlAccess = class(TControl); TWinControlAccess = class(TWinControl); //TcxEditDataBindingAccess = class(TcxEditDataBinding) 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); ATextRows := nil; cxMakeTextRows(ACanvas.Canvas, PcxCaptionChar(AText), R, ATextParams, ATextRows, ARowCount, AEditSizeProperties.MaxLineCount); if (AEditSizeProperties.MaxLineCount > 0) and (ARowCount > AEditSizeProperties.MaxLineCount) then ARowCount := AEditSizeProperties.MaxLineCount; Result.cy := ARowCount * ACanvas.TextHeight('Zg'); ATextRows := nil; 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); ATextParams := cxCalcTextParams(ACanvas.Canvas, AFlags); ATextRows := nil; cxMakeTextRows(ACanvas.Canvas, PcxCaptionChar(AText), R, ATextParams, ATextRows, ARowCount); if ALineCount > 0 then begin if ARowCount > ALineCount then ARowCount := ALineCount; end else if (AEditSizeProperties.MaxLineCount > 0) and (ARowCount > AEditSizeProperties.MaxLineCount) then ARowCount := AEditSizeProperties.MaxLineCount; if ARowCount = 0 then Result.cx := 0 else Result.cx := cxGetLongestTextRowWidth(ATextRows, ARowCount); ATextRows := nil; 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; TextOutData.TextRows := nil; 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), TextOutData.TextRect, TextOutData.TextParams, TextOutData.TextRows, TextOutData.RowCount, AMaxLineCount); if TextOutData.RowCount <> 0 then begin if (AMaxLineCount > 0) and (TextOutData.RowCount >= AMaxLineCount) then begin TextOutData.RowCount := AMaxLineCount; with TextOutData.TextParams do TextOutData.ForceEndEllipsis := TextOutData.ForceEndEllipsis and EndEllipsis and EditControl and not SingleLine; end else TextOutData.ForceEndEllipsis := False; 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, PcxCaptionChar(Text), R, ATextParams, ATextRows, ARowCount); 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; ATextRows := nil; end; end; procedure InsertThousandSeparator(var S: string); function IsDigitChar(C: Char): Boolean; begin Result := C in ['0'..'9']; end; 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 IsDigitChar(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.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.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; 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; 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; {$IFDEF DELPHI5} function TcxCustomInnerTextEdit.CanFocus: Boolean; begin Result := Container.CanFocusEx; end; {$ENDIF} 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 NeadAdjustAlignment then begin if Focused then Helper.SetAlignment(taLeftJustify) else Helper.SetAlignment(GetBasedAlignment); Container.ShortRefreshContainer(False); 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 NeadAdjustAlignment and (FAlignment <> taLeftJustify) then begin 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 FDblClickTimer.Enabled then Exit; 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; procedure TcxCustomInnerTextEdit.InitializeDblClickTimer; begin FreeAndNil(FDblClickTimer); FDblClickTimer := TcxTimer.Create(Self); with FDblClickTimer do begin Enabled := False; OnTimer := DblClickTimerHandle; Interval := GetDoubleClickTime; end; end; function TcxCustomInnerTextEdit.NeadAdjustAlignment: 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(csDestroying in ComponentState) then begin FDblClickTimer.Enabled := False; AdjustAlignment; 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(csDestroying in ComponentState) then AdjustAlignment; inherited; if not(csDestroying in ComponentState) and (Message.FocusedWnd <> Container.Handle) then Container.FocusChanged; 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 := Size(0, 0); 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 TextOutData.TextRows := nil; 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 GetTextFlags: Integer; begin Result := DrawTextFlags and not(CXTO_CENTER_VERTICALLY or CXTO_BOTTOM) or CXTO_TOP or CXTO_CALCROWCOUNT; end; function IsTextNotFullyVisible(const ARealVisibleBounds: TRect): Boolean; var AFlags: Integer; ARowCount: Integer; ARowText: string; ASize: TSize; ATextRows: TcxTextRows; ATextWidth, ATextBottom: Integer; I, L: Integer; R: TRect; begin ACanvas.Font := Font; AFlags := GetTextFlags; R := TextRect; if not IsMultiLine(AFlags) then R.Right := MaxInt div 2; R.Bottom := MaxInt div 2; ATextRows := nil; Result := not cxMakeTextRows(ACanvas.Canvas, PcxCaptionChar(Text), R, cxCalcTextParams(ACanvas.Canvas, AFlags), ATextRows, ARowCount, MaxLineCount); if not Result then begin L := R.Left; ATextWidth := R.Right - R.Left; ATextBottom := TextRect.Top; for I := 0 to ARowCount - 1 do begin ARowText := TrimRight(Copy(ATextRows[I].Text, 1, ATextRows[I].TextLength)); if ARowText = '' then ASize := Size(0, ACanvas.TextHeight('Zg')) else GetTextExtentPoint32(ACanvas.Handle, PAnsiChar(ARowText), Length(ARowText), ASize); Inc(ATextBottom, ASize.cy); if (ASize.cx > ATextWidth) or (L + ASize.cx > ARealVisibleBounds.Right) or (ATextBottom > ARealVisibleBounds.Bottom) then begin Result := True; Break; end; end; end; 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(GetTextFlags); AText := Text; ATextRect := TextRect; OffsetRect(ATextRect, Left, Top); end; 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 Length(TextRows) - 1 do with 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 if FHideInnerEdit or FShowInnerEdit then begin Result := not FHideInnerEdit and FShowInnerEdit; Exit; end; 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; try AText := DisplayValue; Delete(AText, SelStart + 1, SelLength); APrevSelStart := SelStart; if SetDisplayText(AText) then SelStart := APrevSelStart; finally KeyboardAction := APrevKeyboardAction; end; 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 case Key of #8: 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; #32..#255: 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.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.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; 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.SetHideInnerEdit(Value: Boolean); begin if Value <> FHideInnerEdit then begin FHideInnerEdit := Value; PropertiesChanged(ActiveProperties); end; 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; 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; procedure TcxCustomTextEdit.SetSelText(const Value: TCaption); var ANewSelStart: Integer; ANewText: string; APrevKeyboardAction: Boolean; begin APrevKeyboardAction := KeyboardAction; KeyboardAction := Focused; 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.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.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; 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 GetRegisteredEditProperties.Register(TcxTextEditProperties, scxSEditRepositoryTextItem); FilterEditsController.Register(TcxTextEditProperties, TcxFilterTextEditHelper); finalization FilterEditsController.Unregister(TcxTextEditProperties, TcxFilterTextEditHelper); end.