lazarus-ccr/components/orpheus/ovcef.pas
2012-09-04 01:19:06 +00:00

4767 lines
130 KiB
ObjectPascal

{*********************************************************}
{* OVCEF.PAS 4.06 *}
{*********************************************************}
{* ***** BEGIN LICENSE BLOCK ***** *}
{* Version: MPL 1.1 *}
{* *}
{* The contents of this file are subject to the Mozilla Public License *}
{* Version 1.1 (the "License"); you may not use this file except in *}
{* compliance with the License. You may obtain a copy of the License at *}
{* http://www.mozilla.org/MPL/ *}
{* *}
{* Software distributed under the License is distributed on an "AS IS" basis, *}
{* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License *}
{* for the specific language governing rights and limitations under the *}
{* License. *}
{* *}
{* The Original Code is TurboPower Orpheus *}
{* *}
{* The Initial Developer of the Original Code is TurboPower Software *}
{* *}
{* Portions created by TurboPower Software Inc. are Copyright (C)1995-2002 *}
{* TurboPower Software Inc. All Rights Reserved. *}
{* *}
{* Contributor(s): *}
{* *}
{* ***** END LICENSE BLOCK ***** *}
{$I OVC.INC}
{$B-} {Complete Boolean Evaluation}
{$I+} {Input/Output-Checking}
{$P+} {Open Parameters}
{$T-} {Typed @ Operator}
{.W-} {Windows Stack Frame}
{$X+} {Extended Syntax}
unit ovcef;
{-Base entry field class}
interface
uses
{$IFNDEF LCL} Windows, Messages, {$ELSE} LclIntf, LMessages, Types, LclType, MyMisc, {$ENDIF}
Classes, ClipBrd, Controls, Forms, Graphics, Menus,
SysUtils, {$IFDEF VERSION6} Variants, {$ENDIF}
OvcBase, OvcCaret, OvcColor, OvcConst, OvcCmd, OvcData, OvcExcpt,
OvcIntl, OvcMisc, OvcStr, OvcUser, OvcDate, OvcBordr;
type
{user validation event}
TUserValidationEvent =
procedure(Sender : TObject; var ErrorCode : Word)
of object;
TValidationErrorEvent =
procedure(Sender : TObject; ErrorCode : Word; ErrorMsg : string)
of object;
{options available to specific fields}
TOvcEntryFieldOption = (efoArrowIncDec, efoCaretToEnd, efoForceInsert,
efoForceOvertype, efoInputRequired,
efoPasswordMode, efoReadOnly, efoRightAlign,
efoRightJustify, efoSoftValidation,
efoStripLiterals, efoTrimBlanks);
TOvcEntryFieldOptions = set of TOvcEntryFieldOption;
const
efDefOptions = [efoCaretToEnd, efoTrimBlanks];
type
{combined color class}
TOvcEfColors = class(TPersistent)
protected {private}
FDisabled : TOvcColors; {colors for disabled fields}
FError : TOvcColors; {colors for invalid fields}
FHighlight : TOvcColors; {background and text highlight colors}
public
procedure Assign(Source : TPersistent); override;
constructor Create; virtual;
destructor Destroy; override;
published
property Disabled : TOvcColors read FDisabled write FDisabled;
property Error : TOvcColors read FError write FError;
property Highlight : TOvcColors read FHighlight write FHighlight;
end;
{abstract entry field class}
TOvcBaseEntryField = class(TOvcCustomControlEx)
{.Z+}
protected {private}
{property instance variables}
FAutoSize : Boolean; {size control when font changes}
FBorders : TOvcBorders; {simple line borders}
FBorderStyle : TBorderStyle; {border around the edit field}
FCtrlColor : TColor; {control character foreground color}
FDecimalPlaces : Byte; {max decimal places, if no '.' in Picture}
FEFColors : TOvcEfColors; {entry field colors}
FEpoch : Integer; {combined epoch year and cenury}
FIntlSup : TOvcIntlSup; {international support object}
FLastError : Word; {result of last validation}
FMaxLength : Word; {maximum length of string}
FOptions : TOvcEntryFieldOptions;
FPadChar : AnsiChar; {character used to pad end of string}
FPasswordChar : AnsiChar; {character used in password mode}
FTextMargin : Integer; {indent from left (right)}
FUninitialized : Boolean; {the field isblanked out completely except when it has the focus}
FUserData : TOvcUserData; {field mask and data object}
FZeroDisplay : TZeroDisplay; {true to display an empty field}
FZeroDisplayValue : Double; {value used by ZeroDisplay logic}
{$IFDEF LCL}
FCtl3D : Boolean;
{$ENDIF}
{event variables}
FOnChange : TNotifyEvent;
FOnError : TValidationErrorEvent;
FOnGetEpoch : TGetEpochEvent;
FOnUserCommand : TUserCommandEvent;
FOnUserValidation : TUserValidationEvent;
{internal variables}
efCaret : TOvcCaretPair; {our carets}
efDataSize : Word; {size of data type being edited}
efDataType : Byte; {code indicating field type}
efEditSt : TEditString; {the edit string}
efFieldClass : Byte; {fcSimple, fcPicture, or fcNumeric}
efHOffset : Integer; {horizontal scrolling offset}
efHPos : Integer; {current position in field (column)}
efPicLen : Word; {length of picture mask}
efPicture : TPictureMask; {picture mask}
efRangeHi : TRangeType; {high range for the field}
efRangeLo : TRangeType; {low range for the field}
efRightAlignActive : Boolean; {true if right-align is in use}
efSaveData : Boolean; {save data during create window}
efSaveEdit : PAnsiChar; {saved copy of edit string}
efSelStart : Integer; {start of highlighted selection}
efSelEnd : Integer; {end of highlighted selection}
efTopMargin : Integer; {margin above text}
sefOptions : TsefOptionSet; {secondary field options}
{property methods}
function GetAsBoolean : Boolean;
function GetAsCents : LongInt;
function GetAsExtended : Extended;
function GetAsFloat : Double;
function GetAsInteger : Longint;
function GetAsDateTime : TDateTime;
function GetAsStDate : TStDate;
function GetAsStTime : TStTime;
function GetAsString : string;
function GetAsVariant : Variant;
function GetCurrentPos : Integer;
function GetDataSize : Word;
function GetDisplayString : string;
function GetEditString : string;
function GetEpoch : Integer;
function GetEverModified : Boolean;
function GetInsCaretType : TOvcCaret;
function GetInsertMode : Boolean;
function GetModified : Boolean;
function GetOvrCaretType : TOvcCaret;
function GetRangeHiStr : string;
function GetRangeLoStr : string;
function GetSelLength : Integer;
function GetSelStart : Integer;
function GetSelText : string;
procedure SetAsBoolean(Value : Boolean);
procedure SetAsCents(Value : LongInt);
procedure SetAsDateTime(Value : TDateTime);
procedure SetAsExtended(Value : Extended);
procedure SetAsFloat(Value : Double);
procedure SetAsInteger(Value : Longint);
procedure SetAsStDate(Value : TStDate);
procedure SetAsStTime(Value : TStTime);
procedure SetAsVariant(Value : Variant);
procedure SetAutoSize(Value : Boolean); {$IFDEF VERSION6}{$IFNDEF LCL} override;{$ENDIF}{$ENDIF}
procedure SetBorderStyle(Value : TBorderStyle);
procedure SetDecimalPlaces(Value : Byte);
procedure SetEpoch(Value : Integer);
procedure SetEverModified(Value : Boolean);
procedure SetInsCaretType(const Value : TOvcCaret);
procedure SetInsertMode(Value : Boolean);
procedure SetIntlSupport(Value : TOvcIntlSup);
procedure SetMaxLength(Value : Word);
procedure SetModified(Value : Boolean);
procedure SetOptions(Value : TOvcEntryFieldOptions);
procedure SetOvrCaretType(const Value : TOvcCaret);
procedure SetPadChar(Value : AnsiChar);
procedure SetPasswordChar(Value : AnsiChar);
procedure SetRangeLoStr(const Value : string);
procedure SetRangeHiStr(const Value : string);
procedure SetSelLength(Value : Integer);
procedure SetSelStart(Value : Integer);
procedure SetSelText(const Value : string);
procedure SetTextMargin(Value : Integer);
procedure SetUninitialized(Value : Boolean);
procedure SetUserData(Value : TOvcUserData);
procedure SetZeroDisplay(Value : TZeroDisplay);
procedure SetZeroDisplayValue(Value : Double);
{internal methods}
procedure efBorderChanged(ABorder : TObject);
procedure efCalcTopMargin;
procedure efColorChanged(AColor : TObject);
function efGetTextExtent(S : PChar; Len : Integer) : Word;
procedure efInitializeDataSize;
{ - HWnd changed to TOvcHWnd for BCB Compatibility }
function efIsSibling(HW : TOvcHWnd{hWnd}) : Boolean;
procedure efMoveFocus(C : TWinControl);
procedure efPaintBorders;
procedure efPerformEdit(var Msg : TMessage; Cmd : Word);
procedure efPerformPreEditNotify(C : TWinControl);
procedure efPerformPostEditNotify(C : TWinControl);
procedure efReadRangeHi(Stream : TStream);
procedure efReadRangeLo(Stream : TStream);
function efTransferPrim(DataPtr : Pointer; TransferFlag : Word) : Word;
procedure efWriteRangeHi(Stream : TStream);
procedure efWriteRangeLo(Stream : TStream);
{VCL control methods}
{$IFNDEF LCL}
procedure CMCtl3DChanged(var Msg : TMessage);
message CM_CTL3DCHANGED;
{$ENDIF}
procedure CMDialogChar(var Msg : TCMDialogChar);
message CM_DIALOGCHAR;
procedure CMEnabledChanged(var Msg : TMessage);
message CM_ENABLEDCHANGED;
procedure CMFontChanged(var Msg : TMessage);
message CM_FONTCHANGED;
{private message response methods}
procedure OMGetDataSize(var Msg : TMessage);
message OM_GETDATASIZE;
procedure OMReportError(var Msg : TOMReportError);
message OM_REPORTERROR;
{windows message response methods}
procedure WMChar(var Msg : TWMChar);
message WM_CHAR;
procedure WMClear(var Msg : TWMClear);
message WM_CLEAR;
procedure WMCopy(var Msg : TWMCopy);
message WM_COPY;
procedure WMCut(var Msg : TWMCut);
message WM_CUT;
procedure WMEraseBkGnd(var Msg : TWMEraseBkGnd);
message WM_ERASEBKGND;
procedure WMGetDlgCode(var Msg : TWMGetDlgCode);
message WM_GETDLGCODE;
procedure WMKeyDown(var Msg : TWMKeyDown);
message WM_KEYDOWN;
procedure WMKillFocus(var Msg : TWMKillFocus);
message WM_KILLFOCUS;
procedure WMLButtonDblClk(var Msg : TWMLButtonDblClk);
message WM_LBUTTONDBLCLK;
procedure WMLButtonDown(var Msg : TWMLButtonDown);
message WM_LBUTTONDOWN;
procedure WMMouseActivate(var Msg : TWMMouseActivate);
message WM_MOUSEACTIVATE;
procedure WMMouseMove(var Msg : TWMMouseMove);
message WM_MOUSEMOVE;
procedure WMPaste(var Msg : TWMPaste);
message WM_PASTE;
procedure WMRButtonUp(var Msg : TWMRButtonDown);
message WM_RBUTTONUP;
procedure WMSetFocus(var Msg : TWMSetFocus);
message WM_SETFOCUS;
procedure WMSetFont(var Msg : TWMSetFont);
message WM_SETFONT;
procedure WMSetText(var Msg : TWMSetText);
message WM_SETTEXT;
procedure WMSize(var Msg : TWMSize);
message WM_SIZE;
procedure WMSysKeyDown(var Msg : TWMSysKeyDown);
message WM_SYSKEYDOWN;
{edit control message methods}
procedure EMGetModify(var Msg : TMessage);
message EM_GETMODIFY;
procedure EMGetSel(var Msg : TMessage);
message EM_GETSEL;
procedure EMSetModify(var Msg : TMessage);
message EM_SETMODIFY;
procedure EMSetSel(var Msg : TMessage);
message EM_SETSEL;
protected
{VCL methods}
procedure CreateParams(var Params : TCreateParams);
override;
procedure CreateWnd;
override;
procedure DefineProperties(Filer : TFiler);
override;
procedure Paint;
override;
{dynamic event wrappers}
procedure DoOnChange;
dynamic;
{-perform notification of a change}
procedure DoOnError(ErrorCode : Word; const ErrorMsg : string);
dynamic;
{-perform notification of an error}
procedure DoOnUserCommand(Command : Word);
dynamic;
{-perform notification of a user command}
procedure DoOnUserValidation(var ErrorCode : Word);
dynamic;
{-perform call to user validation event handler}
procedure DoRestoreClick(Sender : TObject);
dynamic;
procedure DoCutClick(Sender : TObject);
dynamic;
procedure DoCopyClick(Sender : TObject);
dynamic;
procedure DoPasteClick(Sender : TObject);
dynamic;
procedure DoDeleteClick(Sender : TObject);
dynamic;
procedure DoSelectAllClick(Sender : TObject);
dynamic;
procedure efAdjustSize;
dynamic;
{-adjust the size of the control based on the current font}
function efCanClose(DoValidation : Boolean) : Boolean;
virtual;
{-returns true if the field contents are valid}
procedure efCaretToEnd;
virtual;
{-move the caret to the end of the field}
procedure efCaretToStart;
virtual;
{-move the caret to the beginning of the field}
procedure efChangeMask(Mask : PAnsiChar);
dynamic;
{-change the picture mask}
function efCharOK(PicChar : AnsiChar; var Ch : AnsiChar;
PrevCh : AnsiChar; Fix : Boolean) : Boolean;
{-return True if Ch is in character set corresponding to PicChar}
procedure efConditionalBeep;
{-beep if pefBeepOnError option is active}
procedure efCopyPrim;
{-Primitive clipboard copy method}
function efBinStr2Long(St : PAnsiChar; var L : LongInt) : Boolean;
{-convert a binary string to a longint}
function efCalcDataSize(St : PAnsiChar; MaxLen : Word) : Word;
{-calculate data size of a string field with literal stripping option on}
procedure efEdit(var Msg : TMessage; Cmd : Word);
virtual; abstract;
{-process the specified editing command}
function efEditBegin : Word;
virtual;
{-return offset of first editable position in field}
function efFieldIsEmpty : Boolean;
virtual;
{-return True if the field is empty}
procedure efFieldModified;
{-mark the field as modified; tell parent form it changed}
procedure efFindCtrlChars(P : PAnsiChar; var ChCnt, CtCnt : Integer);
{-find control caracters and return normal and control char counts}
procedure efFixCase(PicChar : AnsiChar; var Ch : AnsiChar; PrevCh : AnsiChar);
{-fix the case of Ch based on PicChar}
function efGetDisplayString(Dest : PAnsiChar; Size : Word) : PAnsiChar;
virtual;
{-return the display string in Dest and a pointer as the result}
function efGetMousePos(MPos : Integer) : Integer;
{-get the position of a mouse click}
procedure efGetSampleDisplayData(T : PAnsiChar);
dynamic;
{-return sample data for the current field type}
procedure efIncDecValue(Wrap : Boolean; Delta : Double);
dynamic; abstract;
{-increment field by Delta}
function efIsNumericType : Boolean;
{-return True if field is of a numeric type}
function efIsReadOnly : Boolean;
virtual;
{-return True if field is read-only}
procedure efLong2Str(P : PAnsiChar; L : LongInt);
{-convert a longint to a string}
procedure efMapControlChars(Dest, Src : PAnsiChar);
{-copy from Src to Dest, mapping control characters to alph in process}
procedure efMoveFocusToNextField;
dynamic;
{-give next field the focus}
procedure efMoveFocusToPrevField;
dynamic;
{-give previous field the focus}
function efNthMaskChar(N : Word) : AnsiChar;
{-return the N'th character in the picture mask. N is 0-based}
function efOctStr2Long(St : PAnsiChar; var L : LongInt) : Boolean;
{-convert an octal string to a longint}
{ - Hdc changed to TOvcHdc for BCB Compatibility }
procedure efPaintPrim(DC : TOvcHDC{Hdc}; ARect : TRect; Offset : Integer);
{-primitive routine to draw the entry field control}
procedure efPerformRepaint(Modified : Boolean);
{-flag the field as modified and redraw it}
function efPositionCaret(Adjust : Boolean) : Boolean;
{-position the editing caret}
function efRangeToStRange(const Value : TRangeType) : string;
{-returns the range as a string}
function efStRangeToRange(const Value : string; var R : TRangeType) : Boolean;
{-converts a string range to a RangeType}
procedure efRemoveBadOptions;
virtual;
{-remove inappropriate options for this field and data type}
procedure efResetCaret;
virtual;
{-move the caret to the beginning or end of the field, as appropriate}
procedure efSaveEditString;
{-save a copy of the edit string}
procedure efSetDefaultRange(FT : Byte);
{-set the default range for the given field type}
procedure efSetInitialValue;
{-set the initial value of the field}
function efStr2Long(P : PAnsiChar; var L : LongInt) : Boolean;
{-convert a string to a longint}
function efTransfer(DataPtr : Pointer; TransferFlag : Word) : Word;
virtual;
{-transfer data to/from the entry fields}
function efValidateField : Word;
virtual; abstract;
{-validate contents of field; result is error code or 0}
{virtual property methods}
procedure efSetCaretPos(Value : Integer);
virtual;
{-set position of the caret within the field}
procedure SetAsString(const Value : string);
virtual;
{-sets the field value to a String Value}
procedure SetName(const Value : TComponentName);
override;
{-catch when component name is changed}
public
constructor Create(AOwner : TComponent);
override;
destructor Destroy;
override;
procedure SetBounds(ALeft, ATop, AWidth, AHeight : Integer);
override;
{.Z-}
procedure ClearContents;
{-clear the contents of the entry field}
procedure ClearSelection;
{-erase the highlighted text}
procedure CopyToClipboard;
{-copies the highlighted text to the clipboard}
procedure CutToClipboard;
dynamic;
{-performs a CopyToClipboard then deletes the highlighted text from the field}
procedure DecreaseValue(Wrap : Boolean; Delta : Double);
{-decrease the value of the field by Delta, wrapping if enabled}
procedure Deselect;
{-unhighlight any highlighted text}
function FieldIsEmpty : Boolean;
{-return True if the field is completely empty}
function GetStrippedEditString : string;
dynamic;
{-return edit string stripped of literals and semi-literals}
function GetValue(var Data) : Word;
{-returns the current field value in Data. Result is 0 or error code}
procedure IncreaseValue(Wrap : Boolean; Delta : Double);
{-increase the value of the field by Delta, wrapping if enabled}
function IsValid : Boolean;
{-returns true if the field is not marked as invalid}
procedure MergeWithPicture(const S : string);
dynamic;
{-combines S with the picture mask and updates the edit string}
procedure MoveCaret(Delta : Integer);
{-moves the caret to the right or left Value positions}
procedure MoveCaretToEnd;
{-move the caret to the end of the field}
procedure MoveCaretToStart;
{-move the caret to the beginning of the field}
procedure PasteFromClipboard;
dynamic;
{-places the text content of the clipboard into the field}
procedure ProcessCommand(Cmd, CharCode : Word);
{-process the specified command}
procedure ResetCaret;
{-move the caret to the beginning or end of the field, as appropriate}
procedure Restore;
dynamic;
{-restore the previous contents of the field}
procedure SelectAll;
{-selects the current edit text}
procedure SetInitialValue;
{-resets the field value to its initial value}
procedure SetRangeHi(const Value : TRangeType);
{-set the high range for this field}
procedure SetRangeLo(const Value : TRangeType);
{-set the low range for this field}
procedure SetSelection(Start, Stop : Word);
{-mark offsets Start..Stop as selected}
procedure SetValue(const Data);
{-changes the field's value to the value in Data}
function ValidateContents(ReportError : Boolean) : Word;
dynamic;
{-performs field validation, returns error code, and conditionally reports error}
function ValidateSelf : Boolean;
{-performs field validation, returns true if no errors, and reports error}
{public properties}
property ParentColor default False;
property AsBoolean : Boolean
read GetAsBoolean write SetAsBoolean;
property AsCents : LongInt
read GetAsCents write SetAsCents;
property AsDateTime : TDateTime
read GetAsDateTime write SetAsDateTime;
property AsExtended : Extended
read GetAsExtended write SetAsExtended;
property AsFloat : Double
read GetAsFloat write SetAsFloat;
property AsInteger : Longint
read GetAsInteger write SetAsInteger;
property AsOvcDate : TOvcDate
read GetAsStDate write SetAsStDate;
property AsOvcTime : TOvcTime
read GetAsStTime write SetAsStTime;
property AsString : string
read GetAsString write SetAsString;
property AsVariant : Variant
read GetAsVariant write SetAsVariant;
property AsStDate : TStDate
read GetAsStDate write SetAsStDate;
property AsStTime : TStTime
read GetAsStTime write SetAsStTime;
property Font;
property Canvas;
property Color;
property CurrentPos : Integer
read GetCurrentPos write efSetCaretPos;
property DataSize : Word
read GetDataSize;
property DisplayString : string
read GetDisplayString;
property EditString : string
read GetEditString;
property Epoch : Integer
read GetEpoch write SetEpoch;
property EverModified : Boolean
read GetEverModified write SetEverModified;
{.Z+}
property InsertMode : Boolean
read GetInsertMode write SetInsertMode;
{.Z-}
property IntlSupport : TOvcIntlSup
read FIntlSup write SetIntlSupport;
property LastError : Word
read FLastError;
property Modified : Boolean
read GetModified write SetModified;
property SelectionLength : Integer
read GetSelLength write SetSelLength;
property SelectionStart : Integer
read GetSelStart write SetSelStart;
property SelectedText : string
read GetSelText write SetSelText;
property Text : string
read GetAsString write SetAsString;
property UserData : TOvcUserData
read FUserData write SetUserData;
{publishable properties}
{revised}
property AttachedLabel : TOvcAttachedLabel
read GetAttachedLabel;
property AutoSize : Boolean
read FAutoSize write SetAutoSize default True;
property Borders : TOvcBorders
read FBorders write FBorders;
property BorderStyle : TBorderStyle
read FBorderStyle write SetBorderStyle default bsSingle;
property CaretIns : TOvcCaret
read GetInsCaretType write SetInsCaretType;
property CaretOvr : TOvcCaret
read GetOvrCaretType write SetOvrCaretType;
property ControlCharColor : TColor
read FCtrlColor write FCtrlColor;
property DecimalPlaces : Byte
read FDecimalPlaces write SetDecimalPlaces;
property EFColors : TOvcEfColors
read FEFColors write FEFColors;
property MaxLength : Word
read FMaxLength write SetMaxLength default 15;
property Options : TOvcEntryFieldOptions
read FOptions write SetOptions default efDefOptions;
property PadChar : AnsiChar
read FPadChar write SetPadChar default DefPadChar;
property PasswordChar : AnsiChar
read FPasswordChar write SetPasswordChar default '*';
property RangeHi : string
read GetRangeHiStr write SetRangeHiStr stored False;
property RangeLo : string
read GetRangeLoStr write SetRangeLoStr stored False;
property TextMargin : Integer
read FTextMargin write SetTextMargin default 2;
property Uninitialized : Boolean
read FUninitialized write SetUninitialized default False;
property ZeroDisplay : TZeroDisplay
read FZeroDisplay write SetZeroDisplay default zdShow;
property ZeroDisplayValue : Double
read FZeroDisplayValue write SetZeroDisplayValue;
{$IFDEF LCL}
property Ctl3D : Boolean read FCtl3D write FCtl3D default True;
{$ENDIF}
{events}
property OnChange : TNotifyEvent
read FOnChange write FOnChange;
property OnError : TValidationErrorEvent
read FOnError write FOnError;
property OnGetEpoch : TGetEpochEvent
read FOnGetEpoch write FOnGetEpoch;
property OnUserCommand : TUserCommandEvent
read FOnUserCommand write FOnUserCommand;
property OnUserValidation : TUserValidationEvent
read FOnUserValidation write FOnUserValidation;
end;
implementation
{*** TOvcEfColors ***}
procedure TOvcEfColors.Assign(Source : TPersistent);
var
C : TOvcEfColors absolute Source;
begin
if (Source <> nil) and (Source is TOvcEfColors) then begin
FDisabled.Assign(C.Disabled);
FError.Assign(C.Error);
FHighlight.Assign(C.Highlight);
end else
inherited Assign(Source);
end;
constructor TOvcEfColors.Create;
begin
inherited Create;
{create color objects and assign defaults}
FDisabled := TOvcColors.Create(clGrayText, clWindow);
FError := TOvcColors.Create(clBlack, clRed);
FHighlight := TOvcColors.Create(clHighlightText, clHighlight);
end;
destructor TOvcEfColors.Destroy;
begin
{dispose of the color objects}
FDisabled.Free;
FError.Free;
FHighlight.Free;
inherited Destroy;
end;
{*** TOvcBaseEntryField ***}
procedure TOvcBaseEntryField.ClearContents;
{-erases the contents of the edit field}
var
RO : Boolean;
begin
if HandleAllocated then begin
RO := efoReadOnly in Options; {store current read only state}
Exclude(FOptions, efoReadOnly);
{set the updating flag so OnChange doesn't get fired}
Include(sefOptions, sefUpdating);
SetWindowText(Handle, '');
Exclude(sefOptions, sefUpdating);
{restore previous state}
if RO then
Include(FOptions, efoReadOnly);
end;
end;
procedure TOvcBaseEntryField.ClearSelection;
begin
if HandleAllocated then
Perform(WM_CLEAR, 0, 0);
end;
{$IFNDEF LCL}
procedure TOvcBaseEntryField.CMCtl3DChanged(var Msg : TMessage);
begin
if not HandleAllocated then
Exit;
if NewStyleControls and (FBorderStyle = bsSingle) then begin
{$IFNDEF LCL}
RecreateWnd;
{$ELSE}
MyMisc.RecreateWnd(Self);
{$ENDIF}
if not (csLoading in ComponentState) then
efAdjustSize;
end;
efCalcTopMargin;
inherited;
end;
{$ENDIF}
procedure TOvcBaseEntryField.CMDialogChar(var Msg : TCMDialogChar);
begin
{see if this is an Alt-Backspace key sequence (Alt flag is bit 29}
if (Msg.CharCode = VK_BACK) and (HiWord(Msg.KeyData) and $2000 <> 0) then
{don't pass it on as a dialog character since we use it as}
{the restore command by default}
Msg.Result := 1;
inherited;
end;
procedure TOvcBaseEntryField.CMEnabledChanged(var Msg : TMessage);
begin
inherited;
Repaint;
end;
procedure TOvcBaseEntryField.CMFontChanged(var Msg : TMessage);
begin
inherited;
if (csLoading in ComponentState) then
Exit;
if not HandleAllocated then
Exit;
{efCalcTopMargin;}
efAdjustSize; {adjust height based on font}
efCalcTopMargin;
if GetFocus = Handle then
efPositionCaret(False); {adjust caret for new font}
end;
procedure TOvcBaseEntryField.CopyToClipboard;
{-copies the selected text to the clipboard}
begin
if HandleAllocated then
Perform(WM_COPY, 0, 0);
end;
constructor TOvcBaseEntryField.Create(AOwner : TComponent);
const
CStyle = [csClickEvents, csCaptureMouse, csOpaque];
begin
inherited Create(AOwner);
if NewStyleControls then
ControlStyle := ControlStyle + CStyle
else
ControlStyle := ControlStyle + CStyle + [csFramed];
// TurboPower bug: forgot to enable XP theme support.
ControlStyle := ControlStyle + [csNeedsBorderPaint]; //Added
{create borders class and assign notifications}
FBorders := TOvcBorders.Create;
FBorders.LeftBorder.OnChange := efBorderChanged;
FBorders.RightBorder.OnChange := efBorderChanged;
FBorders.TopBorder.OnChange := efBorderChanged;
FBorders.BottomBorder.OnChange := efBorderChanged;
Cursor := crIBeam;
Height := 25;
ParentColor := False;
Width := 130;
TabStop := True;
{defaults}
FAutoSize := True;
FBorderStyle := bsSingle;
FCtrlColor := clRed;
FDecimalPlaces := 0;
FMaxLength := 15;
FOptions := efDefOptions;
FPadChar := DefPadChar;
FPasswordChar := '*';
FTextMargin := 2;
FUninitialized := False;
FZeroDisplay := zdShow;
FZeroDisplayValue := 0;
{$IFDEF LCL}
FCtl3D := True;
Color := clWindow;
{$ENDIF}
efRangeLo := BlankRange;
efRangeHi := BlankRange;
{default picture and field settings}
efPicture[0] := 'X';
efPicture[1] := #0;
efPicLen := 1;
efFieldClass := fcSimple;
efDataType := fidSimpleString;
{assign default user data object}
FUserData := OvcUserData;
{assign default international support object}
FIntlSup := OvcIntlSup;
{create the caret class}
efCaret := TOvcCaretPair.Create(Self);
{init edit and save edit strings}
FillChar(efEditSt, MaxEditLen, #0);
efSaveEdit := nil;
{create colors class}
FEFColors := TOvcEfColors.Create;
{assign color change notification methods}
FEFColors.FDisabled.OnColorChange := efColorChanged;
FEFColors.FError.OnColorChange := efColorChanged;
FEFColors.FHighlight.OnColorChange := efColorChanged;
efCalcTopMargin;
end;
procedure TOvcBaseEntryField.CreateParams(var Params : TCreateParams);
begin
inherited CreateParams(Params);
Params.Style := LongInt(Params.Style) or BorderStyles[FBorderStyle];
if NewStyleControls and Ctl3D and (FBorderStyle = bsSingle) then begin
Params.Style := Params.Style and not WS_BORDER;
Params.ExStyle := Params.ExStyle or WS_EX_CLIENTEDGE;
end;
{set picture length and check MaxLength}
efPicLen := StrLen(efPicture);
if FMaxLength = 0 then
FMaxLength := efPicLen;
{reset secondary options}
sefOptions := sefDefOptions;
{$IFDEF LCL}
inherited SetBorderStyle(FBorderStyle);
{$ENDIF}
end;
procedure TOvcBaseEntryField.CreateWnd;
begin
inherited CreateWnd;
efHOffset := 0;
efHPos := 0;
efSelStart := 0;
efSelEnd := 0;
{set efDataSize for this field type}
efInitializeDataSize;
{if input is required then these fields must also be uninitialized}
if efoInputRequired in Options then
case efDataType mod fcpDivisor of
fsubChar, fsubBoolean, fsubYesNo, fsubLongInt,
fsubWord, fsubInteger, fsubByte, fsubShortInt,
fsubReal, fsubExtended, fsubDouble, fsubSingle,
fsubComp : Uninitialized := True;
end;
{is it a hex, binary, octal, and/or numeric field?}
if StrScan(efPicture, pmHexadecimal) <> nil then
Include(sefOptions, sefHexadecimal)
else
Exclude(sefOptions, sefHexadecimal);
if StrScan(efPicture, pmBinary) <> nil then
Include(sefOptions, sefBinary)
else
Exclude(sefOptions, sefBinary);
if StrScan(efPicture, pmOctal) <> nil then
Include(sefOptions, sefOctal)
else
Exclude(sefOptions, sefOctal);
if efFieldClass = fcNumeric then
Include(sefOptions, sefNumeric)
else
Exclude(sefOptions, sefNumeric);
{assume no literals in mask}
Include(sefOptions, sefNoLiterals);
{reject bad options}
efRemoveBadOptions;
{set canvas font to selected font}
Canvas.Font := Font;
efAdjustSize; {adjust height based on font}
efCalcTopMargin;
efRightAlignActive := efoRightAlign in Options;
end;
procedure TOvcBaseEntryField.CutToClipboard;
{-erases the selected text and places it in the clipboard}
begin
if HandleAllocated then
Perform(WM_CUT, 0, 0);
end;
procedure TOvcBaseEntryField.DefineProperties(Filer : TFiler);
var
Save : Boolean;
begin
inherited DefineProperties(Filer);
Save := not (efDataType mod fcpDivisor in [fsubString, fsubBoolean, fsubYesNo]);
Filer.DefineBinaryProperty('RangeHigh', efReadRangeHi, efWriteRangeHi, Save);
Filer.DefineBinaryProperty('RangeLow', efReadRangeLo, efWriteRangeLo, Save);
end;
procedure TOvcBaseEntryField.DecreaseValue(Wrap : Boolean; Delta : Double);
{-decrease the value of the field by Delta, wrapping if enabled}
begin
SendMessage(Handle, WM_SETREDRAW, 0, 0);
efIncDecValue(Wrap, -Delta);
SetSelection(0, 0);
SendMessage(Handle, WM_SETREDRAW, 1, 0);
Refresh;
end;
procedure TOvcBaseEntryField.Deselect;
{-unhighlight any highlighted text}
begin
SetSelection(0, 0);
end;
destructor TOvcBaseEntryField.Destroy;
var
PF : TCustomForm;
begin
if Focused then begin
PF := GetParentForm(Self);
PF.DefocusControl(Self, True);
end;
{dispose of the caret object}
efCaret.Free;
{dispose of the color object}
FEFColors.Free;
{dispose the borders object}
FBorders.Free;
{dispose of the saved edit string}
if efSaveEdit <> nil then
StrDispose(efSaveEdit);
inherited Destroy;
end;
procedure TOvcBaseEntryField.DoOnChange;
{-perform notification of a change}
begin
if Assigned(FOnChange) and not (sefUpdating in sefOptions) then
FOnChange(Self);
end;
procedure TOvcBaseEntryField.DoOnError(ErrorCode : Word; const ErrorMsg : string);
begin
if Assigned(FOnError) then
FOnError(Self, ErrorCode, ErrorMsg)
else
Controller.DoOnError(Self, ErrorCode, ErrorMsg);
end;
procedure TOvcBaseEntryField.DoOnUserCommand(Command : Word);
{-perform notification of a user command}
begin
if Assigned(FOnUserCommand) then
FOnUserCommand(Self, Command);
end;
procedure TOvcBaseEntryField.DoOnUserValidation(var ErrorCode : Word);
{-perform call to user validation event handler}
begin
if Assigned(FOnUserValidation) then
if not (sefNoUserValidate in sefOptions) then
FOnUserValidation(Self, ErrorCode);
end;
procedure TOvcBaseEntryField.DoRestoreClick(Sender : TObject);
begin
Restore;
efPositionCaret(True);
end;
procedure TOvcBaseEntryField.DoCutClick(Sender : TObject);
begin
CutToClipboard
end;
procedure TOvcBaseEntryField.DoCopyClick(Sender : TObject);
begin
CopyToClipboard;
end;
procedure TOvcBaseEntryField.DoPasteClick(Sender : TObject);
begin
PasteFromClipboard;
end;
procedure TOvcBaseEntryField.DoDeleteClick(Sender : TObject);
begin
ClearSelection;
end;
procedure TOvcBaseEntryField.DoSelectAllClick(Sender : TObject);
begin
SelectAll;
end;
procedure TOvcBaseEntryField.efAdjustSize;
{-adjust the height of the control based on the current font}
var
DC : hDC;
SaveFont : hFont;
I : Integer;
SysMetrics : TTextMetric;
Metrics : TTextMetric;
begin
if not FAutoSize then
Exit;
DC := GetDC(0);
try
GetTextMetrics(DC, SysMetrics);
SaveFont := SelectObject(DC, Font.Handle);
GetTextMetrics(DC, Metrics);
SelectObject(DC, SaveFont);
finally
ReleaseDC(0, DC);
end;
if NewStyleControls then begin
if Ctl3D then
I := 8
else
I := 6;
I := GetSystemMetrics(SM_CYBORDER) * I;
end else begin
I := SysMetrics.tmHeight;
if I > Metrics.tmHeight then
I := Metrics.tmHeight;
I := I div 4 + GetSystemMetrics(SM_CYBORDER) * 4;
end;
Height := Metrics.tmHeight + I;
{SetBounds may have turn this off, turn it back on}
if not FAutoSize then
FAutoSize := True;
end;
function TOvcBaseEntryField.efBinStr2Long(St : PAnsiChar; var L : LongInt) : Boolean;
{-convert a binary string to a longint}
var
BitNum : Word;
Len : Word;
LT : LongInt;
begin
Result := False;
Len := StrLen(St);
BitNum := 0;
LT := 0;
while Len > 0 do begin
Dec(Len);
case St[Len] of
'0' : {OK};
'1' : if BitNum > 31 then
Exit
else
Inc(LT, LongInt(1) shl BitNum);
else Exit;
end;
Inc(BitNum);
end;
L := LT;
Result := True;
end;
function TOvcBaseEntryField.efCalcDataSize(St : PAnsiChar; MaxLen : Word) : Word;
{-calculate data size of a string field with literal stripping option on}
var
I, L : Word;
begin
I := 0;
L := StrLen(St);
while St^ <> #0 do begin
if (St^ in PictureChars) then
Inc(I)
else case St^ of
pmFloatDollar, pmComma : Inc(I);
end;
Inc(St);
end;
Result := I+(MaxLen-L)+1;
end;
function TOvcBaseEntryField.efCanClose(DoValidation : Boolean) : Boolean;
var
SoftV : Boolean;
begin
Result := True;
{don't do any of this if we're hidden or not enabled}
if (not Visible) or (not Enabled) then
Exit;
HandleNeeded;
{clear error flag}
FLastError := 0;
{check for empty/uninitialized required field}
if (efoInputRequired in Options) and not efIsReadOnly then
if efFieldIsEmpty or (Uninitialized and not (sefModified in sefOptions)) then
FLastError := oeRequiredField;
{ask the validation routine if there's an error}
if FLastError = 0 then begin
Include(sefOptions, sefValidating);
FLastError := efValidateField;
Exclude(sefOptions, sefValidating);
end;
if efHPos > LongInt(StrLen(efEditSt)) then
efHPos := LongInt(StrLen(efEditSt));
if FLastError = 0 then
Exclude(sefOptions, sefInvalid)
else begin
if DoValidation and (efoSoftValidation in Options) then begin
Include(sefOptions, sefInvalid);
Result := True; {say we can close, error is in FLastError}
Exit;
end else begin
if (efoSoftValidation in Options) then
Include(sefOptions, sefInvalid);
{set flag to indicate that an error is pending}
Include(sefOptions, sefErrorPending);
{keep the caret where it is if we have the focus}
if sefHaveFocus in sefOptions then
Include(sefOptions, sefRetainPos);
{force soft validation on}
SoftV := efoSoftValidation in Options;
Include(FOptions, efoSoftValidation);
try
{ask the parent form to give us back the focus}
efMoveFocus(Self);
{report the error}
if not Controller.ErrorPending then
PostMessage(Handle, om_ReportError, FLastError, 0);
{set controller's error pending flag}
Controller.ErrorPending := True;
finally
{restore old options}
if SoftV then
Include(FOptions, efoSoftValidation)
else
Exclude(FOptions, efoSoftValidation);
end;
end;
end;
Result := FLastError = 0;
end;
procedure TOvcBaseEntryField.efCaretToEnd;
{-move the caret to the end of the field}
begin
efHPos := StrLen(efEditSt);
end;
procedure TOvcBaseEntryField.efCaretToStart;
{-move the caret to the beginning of the field}
begin
efHPos := 0;
efHOffset := 0;
end;
procedure TOvcBaseEntryField.efChangeMask(Mask : PAnsiChar);
{-change the picture mask}
var
Buf : array[0..MaxEditLen] of Byte;
begin
if (Mask <> nil) and (Mask^ <> #0) then begin
if csLoading in ComponentState then begin
{change the mask}
StrLCopy(efPicture, Mask, MaxPicture);
efPicLen := StrLen(efPicture);
end else begin
{save the current field value in tmp buffer}
efTransfer(@Buf, otf_GetData);
{change the mask}
StrLCopy(efPicture, Mask, MaxPicture);
efPicLen := StrLen(efPicture);
{reset the field to its former value}
efTransfer(@Buf, otf_SetData);
end;
end;
end;
function TOvcBaseEntryField.efCharOK(PicChar : AnsiChar; var Ch : AnsiChar;
PrevCh : AnsiChar; Fix : Boolean) : Boolean;
{-return True if Ch is in character set corresponding to PicChar}
begin
if Ch = #0 then begin
Result := False;
Exit;
end;
if Fix then
efFixCase(PicChar, Ch, PrevCh);
{assume it's OK}
Result := True;
case PicChar of
pmAnyChar, pmForceUpper, pmForceLower, pmForceMixed :
;
pmMonthName, pmMonthNameU, pmAlpha, pmUpperAlpha, pmLowerAlpha :
Result := Ch in AlphaCharSet;
pmDecimal :
Result := Ch in RealCharSet;
pmWhole :
Result := (Ch = '-') or (Ch in IntegerCharSet);
pmMonth, pmMonthU, pmDay, pmDayU, pmYear,
pmHour, pmHourU, pmSecond, pmSecondU,
pmPositive :
Result := Ch in IntegerCharSet;
pmHexadecimal :
case Ch of
'A'..'F' : ;
else
Result := Ch in IntegerCharSet;
end;
pmOctal :
case Ch of
'0'..'7', ' ' : ;
else
Result := False;
end;
pmBinary :
case Ch of
'0', '1', ' ' : ;
else
Result := False;
end;
pmAmPm : {};
pmTrueFalse :
Result := (Ch = FIntlSup.TrueChar) or (Ch = FIntlSup.FalseChar);
pmYesNo :
Result := (Ch = FIntlSup.YesChar) or (Ch = FIntlSup.NoChar);
pmScientific :
case Ch of
'+', 'E' : ;
else
Result := Ch in RealCharSet;
end;
pmUser1..pmUser8 :
Result := Ch in UserData.UserCharSet[PicChar];
end;
end;
procedure TOvcBaseEntryField.efConditionalBeep;
begin
if (efoBeepOnError in Controller.EntryOptions) then
MessageBeep(0);
end;
procedure TOvcBaseEntryField.efCopyPrim;
var
Size : Word;
H : THandle;
GP : PAnsiChar;
I : Word;
T : TEditString;
begin
Size := efSelEnd-efSelStart;
if Size > 0 then begin
{allocate global memory block}
H := GlobalAlloc(GHND, Size+1);
if H = 0 then
Exit;
{copy selected text to global memory block}
GP := GlobalLock(H);
efGetDisplayString(T, MaxEditLen);
StrStCopy(GP, T, efSelStart, Size);
{remove control characters}
for I := efSelStart to efSelEnd-1 do
case efEditSt[I] of
#1..#31 : GP[I-efSelStart] := efEditSt[I];
end;
GlobalUnlock(H);
{give the handle to the clipboard}
{$IFNDEF LCL}
Clipboard.SetAsHandle(CF_TEXT, H);
{$ENDIF}
end;
end;
function TOvcBaseEntryField.efEditBegin : Word;
{-return offset of first editable position in field}
begin
Result := 0;
end;
function TOvcBaseEntryField.efFieldIsEmpty : Boolean;
{-return True if the field is empty}
var
P : PAnsiChar;
begin
P := efEditSt;
while P^ = ' ' do
Inc(P);
Result := (P^ = #0);
end;
procedure TOvcBaseEntryField.efFieldModified;
{-mark the field as modified; call notify event}
begin
Include(sefOptions, sefModified);
Include(sefOptions, sefEverModified);
DoOnChange;
end;
procedure TOvcBaseEntryField.efFindCtrlChars(P : PAnsiChar; var ChCnt, CtCnt : Integer);
{-find control caracters and return normal and control char counts}
const
Space = ' ';
var
I : Integer;
begin
ChCnt := 0;
CtCnt := 0;
I := 0;
{count "normal" characters}
while (I < LongInt(StrLen(P))) and (P[I] >= Space) do begin
Inc(ChCnt);
Inc(I);
end;
{count "control" characters}
while (I < LongInt(StrLen(P))) and (P[I] < Space) do begin
Inc(CtCnt);
Inc(I);
end;
end;
procedure TOvcBaseEntryField.efFixCase(PicChar : AnsiChar; var Ch : AnsiChar; PrevCh : AnsiChar);
{-fix the case of Ch based on PicChar}
begin
case PicChar of
pmMonthNameU, pmForceUpper, pmUpperAlpha, pmTrueFalse,
pmYesNo, pmScientific, pmHexadecimal :
Ch := UpCaseChar(Ch);
pmForceLower, pmLowerAlpha :
Ch := LoCaseChar(Ch);
pmForceMixed :
case PrevCh of
' ', '-' :
Ch := UpCaseChar(Ch);
end;
pmAmPm : ;
pmUser1..pmUser8 :
case UserData.ForceCase[PicChar] of
mcUpperCase :
Ch := UpCaseChar(Ch);
mcLowerCase :
Ch := LoCaseChar(Ch);
mcMixedCase :
case PrevCh of
' ', '-' :
Ch := UpCaseChar(Ch);
end;
end;
end;
end;
function TOvcBaseEntryField.efGetDisplayString(Dest : PAnsiChar; Size : Word) : PAnsiChar;
{-return the display string in Dest and a pointer as the result}
var
Len : Word;
Value : Double;
Code : Integer;
S : string;
begin
FillChar(Dest^, Size, #0);
efMapControlChars(Dest, efEditSt);
{see if zero values should be displayed}
if efIsNumericType and not (sefHaveFocus in sefOptions) then begin
if (ZeroDisplay = zdHide) or
((ZeroDisplay = zdHideUntilModified) and not EverModified) then begin
S := Trim(GetStrippedEditString);
Val(S, Value, Code);
if (Value = ZeroDisplayValue) and (Code = 0) then begin
Len := StrLen(Dest);
if Len > 0 then
FillChar(Dest^, Len, ' ');
end;
end;
end;
Result := Dest;
end;
function TOvcBaseEntryField.efGetMousePos(MPos : Integer) : Integer;
{-get the position of a mouse click}
var
I : Integer;
Len : Integer;
Ex : Integer;
Pos : Integer;
S : PAnsiChar;
Metrics : TTextMetric;
TmpSt : TEditString;
Done : Boolean;
SLen : Integer;
X : Integer;
LMargin : Integer;
begin
LMargin := TextMargin;
if (MPos < 0) and (efHOffset > 0) then begin
GetTextMetrics(Canvas.Handle, Metrics);
I := (Abs(MPos)+Metrics.tmAveCharWidth) div Metrics.tmAveCharWidth;
Dec(efHOffset, I);
if efHOffset < 0 then
efHOffset := 0;
end;
{get a copy of the display string}
efGetDisplayString(TmpSt, MaxEditLen);
Len := StrLen(TmpSt);
if efHOffset > Len then
I := Len
else
I := efHOffset;
S := @TmpSt[I];
if efRightAlignActive then begin
if (Assigned(FBorders)) then begin
if (FBorders.RightBorder.Enabled) then
LMargin := LMargin + FBorders.RightBorder.PenWidth;
end;
MPos := ClientWidth-LMargin-1-MPos;
Pos := Len + 1;
I := 0;
end else begin
if (Assigned(FBorders)) then begin
if (FBorders.LeftBorder.Enabled) then
LMargin := LMargin + FBorders.LeftBorder.PenWidth;
end;
MPos := MPos - LMargin+1;
Pos := 0;
end;
repeat
if efRightAlignActive then begin
Dec(Pos);
S := @TmpSt[Pos-1];
SLen := Len - Pos + 1;
end else begin
Inc(Pos);
SLen := Pos;
end;
Ex := efGetTextExtent(S, SLen);
X := (efGetTextExtent(@S[SLen-1], 1) div 2);
if efRightAlignActive then
Done := (Ex+X > MPos) or (I+Pos < 1)
else
Done := (Ex-X > MPos) or (I+Pos > Len);
until Done;
Result := I+(Pos-1);
if Result < 0 then
Result := 0;
if efRightAlignActive then begin
if MPos < 1 then
Result := I+Pos;
end;
end;
procedure TOvcBaseEntryField.efGetSampleDisplayData(T : PAnsiChar);
{-return sample data for the current field type}
var
Buf : TEditString;
I : Integer;
begin
{return the picture mask for the sample display data}
StrLCopy(Buf, efPicture, MaxLength);
if efFieldClass = fcSimple then begin
for I := 1 to MaxLength-1 do
Buf[I] := Buf[I-1];
Buf[MaxLength] := #0;
end;
StrLCopy(T, Buf, MaxLength);
end;
function TOvcBaseEntryField.efGetTextExtent(S : PChar; Len : Integer) : Word;
var
Size : TSize;
begin
// Apparent TurboPower bug: sometimes Len is 1 when string is blank.
// Probably meaningless width returned in that case.
// Could also return width of "x" if a non-zero width is assumed
// by calling code.
if Length(S) = 0 then
begin
Result := 0;
Exit;
end;
GetTextExtentPoint32(Canvas.Handle, S, Len, Size);
Result := Size.cX;
end;
procedure TOvcBaseEntryField.efBorderChanged(ABorder : TObject);
begin
if (FBorders.BottomBorder.Enabled) or
(FBorders.LeftBorder.Enabled) or
(FBorders.RightBorder.Enabled) or
(FBorders.TopBorder.Enabled) then begin
BorderStyle := bsNone;
Ctl3D := False;
end else begin
BorderStyle := bsSingle;
Ctl3D := True;
end;
{$IFNDEF LCL}
RecreateWnd;
{$ELSE}
MyMisc.RecreateWnd(Self);
{$ENDIF}
end;
procedure TOvcBaseEntryField.efCalcTopMargin;
begin
if HandleAllocated then
efTopMargin := GetTopTextMargin(Font, BorderStyle, Height, Ctl3D)
else
efTopMargin := 0;
if (Assigned(FBorders)) then begin
if (FBorders.TopBorder.Enabled) then
efTopMargin := efTopMargin + FBorders.TopBorder.PenWidth;
end;
end;
procedure TOvcBaseEntryField.efColorChanged(AColor : TObject);
begin
Repaint;
end;
procedure TOvcBaseEntryField.efInitializeDataSize;
begin
case efDataType mod fcpDivisor of
fsubString :
begin
efDataSize := MaxLength+1;
{handle special data size cases}
if efDataType = fidPictureString then
if (efoStripLiterals in Options) then
efDataSize := efCalcDataSize(efPicture, MaxLength);
end;
fsubChar : efDataSize := SizeOf(AnsiChar);
fsubBoolean : efDataSize := SizeOf(Boolean);
fsubYesNo : efDataSize := SizeOf(Boolean);
fsubLongInt : efDataSize := SizeOf(LongInt);
fsubWord : efDataSize := SizeOf(Word);
fsubInteger : efDataSize := SizeOf(SmallInt);
fsubByte : efDataSize := SizeOf(Byte);
fsubShortInt : efDataSize := SizeOf(ShortInt);
fsubReal : efDataSize := SizeOf(Real);
fsubExtended : efDataSize := SizeOf(Extended);
fsubDouble : efDataSize := SizeOf(Double);
fsubSingle : efDataSize := SizeOf(Single);
fsubComp : efDataSize := SizeOf(Comp);
fsubDate : efDataSize := SizeOf(TStDate);
fsubTime : efDataSize := SizeOf(TStTime);
else
efDataSize := 0;
end;
end;
function TOvcBaseEntryField.efIsNumericType : Boolean;
{-return True if field is of a numeric type}
begin
case efDataType mod fcpDivisor of
fsubLongInt, fsubWord, fsubInteger, fsubByte,
fsubShortInt, fsubReal, fsubExtended, fsubDouble,
fsubSingle, fsubComp :
Result := True;
else
Result := False;
end;
end;
function TOvcBaseEntryField.efIsReadOnly : Boolean;
{-return True if field is read-only}
begin
Result := efoReadOnly in Options;
end;
{ - HWnd changed to TOvcHWnd for BCB Compatibility }
function TOvcBaseEntryField.efIsSibling(HW : TOvcHWnd{hWnd}) : Boolean;
{-is the window HW one of our siblings}
var
C : TWinControl;
H : hWnd;
begin
Result := False;
if HW = 0 then
Exit;
C := FindControl(HW);
{see if this window is a child of one of our siblings}
if not Assigned(C) then begin
H := GetParent(HW);
if H > 0 then
C := FindControl(H);
end;
if Assigned(C) then
{$IFDEF VERSION5}
if (GetImmediateParentForm(C) = GetImmediateParentForm(Self)) then
{$ELSE}
if GetParentForm(C) = GetParentForm(Self) then
{$ENDIF}
Result := True;
end;
procedure TOvcBaseEntryField.efLong2Str(P : PAnsiChar; L : LongInt);
{-convert a longint to a string}
var
W : Word;
S : array[0..32] of AnsiChar;
St : string[32];
begin
W := efDataSize * 2;
if sefHexadecimal in sefOptions then begin
HexLPChar(S, L);
if W < 8 then
StrStDeletePrim(S, 0, 8-W);
end else if sefOctal in sefOptions then begin
OctalLPChar(S, L);
if W < 8 then
StrStDeletePrim(S, 0, 12-(W*2));
end else if sefBinary in sefOptions then begin
BinaryLPChar(S, L);
if W < 8 then
StrStDeletePrim(S, 0, 32-(W*4));
end else if L = 0 then begin
S[0] := '0';
S[1] := #0;
end else begin
Str(L, St);
StrPCopy(S, St);
end;
StrCopy(P, S);
end;
procedure TOvcBaseEntryField.efMapControlChars(Dest, Src : PAnsiChar);
{-copy from Src to Dest, mapping control characters to alpha in process}
var
I : Integer;
begin
StrCopy(Dest, Src);
if (StrLen(Dest) > 0) then begin
for I := 0 to StrLen(Dest)-1 do
if Dest[I] < ' ' then
Dest[I] := AnsiChar(Byte(Dest[I])+64);
end;
end;
procedure TOvcBaseEntryField.efMoveFocus(C : TWinControl);
{-ask the controller to move the focus to the specified control}
begin
{$IFNDEF LCL}
PostMessage(Controller.Handle, om_SetFocus, 0, LongInt(C));
{$ELSE}
Controller.PostMessage(Controller.Handle, om_SetFocus, 0, LongInt(C));
{$ENDIF}
end;
procedure TOvcBaseEntryField.efMoveFocusToNextField;
{-give next field the focus}
var
PF : TForm;
begin
PF := TForm(GetParentForm(Self));
if not Assigned(PF) then
Exit;
{$IFNDEF LCL}
PostMessage(PF.Handle, WM_NEXTDLGCTL, 0, 0);
{$ELSE} //WM_NEXTDLGCTL message apparently not handled by LCL TForm
Self.PerformTab(True);
{$ENDIF}
end;
procedure TOvcBaseEntryField.efMoveFocusToPrevField;
{-give previous field the focus}
var
PF : TForm;
begin
PF := TForm(GetParentForm(Self));
if not Assigned(PF) then
Exit;
{$IFNDEF LCL}
PostMessage(PF.Handle, WM_NEXTDLGCTL, 1, 0);
{$ELSE} //WM_NEXTDLGCTL message apparently not handled by LCL TForm
Self.PerformTab(False);
{$ENDIF}
end;
function TOvcBaseEntryField.efNthMaskChar(N : Word) : AnsiChar;
{-return the N'th character in the picture mask. N is 0-based}
begin
if N >= efPicLen then
Result := efPicture[efPicLen-1]
else
Result := efPicture[N];
end;
function TOvcBaseEntryField.efOctStr2Long(St : PAnsiChar; var L : LongInt) : Boolean;
{-convert an octal string to a longint}
var
I : Word;
begin
Result := True;
L := 0;
for I := 0 to StrLen(St)-1 do begin
{are we going to loose any of the top 3 bits}
if (L and $E0000000) <> 0 then
Result := False;
L := L shl 3;
L := L or (Ord(St[I]) - Ord('0'));
end;
end;
{ - Hdc changed to TOvcHdc for BCB Compatibility }
procedure TOvcBaseEntryField.efPaintPrim(DC : TOvcHdc{Hdc};
ARect : TRect; Offset : Integer);
{-primitive routine to draw the entry field control}
var
X, Y : Integer;
ChCnt : Integer;
CtCnt : Integer;
HStart : Integer;
HEnd : Integer;
OldBKMode : Integer;
RTC, HTC : LongInt;
RBC, HBC : LongInt;
CtlClr : LongInt;
SA, SD : PAnsiChar;
T : TEditString;
LMargin : Integer;
// I : Integer;
procedure Display(Count : Word; TC, BC : LongInt);
begin
if (Count <> 0) and (X < ARect.Right) then begin
SetTextColor(DC, TC);
SetBkColor(DC, BC);
ExtTextOut(DC, X, Y, ETO_CLIPPED, @ARect, SD, Count, nil);
end;
if (Count <> 0) then begin
{adjust X coordinate}
Inc(X, efGetTextExtent(SD, Count));
{advance string pointers}
Inc(SD, Count);
Inc(SA, Count);
{adjust highlight indices}
Dec(HStart, Count);
if HStart < 0 then
HStart := 0;
Dec(HEnd, Count);
if HEnd <= HStart then
HEnd := 0;
end;
end;
procedure DisplayPrim(Count : Word; TC, HC : LongInt);
var
SubCnt : Word;
Buf : TEditString;
begin
if (Count > 0) and (efFieldClass = fcNumeric) then begin
StrCopy(Buf, SD);
{remove leading and trailing spaces}
TrimAllSpacesPChar(Buf);
SubCnt := StrLen(Buf);
if HStart < HEnd then begin
SetTextColor(DC, HTC);
SetBkColor(DC, HBC)
end else begin
SetTextColor(DC, RTC);
SetBkColor(DC, RBC);
end;
{set right alignment}
SetTextAlign(DC, TA_RIGHT);
{paint the text right aligned}
ExtTextOut(DC, X, Y, ETO_CLIPPED, @ARect, Buf, SubCnt, nil);
Exit;
end;
if (HStart = 0) and (HEnd > 0) then begin
SubCnt := HEnd-HStart;
if SubCnt > Count then
SubCnt := Count;
{highlighted chars}
OldBKMode := SetBkMode(DC, OPAQUE);
Display(SubCnt, HC, HBC);
SetBkMode(DC, OldBkMode);
end else begin
if HStart > 0 then begin
SubCnt := HStart;
if SubCnt > Count then
SubCnt := Count;
end else
SubCnt := Count;
Display(SubCnt, TC, RBC);
end;
{do we need to recurse?}
Dec(Count, SubCnt);
if Count > 0 then
DisplayPrim(Count, TC, HC);
end;
begin
{select the font into our painting DC}
SelectObject(DC, Font.Handle);
SetBkColor(DC, Graphics.ColorToRGB(Color));
SetTextColor(DC, Graphics.ColorToRGB(Font.Color));
{display samples of appropriate data while designing}
if csDesigning in ComponentState then begin
efGetSampleDisplayData(T);
SD := @T[0];
end else begin
{get the display version of the string}
efGetDisplayString(T, MaxEditLen);
SD := @T[Offset];
end;
{point to the starting point of the string}
SA := @efEditSt[Offset];
{determine highlighted portion of the string}
if not (sefHaveFocus in sefOptions) then begin
HStart := 0;
HEnd := 0;
end else begin
HStart := efSelStart-Offset;
HEnd := efSelEnd-Offset;
if HStart < 0 then
HStart := 0;
if HEnd <= HStart then
HEnd := 0;
end;
{get text colors to use}
if IsValid then begin
RTC := GetTextColor(DC);
RBC := GetBkColor(DC);
end else begin
RTC := Graphics.ColorToRGB(FEFColors.Error.TextColor);
RBC := Graphics.ColorToRGB(FEFColors.Error.BackColor);
end;
{fill in the background}
if not Enabled then
Canvas.Brush.Color := FEFColors.Disabled.BackColor
else if IsValid then
Canvas.Brush.Color := Color
else
Canvas.Brush.Color := FEFColors.Error.BackColor;
OldBkMode := SetBkMode(DC, TRANSPARENT);
FillRect(DC, ARect, Canvas.Brush.Handle);
SetBkMode(DC, OldBkMode);
if csDesigning in ComponentState then begin
{no highlights if we're designing}
HStart := 0;
HEnd := 0;
end else if not Enabled then begin
{no highlights}
HStart := 0;
HEnd := 0;
RTC := Graphics.ColorToRGB(FEFColors.Disabled.TextColor);
RBC := Graphics.ColorToRGB(FEFColors.Disabled.BackColor);
end;
if csDesigning in ComponentState then begin
ChCnt := StrLen(T);
CtCnt := 0;
end else
{count characters (use actual string, SA, not display string, SD)}
efFindCtrlChars(SA, ChCnt, CtCnt);
LMargin := FTextMargin;
if (efFieldClass = fcNumeric) then begin
if (Assigned(FBorders)) then begin
if (FBorders.RightBorder.Enabled) then
LMargin := LMargin + FBorders.RightBorder.PenWidth;
end;
X := ClientWidth-LMargin-1;
end else begin
efRightAlignActive := efoRightAlign in Options;
if efRightAlignActive then begin
if (Assigned(FBorders)) then begin
if (FBorders.RightBorder.Enabled) then
LMargin := LMargin + FBorders.RightBorder.PenWidth;
end;
X := efGetTextExtent(SD, StrLen(SD));
if X >= ClientWidth-LMargin-1 then begin
(*
!!.04 - This is a classic bad idea. It royally messes stuff up.
{the display string doesn't fit in the client area, so strip all }
{padding. }
while SD[0] = PadChar do begin
for I := 0 to Length(SD) - 1 do
SD[i] := SD[i + 1];
end;
ChCnt := Length(SD);
efRightAlignActive := False;
*)
X := LMargin-1;
end else
X := ClientWidth-X-LMargin-1;
end else begin
if (Assigned(FBorders)) then begin
if (FBorders.LeftBorder.Enabled) then
LMargin := LMargin + Borders.LeftBorder.PenWidth;
end;
(*
!!.04 - This is a classic bad idea. It royally messes stuff up.
{the display string doesn't fit in the client area, so strip any }
{padding away so that the important stuff can show }
X := efGetTextExtent(SD, StrLen(SD));
if X >= ClientWidth-LMargin-1 then
if efoTrimBlanks in Options then
while SD[0] = PadChar do begin
for I := 0 to Length(SD) - 1 do
SD[i] := SD[i + 1];
end;
ChCnt := Length(SD);
*)
X := LMargin-1;
end;
end;
Y := efTopMargin;
{convert TColor values to RGB values}
CtlClr := Graphics.ColorToRGB(FCtrlColor);
HTC := Graphics.ColorToRGB(FEFColors.Highlight.TextColor);
HBC := Graphics.ColorToRGB(FEFColors.Highlight.BackColor);
{display loop}
while (ChCnt or CtCnt) <> 0 do begin
{display regular characters}
if ChCnt > 0 then
DisplayPrim(ChCnt, RTC, HTC);
{display control characters}
if CtCnt > 0 then
DisplayPrim(CtCnt, CtlClr, CtlClr);
{check for more characters}
if CtCnt = 0 then
ChCnt := 0
else
efFindCtrlChars(SA, ChCnt, CtCnt);
end;
end;
procedure TOvcBaseEntryField.efPerformEdit(var Msg : TMessage; Cmd : Word);
{-process the specified editing command if appropriate}
begin
HandleNeeded;
if not HandleAllocated then
Exit;
{the null character implies that the this key should be}
{ignored. the only way for the null character to get here}
{is by changing a key after it has been entered , probably}
{in a key preview event handler}
if (Cmd = ccChar) and (AnsiChar(Lo(Msg.wParam)) = #0) then
Exit;
{filter out commands that are inappropriate in read-only mode}
if efIsReadOnly then begin
case Cmd of
ccChar, ccCtrlChar, ccRestore, ccBack, ccDel, ccDelEol,
ccDelBol, ccDelLine, ccDelWord, ccCut, ccPaste,
ccInc, ccDec :
begin
efConditionalBeep;
Exit;
end;
end;
end;
{do user command notification for user commands}
if Cmd >= ccUserFirst then begin
DoOnUserCommand(Cmd);
Cmd := ccSuppress;
end;
{allow descendant classes to perform edit processing}
efEdit(Msg, Cmd);
end;
procedure TOvcBaseEntryField.efPerformRepaint(Modified : Boolean);
{-flag the field as modified and redraw it}
begin
if Modified then
efFieldModified;
Refresh;
end;
procedure TOvcBaseEntryField.efPerformPreEditNotify(C : TWinControl);
{-pre-edit notification to parent form}
begin
Controller.DoOnPreEdit(Self, C);
end;
procedure TOvcBaseEntryField.efPerformPostEditNotify(C : TWinControl);
{-post-edit notification to parent form}
begin
Controller.DoOnPostEdit(Self, C);
end;
function TOvcBaseEntryField.efPositionCaret(Adjust : Boolean) : Boolean;
{-position the editing caret}
var
Delta : Word;
S : PAnsiChar;
OK : Boolean;
Metrics : TTextMetric;
CW : Integer;
Pos : TPoint;
T : TEditString;
SLen : Integer;
LMargin : Integer;
begin
Result := False;
if not (sefHaveFocus in sefOptions) then
Exit;
if Adjust then begin
{when a character is entered that erases the existing text,
efHPos may be 1 greater than EditBegin because of the
entered character}
if ((efHPos = efEditBegin) or (efHPos = efEditBegin+1)) and
(efHOffset <> 0) then begin
efHOffset := 0;
Result := True;
end else if (efHPos < efHOffset) then begin
efHOffset := efHPos;
Result := True;
end;
end;
efGetDisplayString(T, MaxEditLen);
efRightAlignActive := efoRightAlign in Options;
if efRightAlignActive then begin
Delta := efGetTextExtent(T, StrLen(T));
if Delta >= ClientWidth-FTextMargin-1 then begin
{the display string doesn't fit in the client area, it is displayed left aligned}
efRightAlignActive := False;
end else begin
efRightAlignActive := True;
efHOffset := 0;
end;
end;
repeat
if not efRightAlignActive then begin
S := @T[efHOffset];
end else begin
S := @T[efHPos];
end;
SLen := StrLen(S);
if (efHPos = efHOffset) and not efRightAlignActive then
Delta := 0
else begin
if not efRightAlignActive then
Delta := efGetTextExtent(S, efHPos-efHOffset)
else
Delta := efGetTextExtent(S, SLen);
end;
OK := (Delta < ClientWidth-FTextMargin-1) or
(sefNumeric in sefOptions) or not Adjust;
if not OK then begin
if efHOffset >= efHPos then
OK := True
else begin
Inc(efHOffset);
Result := True;
end;
end;
until OK;
{get metrics for current font}
GetTextMetrics(Canvas.Handle, Metrics);
{get character width}
CW := efGetTextExtent(@T[efHPos], 1);
{set caret cell height and width}
efCaret.CellHeight := Metrics.tmHeight;
efCaret.CellWidth := CW;
{adjust caret position if using a wide cursor}
if (efCaret.CaretType.Shape in [csBlock, csHalfBlock, csHorzLine]) or
(efCaret.CaretType.CaretWidth > 4) then
if efRightAlignActive then
Dec(Delta)
else
Inc(Delta);
{set caret position}
LMargin := FTextMargin;
if (efFieldClass = fcNumeric) then begin
if (Assigned(FBorders)) then begin
if (FBorders.RightBorder.Enabled) then
LMargin := LMargin + FBorders.RightBorder.PenWidth;
end;
Pos.X := ClientWidth-LMargin-1;
end else begin
if efRightAlignActive then begin
if (Assigned(FBorders)) then begin
if (FBorders.RightBorder.Enabled) then
LMargin := LMargin + FBorders.RightBorder.PenWidth;
end;
Pos.X := ClientWidth - Succ(Delta) - LMargin - 1;
end else begin
if (Assigned(FBorders)) then begin
if (FBorders.LeftBorder.Enabled) then
LMargin := LMargin + FBorders.LeftBorder.PenWidth;
end;
Pos.X := Succ(Delta) + LMargin - 3;
end;
end;
Pos.Y := efTopMargin;
if Pos.Y < 0 then
Pos.Y := 0;
efCaret.Position := Pos;
end;
function TOvcBaseEntryField.efRangeToStRange(const Value : TRangeType) : string;
{-returns the range as a string}
var
D : Byte;
Ex : Extended;
Buf : TEditString;
DateMask : string[MaxDateLen];
TimeMask : string[MaxDateLen];
function GetDecimalPlaces : Byte;
var
I : Cardinal;
DotPos : Cardinal;
begin
if not StrChPos(efPicture, pmDecimalPt, DotPos) then
Result := DecimalPlaces
else begin
Result := 0;
for I := DotPos+1 to MaxLength-1 do
if efNthMaskChar(I) in PictureChars then
Inc(Result)
else
Break;
end;
end;
function ExtendedToString(E : Extended; DP : Byte) : string;
label
UseScientificNotation;
var
I : Cardinal;
S : TEditString;
begin
if StrScan(efPicture, pmScientific) <> nil then
goto UseScientificNotation;
{try to use regular notation}
Str(E:0:DP, S);
{trim trailing 0's if appropriate}
if StrScan(S, pmDecimalPt) <> nil then
TrimTrailingZerosPChar(S);
{does it fit?}
if StrLen(S) > MaxLength then begin
{won't fit--use scientific notation}
UseScientificNotation:
if (DP > 0) and (9+DP < MaxLength) then
Str(E:9+DP, S)
else
Str(E:MaxLength, S);
TrimAllSpacesPChar(S);
TrimEmbeddedZerosPChar(S);
end;
{convert decimal point}
if StrChPos(S, pmDecimalPt, I) then
S[I] := IntlSupport.DecimalChar;
Result := StrPas(S);
end;
begin
Result := '';
D := GetDecimalPlaces;
case efDataType mod fcpDivisor of
fsubString : {};
fsubBoolean, fsubYesNo : {};
fsubChar :
if Value.rtChar <= ' ' then begin
Str(Ord(Value.rtChar), Result);
Result := '#' + Result;
end else
Result := Value.rtChar;
fsubLongInt, fsubInteger, fsubShortInt, fsubWord, fsubByte :
begin
efLong2Str(Buf, Value.rtLong);
Result := StrPas(Buf);
end;
fsubReal :
begin
Ex := Value.rtReal;
Result := ExtendedToString(Ex, D);
end;
fsubExtended, fsubDouble, fsubSingle, fsubComp :
Result := ExtendedToString(Value.rtExt, D);
fsubDate :
begin
DateMask := OvcIntlSup.InternationalDate(True);
if Value.rtDate = BadDate then
Result := ''
else
Result := OvcIntlSup.DateToDateString(DateMask, Value.rtDate, False);
end;
fsubTime :
begin
TimeMask := OvcIntlSup.InternationalTime(False);
if Value.rtTime = BadTime then
Result := ''
else
Result := OvcIntlSup.TimeToTimeString(TimeMask, Value.rtTime, False);
end;
end;
end;
procedure TOvcBaseEntryField.efRemoveBadOptions;
{-remove inappropriate options for this field and data type}
begin
if csLoading in ComponentState then
Exit;
case efFieldClass of
fcSimple :
case efDataType mod fcpDivisor of
fsubString :
begin
Exclude(FOptions, efoRightJustify);
Exclude(FOptions, efoStripLiterals);
end;
fsubChar, fsubBoolean, fsubYesNo :
begin
Exclude(FOptions, efoCaretToEnd);
Exclude(FOptions, efoForceInsert);
Exclude(FOptions, efoTrimBlanks);
Exclude(FOptions, efoRightJustify);
Exclude(FOptions, efoStripLiterals);
end;
fsubLongInt, fsubWord, fsubInteger, fsubByte,
fsubShortInt, fsubReal, fsubExtended, fsubDouble,
fsubSingle, fsubComp :
begin
Exclude(FOptions, efoTrimBlanks);
Exclude(FOptions, efoRightJustify);
Exclude(FOptions, efoStripLiterals);
end;
end;
fcPicture :
case efDataType mod fcpDivisor of
fsubString : {};
fsubChar, fsubBoolean, fsubYesNo :
begin
Exclude(FOptions, efoCaretToEnd);
Exclude(FOptions, efoForceInsert);
Exclude(FOptions, efoTrimBlanks);
Exclude(FOptions, efoRightJustify);
Exclude(FOptions, efoStripLiterals);
end;
fsubLongInt, fsubWord, fsubInteger, fsubByte,
fsubShortInt, fsubReal, fsubExtended, fsubDouble,
fsubSingle, fsubComp :
begin
Exclude(FOptions, efoTrimBlanks);
Exclude(FOptions, efoStripLiterals);
end;
fsubDate, fsubTime :
begin
Exclude(FOptions, efoTrimBlanks);
Exclude(FOptions, efoRightJustify);
Exclude(FOptions, efoStripLiterals);
end;
end;
fcNumeric :
begin
Exclude(FOptions, efoCaretToEnd);
Exclude(FOptions, efoForceInsert);
Exclude(FOptions, efoTrimBlanks);
Exclude(FOptions, efoRightJustify);
Exclude(FOptions, efoStripLiterals);
Exclude(FOptions, efoRightAlign);
end;
end;
{if input is required then these fields must also be uninitialized}
if (csDesigning in ComponentState) and (efoInputRequired in Options) then
case efDataType mod fcpDivisor of
fsubChar, fsubBoolean, fsubYesNo, fsubLongInt,
fsubWord, fsubInteger, fsubByte, fsubShortInt,
fsubReal, fsubExtended, fsubDouble, fsubSingle,
fsubComp : FUninitialized := True;
end;
end;
procedure TOvcBaseEntryField.efResetCaret;
{-move the caret to the beginning or end of the field, as appropriate}
begin
if (efoCaretToEnd in FOptions) then
efCaretToEnd
else
efCaretToStart;
end;
procedure TOvcBaseEntryField.efSaveEditString;
{-save a copy of the edit string}
begin
if (efSaveEdit = nil) or (StrLen(efEditSt) <> StrLen(efSaveEdit)) then begin
if efSaveEdit <> nil then
StrDispose(efSaveEdit);
efSaveEdit := StrNew(efEditSt);
end else
StrCopy(efSaveEdit, efEditSt);
end;
procedure TOvcBaseEntryField.efSetCaretPos(Value : Integer);
{-set position of caret within the field}
begin
if not (sefHaveFocus in sefOptions) then
Exit;
if Value < 0 then
efHPos := 0
else if Value > LongInt(StrLen(efEditSt)) then
efHPos := StrLen(efEditSt)+1
else
efHPos := Value;
efPositionCaret(True);
end;
procedure TOvcBaseEntryField.efSetDefaultRange(FT : Byte);
{-set the default range for the given field type FT}
begin
efRangeLo := BlankRange;
efRangeHi := BlankRange;
case FT mod fcpDivisor of
fsubString : {};
fsubBoolean, fsubYesNo : {};
fsubChar :
begin
efRangeLo.rtChar := #32;
efRangeHi.rtChar := #32;
end;
fsubLongInt :
begin
efRangeLo.rtLong := Low(LongInt); {80000000}
efRangeHi.rtLong := High(LongInt); {7FFFFFFF}
end;
fsubWord :
begin
efRangeLo.rtLong := Low(Word); {0}
efRangeHi.rtLong := High(Word); {65535}
end;
fsubInteger :
begin
efRangeLo.rtLong := Low(SmallInt); {-32768}
efRangeHi.rtLong := High(SmallInt); {+32767}
end;
fsubByte :
begin
efRangeLo.rtLong := Low(Byte); {0}
efRangeHi.rtLong := High(Byte); {255}
end;
fsubShortInt :
begin
efRangeLo.rtLong := Low(ShortInt); {-128}
efRangeHi.rtLong := High(ShortInt); {127}
end;
fsubReal :
begin
efRangeLo.rtReal := -1.7e+38;
efRangeHi.rtReal := +1.7e+38;
end;
fsubExtended :
begin
{$IFNDEF FPC}
efRangeLo.rtExt := -1.1e+4932;
efRangeHi.rtExt := +1.1e+4932;
{$ELSE}
{$IFDEF FPC_HAS_TYPE_EXTENDED}
efRangeLo.rtExt := -1.1e+4932;
efRangeHi.rtExt := +1.1e+4932;
{$ELSE} {Extended same as Double on PPC}
efRangeLo.rtExt := -1.7e+308;
efRangeHi.rtExt := +1.7e+308;
{$ENDIF}
{$ENDIF}
end;
fsubDouble :
begin
efRangeLo.rtExt := -1.7e+308;
efRangeHi.rtExt := +1.7e+308;
end;
fsubSingle :
begin
efRangeLo.rtExt := -3.4e+38;
efRangeHi.rtExt := +3.4e+38;
end;
fsubComp :
begin
efRangeLo.rtExt := -9.2e+18;
efRangeHi.rtExt := +9.2e+18;
end;
fsubDate :
begin
efRangeLo.rtDate := MinDate;
efRangeHi.rtDate := MaxDate;
end;
fsubTime :
begin
efRangeLo.rtTime := MinTime;
efRangeHi.rtTime := MaxTime;
end;
end;
end;
procedure TOvcBaseEntryField.efSetInitialValue;
{-set the initial value of the field}
var
R : TRangeType;
FST : Byte;
begin
if csDesigning in ComponentState then
Exit;
R := BlankRange;
FST := efDataType mod fcpDivisor;
case FST of
fsubChar :
if (' ' >= efRangeLo.rtChar) and (' ' <= efRangeHi.rtChar) then
R.rtChar := ' '
else
R.rtChar := efRangeLo.rtChar;
fsubLongInt, fsubWord, fsubInteger, fsubByte, fsubShortInt :
if (0 < efRangeLo.rtLong) or (0 > efRangeHi.rtLong) then
R.rtLong := efRangeLo.rtLong;
fsubReal :
if (0 < efRangeLo.rtReal) or (0 > efRangeHi.rtReal) then
R.rtReal := efRangeLo.rtReal;
fsubExtended, fsubDouble, fsubSingle, fsubComp :
if (0 < efRangeLo.rtExt) or (0 > efRangeHi.rtExt) then
case FST of
fsubExtended : R.rtExt := efRangeLo.rtExt;
fsubDouble : R.rtDbl := efRangeLo.rtExt;
fsubSingle : R.rtSgl := efRangeLo.rtExt;
fsubComp : R.rtComp := efRangeLo.rtExt;
end;
fsubDate : R.rtDate := BadDate;
fsubTime : R.rtTime := BadTime;
end;
efTransfer(@R, otf_SetData);
end;
procedure TOvcBaseEntryField.SetName(const Value : TComponentName);
begin
inherited SetName(Value);
Repaint;
end;
procedure TOvcBaseEntryField.SetSelection(Start, Stop : Word);
{-mark offsets Start..Stop as selected}
var
Len : Word;
begin
if Start <= Stop then begin
Len := StrLen(efEditSt);
if Start > Len then
Start := Len;
if Stop > Len then
Stop := Len;
{all or nothing for numeric fields}
if (efFieldClass = fcNumeric) then
if (Start <> Stop) then begin
Start := 0;
Stop := MaxEditLen;
end;
efSelStart := Start;
efSelEnd := Stop;
end;
end;
function TOvcBaseEntryField.efStr2Long(P : PAnsiChar; var L : LongInt) : Boolean;
{-convert a string to a long integer}
var
S : TEditString;
begin
Result := True;
StrCopy(S, P);
TrimAllSpacesPChar(S);
{treat an empty string as 0}
if StrLen(S) = 0 then begin
L := 0;
Exit;
end;
if sefBinary in sefOptions then
Result := efBinStr2Long(S, L)
else if sefOctal in sefOptions then
Result := efOctStr2Long(S, L)
else begin
if (sefHexadecimal in sefOptions) and (S[0] <> #0) then
if StrPos(S, '$') = nil then
StrChInsertPrim(S, '$', 0);
{check for special value the Val() doesn't handle correctly}
if StrComp(S, '-2147483648') = 0 then
L := LongInt($80000000)
else
Result := StrToLongPChar(S, L);
end;
end;
function TOvcBaseEntryField.efStRangeToRange(const Value : string; var R : TRangeType) : Boolean;
{-converts a string range to a RangeType}
var
I : Integer;
Code : Integer;
fSub : Byte;
Buf : TEditString;
DateMask : string[MaxDateLen];
TimeMask : string[MaxDateLen];
begin
Code := 0; {assume success}
R := BlankRange;
fSub := efDataType mod fcpDivisor;
case fSub of
fsubString : {};
fsubBoolean, fsubYesNo : {};
fsubChar :
if Value = '' then
R.rtChar := #32
else if Value[1] = '#' then begin
Val(Copy(Value, 2, 3), I, Code);
if Code = 0 then
R.rtChar := Chr(I)
else begin
Code := 0;
R.rtChar := #32;
end;
end else
R.rtChar := Value[1];
fsubLongInt, fsubWord, fsubInteger, fsubByte, fsubShortInt :
begin
StrPCopy(Buf, Value);
if not efStr2Long(Buf, R.rtLong) then
Code := 1
else if (fSub = fsubWord) and
((R.rtLong < Low(Word)) or (R.rtLong > High(Word))) then
Code := 1
else if (fSub = fsubInteger) and
((R.rtLong < Low(SmallInt)) or (R.rtLong > High(SmallInt))) then
Code := 1
else if (fSub = fsubByte) and
((R.rtLong < Low(Byte)) or (R.rtLong > High(Byte))) then
Code := 1
else if (fSub = fsubShortInt) and
((R.rtLong < Low(ShortInt)) or (R.rtLong > High(ShortInt))) then
Code := 1;
end;
fsubReal :
if Value = '' then
R.rtReal := 0
else
Val(Value, R.rtReal, Code);
fsubExtended, fsubDouble, fsubSingle, fsubComp :
begin
if Value = '' then
R.rtExt := 0
else
Val(Value, R.rtExt, Code);
if (Code = 0) then begin
if (fSub = fsubDouble) and ((R.rtExt < -1.7e+308) or (R.rtExt > +1.7e+308)) then
Code := 1
else if (fSub = fsubSingle) and ((R.rtExt < -3.4e+38) or (R.rtExt > +3.4e+38)) then
Code := 1
else if (fSub = fsubComp) and ((R.rtExt < -9.2e+18) or (R.rtExt > +9.2e+18)) then
Code := 1;
end;
end;
fsubDate :
begin
DateMask := OvcIntlSup.InternationalDate(True);
if Length(Value) <> Length(DateMask) then
R.rtDate := BadDate
else
R.rtDate := OvcIntlSup.DateStringToDate(DateMask, Value, GetEpoch);
if R.rtDate = BadDate then
Code := 1;
end;
fsubTime :
begin
TimeMask := OvcIntlSup.InternationalTime(False);
if Length(Value) <> Length(TimeMask) then
R.rtTime := BadTime
else
R.rtTime := OvcIntlSup.TimeStringToTime(TimeMask, Value);
if R.rtTime = BadTime then
Code := 1;
end;
end;
Result := Code = 0;
end;
procedure TOvcBaseEntryField.efReadRangeHi(Stream : TStream);
{-called to read the high range from the stream}
begin
Stream.Read(efRangeHi, SizeOf(TRangeType));
end;
procedure TOvcBaseEntryField.efReadRangeLo(Stream : TStream);
{-called to read the low range from the stream}
begin
Stream.Read(efRangeLo, SizeOf(TRangeType));
end;
function TOvcBaseEntryField.efTransfer(DataPtr : Pointer; TransferFlag : Word) : Word;
{-transfer data to or from the field}
begin
if (TransferFlag <> otf_SizeData) and not (csDesigning in ComponentState) then
Result := efTransferPrim(DataPtr, TransferFlag)
else
Result := efDataSize;
{descendant classes will do the actual transfering of data}
end;
function TOvcBaseEntryField.efTransferPrim(DataPtr : Pointer; TransferFlag : Word) : Word;
{-reset for new data in field}
begin
Result := efDataSize;
if TransferFlag = otf_SetData then begin
if not (sefValidating in sefOptions) then begin
Exclude(sefOptions, sefRetainPos);
if sefHaveFocus in sefOptions then begin
efResetCaret;
efPositionCaret(True);
{if we are doing a transfer due to a GetValue}
{validation, don't reset selection}
if not (sefGettingValue in sefOptions) then
SetSelection(0, MaxEditLen);
end else
Exclude(sefOptions, sefInvalid);
{clear modified flags}
Exclude(sefOptions, sefModified);
Exclude(sefOptions, sefEverModified);
Invalidate;
end;
end;
end;
procedure TOvcBaseEntryField.efWriteRangeHi(Stream : TStream);
{-called to store the high range on the stream}
begin
Stream.Write(efRangeHi, SizeOf(TRangeType));
end;
procedure TOvcBaseEntryField.efWriteRangeLo(Stream : TStream);
{-called to store the low range on the stream}
begin
Stream.Write(efRangeLo, SizeOf(TRangeType));
end;
procedure TOvcBaseEntryField.EMGetModify(var Msg : TMessage);
begin
Msg.Result := 0;
if sefModified in sefOptions then
Msg.Result := 1;
end;
procedure TOvcBaseEntryField.EMGetSel(var Msg : TMessage);
begin
{Return this info in Msg as well as in Result}
with Msg do begin
if LPDWORD(wParam) <> nil then
LPDWORD(wParam)^ := efSelStart;
if LPDWORD(lParam) <> nil then
LPDWORD(lParam)^ := efSelEnd;
end;
Msg.Result := MakeLong(efSelStart, efSelEnd);
end;
procedure TOvcBaseEntryField.EMSetModify(var Msg : TMessage);
begin
if Msg.wParam > 0 then begin
Include(sefOptions, sefModified);
Include(sefOptions, sefEverModified);
end else
Exclude(sefOptions, sefModified);
end;
procedure TOvcBaseEntryField.EMSetSel(var Msg : TMessage);
begin
with Msg do begin
if lParamLo = $FFFF then
SetSelection(0, 0)
else if (lParamLo = 0) and (lParamHi = $FFFF) then
SetSelection(0, MaxEditLen)
else if lParamHi >= lParamLo then
SetSelection(lParamLo, lParamHi);
end;
Invalidate;
end;
function TOvcBaseEntryField.GetAsBoolean : Boolean;
{-returns the field value as a Boolean Value}
begin
Result := False;
if (efDataType mod fcpDivisor) in [fsubBoolean, fsubYesNo] then
FLastError := GetValue(Result)
else
raise EInvalidDataType.Create;
end;
function TOvcBaseEntryField.GetAsCents : LongInt;
{-returns the field value as a LongInt Value representing pennies}
const
C = 100.0;
var
Re : Real;
Db : Double;
Si : Single;
Ex : Extended;
begin
Result := 0;
case (efDataType mod fcpDivisor) of
fsubReal :
begin
FLastError := GetValue(Re);
if FLastError = 0 then
Result := Round(Re * C);
end;
fsubDouble :
begin
FLastError := GetValue(Db);
if FLastError = 0 then
Result := Round(Db * C);
end;
fsubSingle :
begin
FLastError := GetValue(Si);
if FLastError = 0 then
Result := Round(Si * C);
end;
fsubExtended :
begin
FLastError := GetValue(Ex);
if FLastError = 0 then
Result := Round(Ex * C);
end;
else
raise EInvalidDataType.Create;
end;
end;
function TOvcBaseEntryField.GetAsDateTime : TDateTime;
{-returns the field value as a Delphi DateTime Value}
var
D : TStDate;
T : TStTime;
begin
case (efDataType mod fcpDivisor) of
fsubDate :
begin
FLastError := GetValue(D);
if FLastError <> 0 then
Result := 0
else
Result := StDateToDateTime(D);
end;
fsubTime :
begin
FLastError := GetValue(T);
if FLastError <> 0 then
Result := 0
else
Result := StTimeToDateTime(T);
end;
else
raise EInvalidDataType.Create;
end;
end;
function TOvcBaseEntryField.GetAsExtended : Extended;
{-returns the field value as an Extended Value}
var
Ex : Extended;
Co : Comp absolute Ex;
Db : Double;
Sg : Single absolute Db;
Re : Real absolute Db;
Li : Longint;
Wo : Word absolute Li;
It : SmallInt absolute Li;
By : Byte absolute Li;
Si : ShortInt absolute Li;
begin
Result := 0;
case efDataType mod fcpDivisor of
fsubExtended :
begin
FLastError := GetValue(Ex);
if FLastError = 0 then
Result := Ex;
end;
fsubComp :
begin
FLastError := GetValue(Co);
if FLastError = 0 then
Result := Co;
end;
fsubReal :
begin
FLastError := GetValue(Re);
if FLastError = 0 then
Result := Re;
end;
fsubDouble :
begin
FLastError := GetValue(Db);
if FLastError = 0 then
Result := Db;
end;
fsubSingle :
begin
FLastError := GetValue(Sg);
if FLastError = 0 then
Result := Sg;
end;
fsubLongInt :
begin
FLastError := GetValue(Li);
if FLastError = 0 then
Result := Li;
end;
fsubWord :
begin
FLastError := GetValue(Wo);
if FLastError = 0 then
Result := Wo;
end;
fsubInteger :
begin
FLastError := GetValue(It);
if FLastError = 0 then
Result := It;
end;
fsubByte :
begin
FLastError := GetValue(By);
if FLastError = 0 then
Result := By;
end;
fsubShortInt :
begin
FLastError := GetValue(Si);
if FLastError = 0 then
Result := Si;
end;
else
raise EInvalidDataType.Create;
end;
end;
function TOvcBaseEntryField.GetAsFloat : Double;
{-returns the field value as a Double Value}
var
Db : Double;
Sg : Single absolute Db;
Re : Real absolute Db;
Ex : Extended;
Co : Comp absolute Ex;
Li : LongInt;
Wo : Word absolute Li;
It : SmallInt absolute Li;
By : Byte absolute Li;
Si : ShortInt absolute Li;
begin
Result := 0;
case efDataType mod fcpDivisor of
fsubReal :
begin
FLastError := GetValue(Re);
if FLastError = 0 then
Result := Re;
end;
fsubDouble :
begin
FLastError := GetValue(Db);
if FLastError = 0 then
Result := Db;
end;
fsubSingle :
begin
FLastError := GetValue(Sg);
if FLastError = 0 then
Result := Sg;
end;
fsubExtended :
begin
FLastError := GetValue(Ex);
if FLastError = 0 then
Result := Ex;
end;
fsubComp :
begin
FLastError := GetValue(Co);
if FLastError = 0 then
Result := Co;
end;
fsubLongInt :
begin
FLastError := GetValue(Li);
if FLastError = 0 then
Result := Li;
end;
fsubWord :
begin
FLastError := GetValue(Wo);
if FLastError = 0 then
Result := Wo;
end;
fsubInteger :
begin
FLastError := GetValue(It);
if FLastError = 0 then
Result := It;
end;
fsubByte :
begin
FLastError := GetValue(By);
if FLastError = 0 then
Result := By;
end;
fsubShortInt :
begin
FLastError := GetValue(Si);
if FLastError = 0 then
Result := Si;
end;
else
raise EInvalidDataType.Create;
end;
end;
function TOvcBaseEntryField.GetAsInteger : Longint;
{-returns the field value as a LongInt Value}
var
Li : Longint;
Wo : Word absolute Li;
It : SmallInt absolute Li;
By : Byte absolute Li;
Si : ShortInt absolute Li;
begin
Result := 0;
case efDataType mod fcpDivisor of
fsubLongInt :
begin
FLastError := GetValue(Li);
if FLastError = 0 then
Result := Li;
end;
fsubWord :
begin
FLastError := GetValue(Wo);
if FLastError = 0 then
Result := Wo;
end;
fsubInteger :
begin
FLastError := GetValue(It);
if FLastError = 0 then
Result := It;
end;
fsubByte :
begin
FLastError := GetValue(By);
if FLastError = 0 then
Result := By;
end;
fsubShortInt :
begin
FLastError := GetValue(Si);
if FLastError = 0 then
Result := Si;
end;
else
raise EInvalidDataType.Create;
end;
end;
function TOvcBaseEntryField.GetAsString : string;
{-return the field value as a string value}
var
Buf : TEditString;
S : string[MaxEditLen];
begin
Result := '';
if (efDataType mod fcpDivisor) = fsubString then begin
FLastError := GetValue(S);
if FLastError = 0 then
Result := S;
end else begin
StrCopy(Buf, efEditSt);
if efoTrimBlanks in Options then
TrimAllSpacesPChar(Buf);
Result := StrPas(Buf);
FLastError := 0;
end;
end;
function TOvcBaseEntryField.GetAsVariant : Variant;
{return the field value as a Variant value}
begin
case efDataType mod fcpDivisor of
fsubBoolean : Result := GetAsBoolean;
fsubYesNo : Result := GetAsBoolean;
fsubLongInt : Result := GetAsInteger;
fsubWord : Result := GetAsInteger;
fsubInteger : Result := GetAsInteger;
fsubByte : Result := GetAsInteger;
fsubShortInt : Result := GetAsInteger;
fsubReal : Result := GetAsFloat;
fsubDouble : Result := GetAsFloat;
fsubSingle : Result := GetAsFloat;
fsubExtended : Result := GetAsExtended;
fsubComp : Result := GetAsExtended;
else
Result := GetAsString;
end;
end;
function TOvcBaseEntryField.GetAsStDate : TStDate;
{-returns the field value as a Date Value}
begin
if (efDataType mod fcpDivisor) = fsubDate then begin
FLastError := GetValue(Result);
if FLastError <> 0 then
Result := BadDate;
end else
raise EInvalidDataType.Create;
end;
function TOvcBaseEntryField.GetAsStTime : TStTime;
{-returns the field value as a Time Value}
begin
if (efDataType mod fcpDivisor) = fsubTime then begin
FLastError := GetValue(Result);
if FLastError <> 0 then
Result := BadTime;
end else
raise EInvalidDataType.Create;
end;
function TOvcBaseEntryField.GetCurrentPos : Integer;
{-get position of the caret within the field}
begin
if sefHaveFocus in sefOptions then
Result := efHPos
else
Result := -1;
end;
function TOvcBaseEntryField.GetDataSize : Word;
{-return the size of the data for this field}
begin
if efDataSize = 0 then
efInitializeDataSize;
Result := efDataSize;
end;
function TOvcBaseEntryField.GetDisplayString : string;
{-return the display string}
var
Buf : TEditString;
begin
efGetDisplayString(Buf, MaxEditLen);
Result := StrPas(Buf);
end;
function TOvcBaseEntryField.GetEditString : string;
{-return a string containing the edit text}
var
Buf : TEditString;
begin
StrLCopy(Buf, efEditSt, MaxEditLen);
Result := StrPas(Buf);
end;
function TOvcBaseEntryField.GetEpoch : Integer;
begin
Result := FEpoch;
{avoid writing controller's epoch value}
if csWriting in ComponentState then
Exit;
if Assigned(FOnGetEpoch) then
FOnGetEpoch(Self, Result);
if (Result = 0) and ControllerAssigned then
Result := Controller.Epoch;
end;
function TOvcBaseEntryField.GetEverModified : Boolean;
{-return true if this field has ever been modified}
begin
Result := (sefEverModified in sefOptions) or (sefModified in sefOptions);
end;
function TOvcBaseEntryField.GetInsCaretType : TOvcCaret;
{-return the current caret type}
begin
Result := efCaret.InsCaretType;
end;
function TOvcBaseEntryField.GetInsertMode : Boolean;
{-return the controller's insert mode state}
begin
if ControllerAssigned then
Result := Controller.InsertMode
else
Result := sefInsert in sefOptions;
end;
function TOvcBaseEntryField.GetModified : Boolean;
{-return true if this field is modified}
begin
Result := sefModified in sefOptions;
end;
function TOvcBaseEntryField.GetOvrCaretType : TOvcCaret;
{-return the current caret type}
begin
Result := efCaret.OvrCaretType;
end;
function TOvcBaseEntryField.GetRangeHiStr : string;
{-get the high field range as string value}
begin
Result := efRangeToStRange(efRangeHi);
end;
function TOvcBaseEntryField.GetRangeLoStr : string;
{-get the low field range as string value}
begin
Result := efRangeToStRange(efRangeLo);
end;
function TOvcBaseEntryField.GetSelLength : Integer;
{-return the length of the currently selected text}
begin
Result := efSelEnd - efSelStart;
end;
function TOvcBaseEntryField.GetSelStart : Integer;
{-return the starting position of the selection, if any}
begin
Result := efSelStart;
end;
function TOvcBaseEntryField.GetSelText : string;
{-return the currently selected text}
var
Len : Integer;
begin
Result := '';
Len := efSelEnd - efSelStart;
if Len > 0 then begin
{limit length to max edit length}
if Len > MaxEditLen then
Len := MaxEditLen;
SetLength(Result, Len);
StrLCopy(@Result[1], @efEditSt[efSelStart], Len);
end;
end;
function TOvcBaseEntryField.FieldIsEmpty : Boolean;
{-return True if the field is completely empty}
begin
HandleNeeded;
Result := efFieldIsEmpty;
end;
function TOvcBaseEntryField.GetStrippedEditString : string;
{-return edit string stripped of literals and semi-literals}
begin
Result := GetEditString;
end;
function TOvcBaseEntryField.GetValue(var Data) : Word;
{-returns the current field value in Data. Result is 0 or error code}
begin
{flag to inform validate and transfer}
{methods that we are retrieving a value}
Include(sefOptions, sefGettingValue);
try
Result := efValidateField;
if Result <> 0 then
Exit;
case efDataType mod fcpDivisor of
fsubString : efTransfer(@ShortString(Data), otf_GetData);
fsubChar : efTransfer(@AnsiChar(Data), otf_GetData);
fsubBoolean : efTransfer(@Boolean(Data), otf_GetData);
fsubYesNo : efTransfer(@Boolean(Data), otf_GetData);
fsubLongInt : efTransfer(@LongInt(Data), otf_GetData);
fsubWord : efTransfer(@Word(Data), otf_GetData);
fsubInteger : efTransfer(@SmallInt(Data), otf_GetData);
fsubByte : efTransfer(@Byte(Data), otf_GetData);
fsubShortInt : efTransfer(@ShortInt(Data), otf_GetData);
fsubReal : efTransfer(@Real(Data), otf_GetData);
fsubExtended : efTransfer(@Extended(Data), otf_GetData);
fsubDouble : efTransfer(@Double(Data), otf_GetData);
fsubSingle : efTransfer(@Single(Data), otf_GetData);
fsubComp : efTransfer(@Comp(Data), otf_GetData);
fsubDate : efTransfer(@TStDate(Data), otf_GetData);
fsubTime : efTransfer(@TStTime(Data), otf_GetData);
else
raise EOvcException.Create(GetOrphStr(SCInvalidParamValue));
end;
finally
Exclude(sefOptions, sefGettingValue);
end;
end;
procedure TOvcBaseEntryField.IncreaseValue(Wrap : Boolean; Delta : Double);
{-increase the value of the field by Delta, wrapping if enabled}
begin
SendMessage(Handle, WM_SETREDRAW, 0, 0);
efIncDecValue(Wrap, +Delta);
SetSelection(0, 0);
SendMessage(Handle, WM_SETREDRAW, 1, 0);
Refresh;
end;
function TOvcBaseEntryField.IsValid : Boolean;
{-returns true if the field is not marked as invalid}
begin
Result := not (sefInvalid in sefOptions);
end;
procedure TOvcBaseEntryField.MergeWithPicture(const S : string);
{-combines S with the picture mask and updates the edit string}
begin
StrPLCopy(efEditSt, S, MaxLength);
end;
procedure TOvcBaseEntryField.MoveCaret(Delta : Integer);
{-moves the caret to the right or left Value positions}
var
I : Integer;
Msg : TMessage;
begin
if not (sefHaveFocus in sefOptions) then
Exit;
FillChar(Msg, SizeOf(Msg), 0);
if Delta > 0 then begin
for I := 1 to Delta do
efPerformEdit(Msg, ccRight)
end else if Delta < 0 then begin
for I := 1 to Abs(Delta) do
efPerformEdit(Msg, ccLeft)
end;
end;
procedure TOvcBaseEntryField.MoveCaretToEnd;
{-move the caret to the end of the field}
begin
efCaretToEnd;
end;
procedure TOvcBaseEntryField.MoveCaretToStart;
{-move the caret to the beginning of the field}
begin
efCaretToStart;
end;
procedure TOvcBaseEntryField.OMGetDataSize(var Msg : TMessage);
{-return the fields data size}
begin
Msg.Result := DataSize;
end;
procedure TOvcBaseEntryField.OMReportError(var Msg : TOMReportError);
{-report the error}
var
P : string;
begin
if Msg.Error = 0 then
Exit;
case Msg.Error of
oeRangeError : P := GetOrphStr(SCRangeError);
oeInvalidNumber : P := GetOrphStr(SCInvalidNumber);
oeRequiredField : P := GetOrphStr(SCRequiredField);
oeInvalidDate : P := GetOrphStr(SCInvalidDate);
oeInvalidTime : P := GetOrphStr(SCInvalidTime);
oeBlanksInField : P := GetOrphStr(SCBlanksInField);
oePartialEntry : P := GetOrphStr(SCPartialEntry);
else
if Msg.Error >= oeCustomError then
P := Controller.ErrorText
else
P := GetOrphStr(SCDefaultEntryErrorText);
end;
{update the error text}
if P <> Controller.ErrorText then
Controller.ErrorText := P;
{do error notification}
DoOnError(Msg.Error, P);
end;
procedure TOvcBaseEntryField.Paint;
{-draw the entry field control}
var
hCBM : hBitmap;
MemDC : hDC;
CR : TRect;
begin
inherited Paint;
{get dimensions of client area}
CR.Top := 0; CR.Left := 0;
CR.Right := Width; CR.Bottom := Height;
{create a compatible display context and bitmap}
MemDC := CreateCompatibleDC(Canvas.Handle);
hCBM := CreateCompatibleBitmap(Canvas.Handle, CR.Right, CR.Bottom);
SelectObject(MemDC, hCBM);
SetMapMode(MemDC, GetMapMode(Canvas.Handle));
{set text alignment}
SetTextAlign(MemDC, TA_LEFT or TA_TOP);
{call our paint routine}
efPaintPrim(MemDC, CR, efHOffset);
{copy everything to the original display context}
BitBlt(Canvas.Handle, 0, 0, CR.Right, CR.Bottom, MemDC, 0, 0, SrcCopy);
efPaintBorders;
{dispose of the bitmap and the extra display context}
DeleteDC(MemDC);
DeleteObject(hCBM);
end;
procedure TOvcBaseEntryField.efPaintBorders;
var
R : TRect;
C : TCanvas;
begin
R.Left := 0;
R.Top := 0;
R.Right := Width;
R.Bottom := Height;
C := Canvas;
if (FBorders.LeftBorder <> nil) then begin
if (FBorders.LeftBorder.Enabled) then begin
C.Pen.Color := FBorders.LeftBorder.PenColor;
C.Pen.Width := FBorders.LeftBorder.PenWidth;
C.Pen.Style := FBorders.LeftBorder.PenStyle;
C.MoveTo(R.Left + (FBorders.LeftBorder.PenWidth div 2), R.Top);
C.LineTo(R.Left + (FBorders.LeftBorder.PenWidth div 2), R.Bottom);
end;
end;
if (FBorders.RightBorder <> nil) then begin
if (FBorders.RightBorder.Enabled) then begin
C.Pen.Color := FBorders.RightBorder.PenColor;
C.Pen.Width := FBorders.RightBorder.PenWidth;
C.Pen.Style := FBorders.RightBorder.PenStyle;
if ((FBorders.RightBorder.PenWidth mod 2) = 0) then begin
C.MoveTo(R.Right - (FBorders.RightBorder.PenWidth div 2), R.Top);
C.LineTo(R.Right - (FBorders.RightBorder.PenWidth div 2), R.Bottom);
end else begin
C.MoveTo(R.Right - (FBorders.RightBorder.PenWidth div 2) - 1, R.Top);
C.LineTo(R.Right - (FBorders.RightBorder.PenWidth div 2) - 1, R.Bottom);
end;
end;
end;
if (FBorders.TopBorder <> nil) then begin
if (FBorders.TopBorder.Enabled) then begin
C.Pen.Color := FBorders.TopBorder.PenColor;
C.Pen.Width := FBorders.TopBorder.PenWidth;
C.Pen.Style := FBorders.TopBorder.PenStyle;
C.MoveTo(R.Left, R.Top + (FBorders.TopBorder.PenWidth div 2));
C.LineTo(R.Right, R.Top + (FBorders.TopBorder.PenWidth div 2));
end;
end;
if (FBorders.BottomBorder <> nil) then begin
if (FBorders.BottomBorder.Enabled) then begin
C.Pen.Color := FBorders.BottomBorder.PenColor;
C.Pen.Width := FBorders.BottomBorder.PenWidth;
C.Pen.Style := FBorders.BottomBorder.PenStyle;
if ((FBorders.BottomBorder.PenWidth mod 2) = 0) then begin
C.MoveTo(R.Left, R.Bottom - (FBorders.BottomBorder.PenWidth div 2));
C.LineTo(R.Right, R.Bottom - (FBorders.BottomBorder.PenWidth div 2));
end else begin
C.MoveTo(R.Left, R.Bottom - (FBorders.BottomBorder.PenWidth div 2) - 1);
C.LineTo(R.Right, R.Bottom - (FBorders.BottomBorder.PenWidth div 2) - 1);
end;
end;
end;
end;
procedure TOvcBaseEntryField.PasteFromClipboard;
{-pastes the contents of the clipboard in the edit field}
begin
if HandleAllocated then
Perform(WM_PASTE, 0, 0);
end;
procedure TOvcBaseEntryField.ProcessCommand(Cmd, CharCode : Word);
{-process the specified command}
var
Msg : TMessage;
begin
FillChar(Msg, SizeOf(Msg), #0);
Msg.wParam := CharCode;
efPerformEdit(Msg, Cmd);
end;
procedure TOvcBaseEntryField.ResetCaret;
{-move the caret to the beginning or end of the field, as appropriate}
begin
efResetCaret;
end;
procedure TOvcBaseEntryField.Restore;
{-restore the previous contents of the field}
begin
if efSaveEdit = nil then
Exit;
StrCopy(efEditSt, efSaveEdit);
efResetCaret;
SetSelection(0, MaxEditLen);
{clear modified flag}
Exclude(sefOptions, sefModified);
Repaint;
DoOnChange;
end;
procedure TOvcBaseEntryField.SelectAll;
{-selects the entire contents of the edit field}
begin
if HandleAllocated then
Perform(EM_SETSEL, 1, LongInt($FFFF0000));
end;
procedure TOvcBaseEntryField.SetAsBoolean(Value : Boolean);
{-sets the field value to a Boolean Value}
begin
if (efDataType mod fcpDivisor) in [fsubBoolean, fsubYesNo] then
SetValue(Value)
else
raise EInvalidDataType.Create;
end;
procedure TOvcBaseEntryField.SetAsCents(Value : LongInt);
{-sets the field value given a LongInt Value representing pennies}
const
C = 100.0;
var
Re : Real;
Db : Double;
Si : Single;
Ex : Extended;
begin
case efDataType mod fcpDivisor of
fsubReal :
begin
Re := Value / C;
SetValue(Re);
end;
fsubDouble :
begin
Db := Value / C;
SetValue(Db);
end;
fsubSingle :
begin
Si := Value / C;
SetValue(Si);
end;
fsubExtended :
begin
Ex := Value / C;
SetValue(Ex);
end;
else
raise EInvalidDataType.Create;
end;
end;
procedure TOvcBaseEntryField.SetAsDateTime(Value : TDateTime);
{-sets the field value to a Delphi DateTime value}
var
D : TStDate;
T : TStTime;
Day,
Month,
Year : Word;
Hour,
Min,
Sec,
MSec : Word;
begin
case (efDataType mod fcpDivisor) of
fsubDate :
begin
{$IFDEF ZeroDateAsNull}
if Value = 0 then
Value := BadDate;
{$ENDIF}
DecodeDate(Value, Year, Month, Day);
D := DMYToStDate(Day, Month, Year, GetEpoch);
if D = DateTimeToStDate(BadDate) then
D := BadDate;
SetValue(D);
end;
fsubTime :
begin
DecodeTime(Value, Hour, Min, Sec, MSec);
T := HMSToStTime(Hour, Min, Sec);
if (T <> 0) and (T = DateTimeToStTime(BadTime)) then
T := BadTime;
SetValue(T);
end;
else
raise EInvalidDataType.Create;
end;
end;
procedure TOvcBaseEntryField.SetAsExtended(Value : Extended);
{-sets the field value to an Extended Value}
var
Co : Comp;
begin
case efDataType mod fcpDivisor of
fsubExtended :
SetValue(Value);
fsubComp :
begin
Co := Trunc(Value);
SetValue(Co);
end;
else
raise EInvalidDataType.Create;
end;
end;
procedure TOvcBaseEntryField.SetAsFloat(Value : Double);
{-sets the field value to a Double Value}
var
Sg : Single;
Re : Real;
Co : Comp;
Ex : Extended;
begin
case efDataType mod fcpDivisor of
fsubReal :
begin
Re := Value;
SetValue(Re);
end;
fsubDouble :
SetValue(Value);
fsubSingle :
begin
Sg := Value;
SetValue(Sg);
end;
fsubExtended :
begin
Ex := Value;
SetValue(Ex);
end;
fsubComp :
begin
Co := Trunc(Value);
SetValue(Co);
end;
else
raise EInvalidDataType.Create;
end;
end;
procedure TOvcBaseEntryField.SetAsInteger(Value : Longint);
{-sets the field value to a LongInt Value}
var
Wo : Word;
It : SmallInt absolute Wo;
By : Byte absolute Wo;
Si : ShortInt absolute Wo;
begin
case efDataType mod fcpDivisor of
fsubLongInt :
SetValue(Value);
fsubWord :
begin
Wo := LOWORD(Value);
SetValue(Wo);
end;
fsubInteger :
begin
It := SmallInt(LOWORD(Value));
SetValue(It);
end;
fsubByte :
begin
By := Lo(LOWORD(Value));
SetValue(By);
end;
fsubShortInt :
begin
Si := ShortInt(Lo(LOWORD(Value)));
SetValue(Si);
end;
else
raise EInvalidDataType.Create;
end;
end;
procedure TOvcBaseEntryField.SetAsString(const Value : string);
{-sets the field value to a String Value}
var
R : TRangeType;
fSub : Byte;
B : Boolean;
Ch : AnsiChar;
S : string[MaxEditLen];
begin
if sefUserValidating in sefOptions then
Exit;
fSub := (efDataType mod fcpDivisor);
if fSub = fsubString then begin
S := Value;
SetValue(S)
end else if fSub in [fsubBoolean, fsubYesNo] then begin
B := False;
if Length(Value) > 0 then begin
Ch := UpCaseChar(Value[1]);
B := (Ch = FIntlSup.TrueChar) or (Ch = FIntlSup.YesChar);
end;
SetValue(B);
end else begin
{use range conversion routines to process string assignment}
if efStRangeToRange(Value, R) then begin
case (efDataType mod fcpDivisor) of
{assign result to proper sub-field in range type var}
fsubWord : R.rtWord := R.rtLong;
fsubInteger : R.rtInt := R.rtLong;
fsubByte : R.rtByte := R.rtLong;
fsubShortInt : R.rtSht := R.rtLong;
fsubDouble : R.rtDbl := R.rtExt;
fsubSingle : R.rtSgl := R.rtExt;
fsubComp : R.rtComp := R.rtExt;
end;
SetValue(R);
end else
raise EEntryFieldError.Create(GetOrphStr(SCInvalidNumber));
end;
end;
procedure TOvcBaseEntryField.SetAsVariant(Value : Variant);
{-sets the field value to a Variant value}
var
fSub : Byte;
begin
{what data type is this field}
fSub := efDataType mod fcpDivisor;
case VarType(Value) of
varSmallInt,
varInteger :
case fSub of
fsubByte,
fsubShortInt,
fsubWord,
fsubInteger,
fsubLongInt : SetAsInteger(Value);
else
{try to convert it into a string}
SetAsString(VarAsType(Value, varString));
end;
varSingle,
varDouble,
varCurrency :
case fSub of
fsubReal,
fsubDouble,
fsubSingle,
fsubExtended,
fsubComp : SetAsFloat(Value);
else
{try to convert it into a string}
SetAsString(VarAsType(Value, varString));
end;
varDate :
if fSub = fsubDate then
SetAsDateTime(Value)
else
{try to convert it into a string}
SetAsString(VarAsType(Value, varString));
varBoolean :
if fSub in [fsubBoolean, fsubYesNo] then
SetAsBoolean(Value)
else
{try to convert it into a string}
SetAsString(VarAsType(Value, varString));
varString : SetAsString(Value);
end;
end;
procedure TOvcBaseEntryField.SetAsStDate(Value : TStDate);
{-sets the field value to a Date Value}
begin
if (efDataType mod fcpDivisor) = fsubDate then
SetValue(Value)
else
raise EInvalidDataType.Create;
end;
procedure TOvcBaseEntryField.SetAsStTime(Value : TStTime);
{-sets the field value to a Time Value}
begin
if efDataType mod fcpDivisor = fsubTime then
SetValue(Value)
else
raise EInvalidDataType.Create;
end;
procedure TOvcBaseEntryField.SetAutoSize(Value : Boolean);
begin
if Value <> FAutoSize then begin
FAutoSize := Value;
if not (csLoading in ComponentState) then
efAdjustSize; {adjust height based on font}
end;
end;
procedure TOvcBaseEntryField.SetBorderStyle(Value : TBorderStyle);
begin
if FBorderStyle <> Value then begin
FBorderStyle := Value;
{$IFNDEF LCL}
RecreateWnd;
{$ELSE}
MyMisc.RecreateWnd(Self);
{$ENDIF}
end;
end;
procedure TOvcBaseEntryField.SetBounds(ALeft, ATop, AWidth, AHeight : Integer);
begin
if FAutoSize and (AHeight <> Height) and
not (csLoading in ComponentState) then
FAutoSize := False;
inherited SetBounds(ALeft, ATop, AWidth, AHeight);
efCalcTopMargin;
if HandleAllocated and (GetFocus = Handle) then
efPositionCaret(False); {adjust caret for new size}
Refresh;
end;
procedure TOvcBaseEntryField.SetDecimalPlaces(Value : Byte);
{-set the number of decimal places for the edit field}
begin
if Value <> FDecimalPlaces then begin
FDecimalPlaces := Value;
{$IFNDEF LCL}
RecreateWnd;
{$ELSE}
MyMisc.RecreateWnd(Self);
{$ENDIF}
end;
end;
procedure TOvcBaseEntryField.SetEpoch(Value : Integer);
begin
if Value <> FEpoch then
if (Value = 0) or ((Value >= MinYear) and (Value <= MaxYear)) then
FEpoch := Value;
if ControllerAssigned and (FEpoch = Controller.Epoch) then
FEpoch := 0;
end;
procedure TOvcBaseEntryField.SetEverModified(Value : Boolean);
{-set the EverModified flag}
begin
if Value then
Include(sefOptions, sefEverModified)
else begin
Exclude(sefOptions, sefEverModified);
{clear sefModified also}
Exclude(sefOptions, sefModified);
end;
end;
procedure TOvcBaseEntryField.SetInsCaretType(const Value : TOvcCaret);
{-set the type of caret to use}
begin
if Value <> efCaret.InsCaretType then
efCaret.InsCaretType := Value;
end;
procedure TOvcBaseEntryField.SetIntlSupport(Value : TOvcIntlSup);
{-set the international support object this field will use}
begin
if Assigned(Value) then
FIntlSup := Value
else
FIntlSup := OvcIntlSup;
end;
procedure TOvcBaseEntryField.SetMaxLength(Value : Word);
{-set the maximum length of the edit field}
begin
if csLoading in ComponentState then
FMaxLength := Value
else if (FMaxLength <> Value) and
(Value > 0) and
(Value <= MaxEditLen) and
(Value >= efPicLen) then begin
FMaxLength := Value;
if StrLen(efEditSt) > FMaxLength then
efEditSt[FMaxLength] := #0;
{$IFNDEF LCL}
RecreateWnd;
{$ELSE}
MyMisc.RecreateWnd(Self);
{$ENDIF}
end;
end;
procedure TOvcBaseEntryField.SetModified(Value : Boolean);
{-set the modified flag}
begin
if Value then begin
Include(sefOptions, sefModified);
{set sefEverModified also}
Include(sefOptions, sefEverModified);
end else
Exclude(sefOptions, sefModified);
end;
procedure TOvcBaseEntryField.SetOptions(Value : TOvcEntryFieldOptions);
{-set the options flags}
begin
if Value <> Options then begin
FOptions := Value;
if (efoForceInsert in FOptions) then
Exclude(FOptions, efoForceOvertype);
if (efoForceOvertype in FOptions) then
Exclude(FOptions, efoForceInsert);
if (efoRightJustify in FOptions) then
if efDataType mod fcpDivisor = fsubString then
Include(FOptions, efoTrimBlanks);
if (efoRightAlign in FOptions) then
efPositionCaret(True);
if not (efoTrimBlanks in FOptions) then begin
{if this is a string picture field then turn off right justify}
if efFieldClass = fcPicture then
if efDataType mod fcpDivisor = fsubString then
Exclude(FOptions, efoRightJustify);
end;
end;
efRemoveBadOptions;
Refresh;
end;
procedure TOvcBaseEntryField.SetOvrCaretType(const Value : TOvcCaret);
{-set the type of caret to use}
begin
if Value <> efCaret.OvrCaretType then
efCaret.OvrCaretType := Value;
end;
procedure TOvcBaseEntryField.SetPadChar(Value : AnsiChar);
{-set the character used to pad the end of the edit string}
begin
if Value <> FPadChar then begin
FPadChar := Value;
Refresh;
end;
end;
procedure TOvcBaseEntryField.SetPasswordChar(Value : AnsiChar);
{-set the character used to mask password entry}
begin
if FPasswordChar <> Value then begin
FPasswordChar := Value;
if Value = #0 then
Exclude(FOptions, efoPasswordMode);
Refresh;
end;
end;
procedure TOvcBaseEntryField.SetSelLength(Value : Integer);
{-set the extent of the selected text}
begin
SetSelection(efSelStart, efSelStart + Value);
Refresh;
end;
procedure TOvcBaseEntryField.SetInitialValue;
{-resets the field value to its initial value}
begin
efSetInitialValue;
end;
procedure TOvcBaseEntryField.SetInsertMode(Value : Boolean);
{-changes the field's insert mode}
begin
if Value <> (sefInsert in sefOptions) then begin
if Value then
Include(sefOptions, sefInsert)
else
Exclude(sefOptions, sefInsert);
Controller.InsertMode := Value;
efCaret.InsertMode := Value;
end;
end;
procedure TOvcBaseEntryField.SetRangeHi(const Value : TRangeType);
{-set the high range for this field}
begin
case efDataType mod fcpDivisor of
fsubLongInt : efRangeHi.rtLong := Value.rtLong;
fsubWord : efRangeHi.rtLong := Value.rtWord;
fsubInteger : efRangeHi.rtLong := Value.rtInt;
fsubByte : efRangeHi.rtLong := Value.rtByte;
fsubShortInt : efRangeHi.rtLong := Value.rtSht;
fsubExtended : efRangeHi.rtExt := Value.rtExt;
fsubDouble : efRangeHi.rtExt := Value.rtDbl;
fsubSingle : efRangeHi.rtExt := Value.rtSgl;
fsubComp : efRangeHi.rtExt := Value.rtComp;
else
efRangeHi := Value;
end;
if (ValidateContents(true) > 0)
and (Parent <> nil)
and (Parent.Visible)
and (Parent.Enabled) then
SetFocus;
end;
procedure TOvcBaseEntryField.SetRangeHiStr(const Value : string);
{-set the high field range from a string value}
var
R : TRangeType;
begin
R := efRangeHi;
if not (csLoading in ComponentState) then
if not efStRangeToRange(Value, R) then
raise EInvalidRangeValue.Create(efDataType mod fcpDivisor);
efRangeHi := R;
if (ValidateContents(true) > 0)
and (Parent <> nil)
and (Parent.Visible)
and (Parent.Enabled) then
SetFocus;
end;
procedure TOvcBaseEntryField.SetRangeLo(const Value : TRangeType);
{-set the low range for this field}
begin
case efDataType mod fcpDivisor of
fsubLongInt : efRangeLo.rtLong := Value.rtLong;
fsubWord : efRangeLo.rtLong := Value.rtWord;
fsubInteger : efRangeLo.rtLong := Value.rtInt;
fsubByte : efRangeLo.rtLong := Value.rtByte;
fsubShortInt : efRangeLo.rtLong := Value.rtSht;
fsubExtended : efRangeLo.rtExt := Value.rtExt;
fsubDouble : efRangeLo.rtExt := Value.rtDbl;
fsubSingle : efRangeLo.rtExt := Value.rtSgl;
fsubComp : efRangeLo.rtExt := Value.rtComp;
else
efRangeLo := Value;
end;
if (ValidateContents(true) > 0)
and (Parent <> nil)
and (Parent.Visible)
and (Parent.Enabled) then
SetFocus;
end;
procedure TOvcBaseEntryField.SetRangeLoStr(const Value : string);
{-set the low field range from a string value}
var
R : TRangeType;
begin
R := efRangeLo;
if not (csLoading in ComponentState) then
if not efStRangeToRange(Value, R) then
raise EInvalidRangeValue.Create(efDataType mod fcpDivisor);
efRangeLo := R;
if (ValidateContents(true) > 0)
and (Parent <> nil)
and (Parent.Visible)
and (Parent.Enabled) then
SetFocus;
end;
procedure TOvcBaseEntryField.SetSelStart(Value : Integer);
{-set the starting position of the selection}
begin
SetSelection(Value, Value);
Refresh;
end;
procedure TOvcBaseEntryField.SetSelText(const Value : string);
{-replace selected text with Value}
var
Msg : TMessage;
Buf : array[0..MaxEditLen] of AnsiChar;
begin
StrPCopy(Buf, Value);
Msg.lParam := LongInt(@Buf);
efPerformEdit(Msg, ccPaste);
end;
procedure TOvcBaseEntryField.SetTextMargin(Value : Integer);
{-set the text margin}
begin
if (Value <> FTextMargin) and (Value >= 2) then begin
FTextMargin := Value;
Refresh;
end;
end;
procedure TOvcBaseEntryField.SetUninitialized(Value : Boolean);
{-sets the Uninitialized option}
begin
if Value <> FUninitialized then begin
FUninitialized := Value;
efRemoveBadOptions;
end;
end;
procedure TOvcBaseEntryField.SetUserData(Value : TOvcUserData);
{-sets pointer to user-defined mask data object}
begin
if Assigned(Value) then
FUserData := Value
else
FUserData := OvcUserData;
end;
procedure TOvcBaseEntryField.SetValue(const Data);
{-changes the field value to the value in Data}
begin
if sefUserValidating in sefOptions then
Exit;
HandleNeeded;
{set the updating flag so OnChange doesn't get fired}
Include(sefOptions, sefUpdating);
try
case efDataType mod fcpDivisor of
fsubString : efTransfer(@ShortString(Data), otf_SetData);
fsubChar : efTransfer(@AnsiChar(Data), otf_SetData);
fsubBoolean : efTransfer(@Boolean(Data), otf_SetData);
fsubYesNo : efTransfer(@Boolean(Data), otf_SetData);
fsubLongInt : efTransfer(@LongInt(Data), otf_SetData);
fsubWord : efTransfer(@Word(Data), otf_SetData);
fsubInteger : efTransfer(@SmallInt(Data), otf_SetData);
fsubByte : efTransfer(@Byte(Data), otf_SetData);
fsubShortInt : efTransfer(@ShortInt(Data), otf_SetData);
fsubReal : efTransfer(@Real(Data), otf_SetData);
fsubExtended : efTransfer(@Extended(Data), otf_SetData);
fsubDouble : efTransfer(@Double(Data), otf_SetData);
fsubSingle : efTransfer(@Single(Data), otf_SetData);
fsubComp : efTransfer(@Comp(Data), otf_SetData);
fsubDate : efTransfer(@TStDate(Data), otf_SetData);
fsubTime : efTransfer(@TStTime(Data), otf_SetData);
else
raise EOvcException.Create(GetOrphStr(SCInvalidParamValue));
end;
finally
Exclude(sefOptions, sefUpdating);
end;
end;
procedure TOvcBaseEntryField.SetZeroDisplay(Value : TZeroDisplay);
{-set flag that determines if zeros are hidden}
begin
if Value <> FZeroDisplay then begin
FZeroDisplay := Value;
Refresh;
end;
end;
procedure TOvcBaseEntryField.SetZeroDisplayValue(Value : Double);
{-set value used by ZeroDisplay logic}
begin
if Value <> FZeroDisplayValue then begin
FZeroDisplayValue := Value;
Refresh;
end;
end;
function TOvcBaseEntryField.ValidateContents(ReportError : Boolean) : Word;
{-performs field validation, returns error code, and conditionally reports error}
var
WasValid : Boolean;
begin
{ - If the parent is not enabled or visible then don't attempt to }
{ validate the contents of the control. }
if (not (Enabled and Visible)) or (Parent = nil)
or (not (Parent.Enabled and Parent.Visible))
then begin
Result := 0;
Exit;
end;
FLastError := 0;
{record current valid state}
WasValid := IsValid;
{check for empty/uninitialized required field}
if (efoInputRequired in Options) and not efIsReadOnly then
if efFieldIsEmpty or (Uninitialized and not (sefModified in sefOptions)) then
FLastError := oeRequiredField;
{ask the validation routine if there's an error}
if FLastError = 0 then begin
Include(sefOptions, sefValidating);
try
FLastError := efValidateField;
finally
Exclude(sefOptions, sefValidating);
end;
end;
if ReportError and (FLastError <> 0) then
PostMessage(Handle, om_ReportError, FLastError, 0);
{update invalid flag}
if FLastError = 0 then
Exclude(sefOptions, sefInvalid)
else if efoSoftValidation in Options then
Include(sefOptions, sefInvalid);
{force field to repaint if valid state has changed}
if WasValid <> IsValid then
Invalidate;
Result := FLastError;
end;
function TOvcBaseEntryField.ValidateSelf : Boolean;
{-performs field validation, returns true if no errors, and reports error if not using SoftValidation}
begin
Result := ValidateContents(not (efoSoftValidation in Options)) = 0;
end;
procedure TOvcBaseEntryField.WMChar(var Msg : TWMChar);
begin
inherited;
if sefCharOk in sefOptions then
efPerformEdit(TMessage(Msg), ccChar);
end;
procedure TOvcBaseEntryField.WMClear(var Msg : TWMClear);
begin
efPerformEdit(TMessage(Msg), ccCut);
end;
procedure TOvcBaseEntryField.WMCopy(var Msg : TWMCopy);
begin
efPerformEdit(TMessage(Msg), ccCopy);
end;
procedure TOvcBaseEntryField.WMCut(var Msg : TWMCut);
begin
efCopyPrim;
efPerformEdit(TMessage(Msg), ccCut);
end;
procedure TOvcBaseEntryField.WMEraseBkGnd(var Msg : TWMEraseBkGnd);
begin
Msg.Result := 1; {don't erase background}
end;
procedure TOvcBaseEntryField.WMGetDlgCode(var Msg : TWMGetDlgCode);
begin
inherited;
if csDesigning in ComponentState then
Msg.Result := DLGC_STATIC
else
Msg.Result := Msg.Result or DLGC_WANTCHARS or DLGC_WANTARROWS;
end;
procedure TOvcBaseEntryField.WMKeyDown(var Msg : TWMKeyDown);
var
Cmd : Word;
begin
inherited;
if Msg.CharCode = 0 then
Exit;
{don't process shift key by itself}
if Msg.CharCode = VK_SHIFT then
Exit;
{see if this command should be processed by us}
Cmd := Controller.EntryCommands.Translate(TMessage(Msg));
{convert undo to restore since ctrl-Z is mapped to ccUndo by default}
{and cannot be mapped to more than one command in a command table}
if Cmd = ccUndo then
Cmd := ccRestore;
if Cmd <> ccNone then begin
if (Cmd <> ccIns) or
not ((efoForceInsert in Options) or
(efoForceOvertype in Options)) then begin
case Cmd of
ccCut : WMCut(TWMCut(Msg));
ccCopy : WMCopy(TWMCopy(Msg));
ccPaste : WMPaste(TWMPaste(Msg));
else
efPerformEdit(TMessage(Msg), Cmd);
end;
end;
end;
end;
procedure TOvcBaseEntryField.WMKillFocus(var Msg : TWMKillFocus);
var
NewWindow : HWnd;
SaveModified : Boolean;
begin
{where is the focus going?}
NewWindow := Msg.FocusedWnd;
if NewWindow = Handle then
NewWindow := 0
else if not efIsSibling(NewWindow) then
NewWindow := 0;
{retain caret position if focus is moving }
{to a menu or a component not on this form}
if (NewWindow = 0) then
Include(sefOptions, sefRetainPos)
else
Exclude(sefOptions, sefRetainPos);
{destroy caret}
efCaret.Linked := False;
{if the mouse if currently captured, release it}
if MouseCapture then
MouseCapture := False;
{perform default processing}
inherited;
{set controller's insert mode flag for sibling fields' to access}
if not ((efoForceInsert in Options) or
(efoForceOvertype in Options)) then
{are we in insert mode}
Controller.InsertMode := sefInsert in sefOptions;
{if no error is pending for this control...}
if not (sefErrorPending in sefOptions) and
not (sefIgnoreFocus in sefOptions) then begin
Include(sefOptions, sefValPending);
{and focus is going to a control...}
if (NewWindow <> 0) then begin
if sefModified in sefOptions then
{clear the unitialized option}
Uninitialized := False;
{that isn't a Cancel, Restore, or Help button...}
if not Controller.IsSpecialButton(Msg.FocusedWnd) then begin
{then validate this field}
efCanClose(True {validate});
if sefErrorPending in sefOptions then
Include(sefOptions, sefValPending)
else
Exclude(sefOptions, sefValPending);
end else begin
{just call validate field and ignore the error, if any}
{this forces the field to redisplay using the proper format}
SaveModified := Modified;
efValidateField;
Modified := SaveModified;
end;
end;
end else begin
{set the validation pending flag on if an error is pending}
if sefErrorPending in sefOptions then
Include(sefOptions, sefValPending)
else
Exclude(sefOptions, sefValPending);
end;
{we no longer have the focus}
Exclude(sefOptions, sefHaveFocus);
{if we're not coming back...}
if (NewWindow <> 0) and not (sefRetainPos in sefOptions) and
not (sefIgnoreFocus in sefOptions) then begin
efPerformPostEditNotify(FindControl(Msg.FocusedWnd));
end;
Exclude(sefOptions, sefIgnoreFocus);
{reset the caret position}
if not (sefRetainPos in sefOptions) then
efCaretToStart;
{redraw the field}
Refresh;
end;
procedure TOvcBaseEntryField.WMLButtonDblClk(var Msg : TWMLButtonDblClk);
begin
if sefHaveFocus in sefOptions then
efPerformEdit(TMessage(Msg), ccDblClk);
inherited;
end;
procedure TOvcBaseEntryField.WMLButtonDown(var Msg : TWMLButtonDown);
begin
inherited;
if not (sefHaveFocus in sefOptions) then begin
Include(sefOptions, sefNoHighlight);
SetSelection(0, 0);
if not Focused then
SetFocus;
end;
// inherited;
if sefHaveFocus in sefOptions then
efPerformEdit(TMessage(Msg), ccMouse);
end;
procedure TOvcBaseEntryField.WMMouseActivate(var Msg : TWMMouseActivate);
begin
if csDesigning in ComponentState then
Exit;
inherited;
end;
procedure TOvcBaseEntryField.WMMouseMove(var Msg : TWMMouseMove);
begin
inherited;
if MouseCapture then
if {$IFNDEF LCL} GetAsyncKeyState(GetLeftButton) {$ELSE} GetKeyState(GetLeftButton) {$ENDIF} and $8000 <> 0 then
efPerformEdit(TMessage(Msg), ccMouseMove);
end;
procedure TOvcBaseEntryField.WMPaste(var Msg : TWMPaste);
{-paste text in the clipboard into the field}
var
H : THandle;
begin
{$IFNDEF LCL}
H := Clipboard.GetAsHandle(CF_TEXT);
if H <> 0 then begin
TMessage(Msg).lParam := LongInt(GlobalLock(H));
efPerformEdit(TMessage(Msg), ccPaste);
GlobalUnlock(H);
end;
{$ENDIF}
end;
procedure TOvcBaseEntryField.WMRButtonUp(var Msg : TWMRButtonDown);
var
P : TPoint;
M : TPopUpMenu;
MI : TMenuItem;
begin
if not (sefHaveFocus in sefOptions) then
if not Focused and CanFocus then
SetFocus;
inherited;
if PopUpMenu = nil then begin
M := TPopupMenu.Create(Self);
try
MI := TMenuItem.Create(M);
MI.Caption := GetOrphStr(SCRestoreMI);
MI.Enabled := Modified;
MI.OnClick := DoRestoreClick;
M.Items.Add(MI);
MI := TMenuItem.Create(M);
MI.Caption := '-';
M.Items.Add(MI);
MI := TMenuItem.Create(M);
MI.Caption := GetOrphStr(SCCutMI);
MI.Enabled := (SelectionLength > 0) and not efIsReadOnly;
MI.OnClick := DoCutClick;
M.Items.Add(MI);
MI := TMenuItem.Create(M);
MI.Caption := GetOrphStr(SCCopyMI);
MI.Enabled := SelectionLength > 0;
MI.OnClick := DoCopyClick;
M.Items.Add(MI);
MI := TMenuItem.Create(M);
MI.Caption := GetOrphStr(SCPasteMI);
MI.Enabled := not efIsReadOnly and Clipboard.HasFormat(CF_TEXT);
MI.OnClick := DoPasteClick;
M.Items.Add(MI);
MI := TMenuItem.Create(M);
MI.Caption := GetOrphStr(SCDeleteMI);
MI.Enabled := (SelectionLength > 0) and not efIsReadOnly;
MI.OnClick := DoDeleteClick;
M.Items.Add(MI);
MI := TMenuItem.Create(M);
MI.Caption := '-';
M.Items.Add(MI);
MI := TMenuItem.Create(M);
MI.Caption := GetOrphStr(SCSelectAllMI);
MI.Enabled := LongInt(StrLen(efEditSt)) > SelectionLength;
MI.OnClick := DoSelectAllClick;
M.Items.Add(MI);
P.X := Msg.XPos;
P.Y := Msg.YPos;
P := ClientToScreen(P);
M.PopUp(P.X, P.Y);
Application.ProcessMessages;
finally
M.Free;
end;
end;
end;
procedure TOvcBaseEntryField.WMSetFocus(var Msg : TWMSetFocus);
var
Highlight,
Ignore,
FixHOfs,
ValPending : Boolean;
PF : TForm;
P : TPoint;
begin
if ((csLoading in ComponentState) or
(csDesigning in ComponentState)) then
Exit;
{we have the focus}
Include(sefOptions, sefHaveFocus);
{reset command processor}
Controller.EntryCommands.ResetCommandProcessor;
{get validation state}
ValPending := sefValPending in sefOptions;
{calling Show forces the parent to do whatever is necessary to}
{make sure that we are visible. In the case where the entry}
{field is on a non-visible notebook page that has had its}
{handle deallocated, this insures that the page is made visible}
{and that the window handles have been created}
{if focus is retruning because of an error condition}
if ValPending then begin
{tell the control that lost the focus to}
{cancel any special modes it might be in}
if Msg.FocusedWnd > 0 then begin
SendMessage(Msg.FocusedWnd, WM_CANCELMODE, 0, 0);
GetCursorPos(P);
{send a fake mouse up message to force release of mouse capture}
{this is necessary so that the TStringGrid exits highlight mode}
SendMessage(Msg.FocusedWnd, WM_LBUTTONUP, 0, MakeLong(P.X, P.Y));
end;
Show;
PF := TForm(GetParentForm(Self));
if Assigned(PF) then
PF.FocusControl(Self);
end;
{get the field's insert mode}
if not ((efoForceInsert in Options) or
(efoForceOvertype in Options)) then
if Controller.InsertMode then
Include(sefOptions, sefInsert)
else
Exclude(sefOptions, sefInsert);
if sefRetainPos in sefOptions then begin
Highlight := False;
FixHOfs := False;
Ignore := False;
end else begin
Ignore := Controller.ErrorPending and {not us} (FLastError = 0);
if not Ignore then begin
if not ValPending then
Exclude(sefOptions, sefModified);
efPerformPreEditNotify(FindControl(Msg.FocusedWnd));
{save a copy of the current edit string}
efSaveEditString;
end;
if sefNoHighlight in sefOptions then begin
Highlight := False;
FixHOfs := False;
end else begin
Highlight := (not Ignore);
FixHOfs := True;
efResetCaret;
end;
end;
if Ignore and not (efoSoftValidation in Options) then
Include(sefOptions, sefIgnoreFocus)
else
Exclude(sefOptions, sefIgnoreFocus);
Exclude(sefOptions, sefErrorPending);
Exclude(sefOptions, sefRetainPos);
Exclude(sefOptions, sefNoHighlight);
Exclude(sefOptions, sefValPending);
{clear controller's error pending flag}
if not Ignore then
Controller.ErrorPending := False;
inherited;
if (efoForceInsert in Options) then
Include(sefOptions, sefInsert)
else if (efoForceOvertype in Options) then
Exclude(sefOptions, sefInsert);
efCaret.Linked := True;
efCaret.Visible := True;
efCaret.InsertMode := (sefInsert in sefOptions);
efPositionCaret(FixHOfs);
if Highlight and (efoAutoSelect in Controller.EntryOptions) then
SetSelection(0, MaxEditLen);
Refresh;
end;
procedure TOvcBaseEntryField.WMSetFont(var Msg : TWMSetFont);
begin
inherited;
{inherited WMSetFont sets our font. Set it as our canvas font}
Canvas.Font := Font;
end;
procedure TOvcBaseEntryField.WMSetText(var Msg : TWMSetText);
begin
if HandleAllocated then begin
SetSelection(0, MaxEditLen);
efPerformEdit(TMessage(Msg), ccPaste);
end;
end;
procedure TOvcBaseEntryField.WMSize(var Msg : TWMSize);
begin
inherited;
Refresh;
end;
procedure TOvcBaseEntryField.WMSysKeyDown(var Msg : TWMSysKeyDown);
var
Cmd : Word;
begin
inherited;
{exit if this is a Tab key or an Alt key by itself}
if (Msg.CharCode = VK_TAB) or (Msg.CharCode = VK_ALT) then
Exit;
{see if this command should be processed by us}
Cmd := Controller.EntryCommands.TranslateKey(Msg.CharCode, [ssAlt]);
{convert undo to restore since ctrl-Z is mapped to ccUndo by default}
{and cannot be mapped to more than one command in a command table}
if Cmd = ccUndo then
Cmd := ccRestore;
if Cmd <> ccNone then begin
case Cmd of
ccCut : WMCut(TWMCut(Msg));
ccCopy : WMCopy(TWMCopy(Msg));
ccPaste : WMPaste(TWMPaste(Msg));
else
efPerformEdit(TMessage(Msg), Cmd);
end;
{allow entering of characters using Alt-keypad numbers}
case Msg.CharCode of
vk_NumPad0, vk_NumPad1, vk_NumPad2, vk_NumPad3, vk_NumPad4,
vk_NumPad5, vk_NumPad6, vk_NumPad7, vk_NumPad8, vk_NumPad9:
begin
Include(sefOptions, sefCharOk);
Include(sefOptions, sefAcceptChar);
end;
end;
end;
end;
end.