Componentes.Terceros.DevExp.../internal/x.46/2/ExpressEditors Library 5/Sources/cxSpinButton.pas

561 lines
18 KiB
ObjectPascal

{********************************************************************}
{ }
{ Developer Express Visual Component Library }
{ ExpressEditors }
{ }
{ Copyright (c) 1998-2009 Developer Express Inc. }
{ ALL RIGHTS RESERVED }
{ }
{ The entire contents of this file is protected by U.S. and }
{ International Copyright Laws. Unauthorized reproduction, }
{ reverse-engineering, and distribution of all or any portion of }
{ the code contained in this file is strictly prohibited and may }
{ result in severe civil and criminal penalties and will be }
{ prosecuted to the maximum extent possible under the law. }
{ }
{ RESTRICTIONS }
{ }
{ THIS SOURCE CODE AND ALL RESULTING INTERMEDIATE FILES }
{ (DCU, OBJ, DLL, ETC.) ARE CONFIDENTIAL AND PROPRIETARY TRADE }
{ SECRETS OF DEVELOPER EXPRESS INC. THE REGISTERED DEVELOPER IS }
{ LICENSED TO DISTRIBUTE THE EXPRESSEDITORS AND ALL }
{ ACCOMPANYING VCL CONTROLS AS PART OF AN EXECUTABLE PROGRAM ONLY. }
{ }
{ THE SOURCE CODE CONTAINED WITHIN THIS FILE AND ALL RELATED }
{ FILES OR ANY PORTION OF ITS CONTENTS SHALL AT NO TIME BE }
{ COPIED, TRANSFERRED, SOLD, DISTRIBUTED, OR OTHERWISE MADE }
{ AVAILABLE TO OTHER INDIVIDUALS WITHOUT EXPRESS WRITTEN CONSENT }
{ AND PERMISSION FROM DEVELOPER EXPRESS INC. }
{ }
{ CONSULT THE END USER LICENSE AGREEMENT FOR INFORMATION ON }
{ ADDITIONAL RESTRICTIONS. }
{ }
{********************************************************************}
unit cxSpinButton;
{$I cxVer.inc}
interface
uses
{$IFDEF DELPHI6}
Variants,
{$ENDIF}
Windows, Classes, Controls, Forms, Graphics, Messages, StdCtrls, SysUtils,
cxClasses, cxContainer, cxControls, cxCustomData, cxEdit, cxExtEditConsts,
cxExtEditUtils, cxGraphics, cxMaskEdit, cxSpinEdit, cxTextEdit, cxVariants;
type
{ TcxSpinButtonViewData }
TcxCustomSpinButtonProperties = class;
TcxSpinButtonViewData = class(TcxSpinEditViewData)
private
function GetProperties: TcxCustomSpinButtonProperties;
protected
function CanPressButton(AViewInfo: TcxCustomEditViewInfo; AButtonVisibleIndex: Integer):
Boolean; override;
function IsButtonPressed(AViewInfo: TcxCustomEditViewInfo; AButtonVisibleIndex:
Integer): Boolean; override;
public
PressedState: TcxSpinEditPressedState;
procedure Calculate(ACanvas: TcxCanvas; const ABounds: TRect; const P: TPoint;
Button: TcxMouseButton; Shift: TShiftState; AViewInfo: TcxCustomEditViewInfo;
AIsMouseEvent: Boolean); override;
property Properties: TcxCustomSpinButtonProperties read GetProperties;
end;
{ TcxCustomSpinButtonProperties }
TcxCustomSpinButton = class;
TcxCustomSpinButtonProperties = class(TcxCustomSpinEditProperties)
protected
class function GetViewDataClass: TcxCustomEditViewDataClass; override;
function IsDisplayValueNumeric: Boolean; override;
function IsEditValueNumeric: Boolean; override;
function PreserveSelection: Boolean; override;
public
constructor Create(AOwner: TPersistent); override;
class function GetContainerClass: TcxContainerClass; override;
end;
{ TcxSpinButtonProperties }
TcxSpinButtonProperties = class(TcxCustomSpinButtonProperties)
published
property Alignment;
property AssignedValues;
property AutoSelect;
property BeepOnError;
property HideSelection;
property ImmediatePost;
property Increment;
property LargeIncrement;
property MaxValue;
property MinValue;
property ReadOnly;
property SpinButtons;
property UseCtrlIncrement;
property UseLeftAlignmentOnEditing;
property ValueType default vtInt;
property OnChange;
property OnEditValueChanged;
end;
{ TcxSpinButtonControlHook }
TcxSpinButtonControlHook = class(TcxControlHook)
private
FParent: TWinControl;
protected
procedure HookWndProc(var AMsg: TMessage); override;
public
destructor Destroy; override;
end;
{ TcxCustomSpinButton }
TcxCustomSpinButton = class(TcxCustomSpinEdit)
private
FAssociate: TWinControl;
FAutoWidth: Boolean;
FSpinButtonControlHook: TcxSpinButtonControlHook;
function GetActiveProperties: TcxCustomSpinButtonProperties;
function GetProperties: TcxCustomSpinButtonProperties;
procedure SetAssociate(AValue: TWinControl);
procedure SetAutoWidth(Value: Boolean);
procedure SetProperties(Value: TcxCustomSpinButtonProperties);
protected
procedure InternalSetEditValue(const Value: TcxEditValue;
AValidateEditValue: Boolean); override;
procedure InternalSetDisplayValue(const Value: TcxEditValue); override;
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
function CanFocusOnClick: Boolean; override;
procedure SetSize; override;
procedure Initialize; override;
function InternalDoEditing: Boolean; override;
procedure JoinToAssociate; virtual;
procedure SetAssociateText(const AValue: Variant); virtual;
function GetValue: Variant; override;
procedure SynchronizeEditValueFromAssociate; virtual;
property Associate: TWinControl read FAssociate write SetAssociate;
property AutoWidth: Boolean read FAutoWidth write SetAutoWidth default True;
property TabStop default False;
public
destructor Destroy; override;
class function GetPropertiesClass: TcxCustomEditPropertiesClass; override;
function Increment(AButton: TcxSpinEditButton): Boolean; override;
property ActiveProperties: TcxCustomSpinButtonProperties read GetActiveProperties;
property Properties: TcxCustomSpinButtonProperties read GetProperties
write SetProperties;
end;
{ TcxSpinButton }
TcxSpinButton = class(TcxCustomSpinButton)
private
function GetActiveProperties: TcxSpinButtonProperties;
function GetProperties: TcxSpinButtonProperties;
procedure SetProperties(Value: TcxSpinButtonProperties);
public
class function GetPropertiesClass: TcxCustomEditPropertiesClass; override;
property ActiveProperties: TcxSpinButtonProperties read GetActiveProperties;
published
property Anchors;
property Associate;
property AutoSize;
property AutoWidth;
property BeepOnEnter;
property Constraints;
property DragCursor;
property DragKind;
property DragMode;
property Enabled;
property ParentColor;
property ParentFont;
property ParentShowHint;
property PopupMenu;
property Properties: TcxSpinButtonProperties read GetProperties
write SetProperties;
property ShowHint;
property Style;
property StyleDisabled;
property StyleFocused;
property StyleHot;
property TabOrder;
property TabStop;
property Value;
property Visible;
property OnClick;
property OnContextPopup;
property OnDblClick;
property OnDragDrop;
property OnDragOver;
property OnEditing;
property OnEndDock;
property OnEndDrag;
property OnEnter;
property OnExit;
property OnKeyDown;
property OnKeyPress;
property OnKeyUp;
property OnMouseDown;
property OnMouseEnter;
property OnMouseLeave;
property OnMouseMove;
property OnMouseUp;
property OnStartDock;
property OnStartDrag;
end;
implementation
uses
cxEditConsts, cxEditUtils, dxThemeConsts, dxThemeManager;
type
TWinControlAccess = class(TWinControl);
{ TcxSpinButtonControlHook }
destructor TcxSpinButtonControlHook.Destroy;
begin
FParent := nil;
inherited Destroy;
end;
procedure TcxSpinButtonControlHook.HookWndProc(var AMsg: TMessage);
var
AKey: Longint;
begin
if Assigned(WinControl) and not IsDestroying and
((AMsg.Msg = WM_KEYDOWN) or (AMsg.Msg = WM_KEYUP)) then
begin
AKey := AMsg.WParam;
if (FParent <> nil) and (AKey in [VK_UP, VK_DOWN, VK_NEXT, VK_PRIOR]) then
PostMessage(FParent.Handle, AMsg.Msg, AKey, AMsg.LParam);
end;
inherited HookWndProc(AMsg);
end;
{ TcxSpinButtonViewData }
procedure TcxSpinButtonViewData.Calculate(ACanvas: TcxCanvas; const ABounds: TRect;
const P: TPoint; Button: TcxMouseButton; Shift: TShiftState; AViewInfo: TcxCustomEditViewInfo;
AIsMouseEvent: Boolean);
begin
inherited Calculate(ACanvas, ABounds, P, Button, Shift, AViewInfo, AIsMouseEvent);
TcxSpinEditViewInfo(AViewInfo).Text := '';
end;
function TcxSpinButtonViewData.CanPressButton(AViewInfo: TcxCustomEditViewInfo;
AButtonVisibleIndex: Integer): Boolean;
begin
Result := inherited CanPressButton(AViewInfo, AButtonVisibleIndex);
end;
function TcxSpinButtonViewData.IsButtonPressed(AViewInfo: TcxCustomEditViewInfo;
AButtonVisibleIndex: Integer): Boolean;
begin
Result := inherited IsButtonPressed(AViewInfo, AButtonVisibleIndex);
end;
function TcxSpinButtonViewData.GetProperties: TcxCustomSpinButtonProperties;
begin
Result := TcxCustomSpinButtonProperties(FProperties);
end;
{ TcxCustomSpinButtonProperties }
constructor TcxCustomSpinButtonProperties.Create(AOwner: TPersistent);
begin
inherited Create(AOwner);
HideCursor := True;
end;
class function TcxCustomSpinButtonProperties.GetContainerClass: TcxContainerClass;
begin
Result := TcxSpinButton;
end;
class function TcxCustomSpinButtonProperties.GetViewDataClass: TcxCustomEditViewDataClass;
begin
Result := TcxSpinButtonViewData;
end;
function TcxCustomSpinButtonProperties.IsDisplayValueNumeric: Boolean;
begin
Result := True;
end;
function TcxCustomSpinButtonProperties.IsEditValueNumeric: Boolean;
begin
Result := True;
end;
function TcxCustomSpinButtonProperties.PreserveSelection: Boolean;
begin
Result := False;
end;
{ TcxCustomSpinButton }
destructor TcxCustomSpinButton.Destroy;
begin
FSpinButtonControlHook.Free;
inherited Destroy;
end;
class function TcxCustomSpinButton.GetPropertiesClass: TcxCustomEditPropertiesClass;
begin
Result := TcxCustomSpinButtonProperties;
end;
function TcxCustomSpinButton.GetValue: Variant;
const
AVarTypeMap: array [TcxSpinEditValueType] of TVarType = (varInteger, varDouble);
begin
PrepareEditValue(Text, Result, InternalFocused);
if not VarIsNumeric(Result) then
Result := VarAsType(ActiveProperties.MinValue, AVarTypeMap[ActiveProperties.ValueType]);
end;
procedure TcxCustomSpinButton.InternalSetDisplayValue(const Value: TcxEditValue);
begin
if IsDestroying then
Exit;
inherited InternalSetDisplayValue(Value);
SetAssociateText(Value);
end;
procedure TcxCustomSpinButton.InternalSetEditValue(const Value: TcxEditValue; AValidateEditValue: Boolean);
begin
if IsDestroying then
Exit;
inherited InternalSetEditValue(Value, AValidateEditValue);
SetAssociateText(Value);
end;
procedure TcxCustomSpinButton.Notification(AComponent: TComponent;
Operation: TOperation);
begin
inherited Notification(AComponent, Operation);
if (Operation = opRemove) and (AComponent = FAssociate) then
Associate := nil;
end;
function TcxCustomSpinButton.CanFocusOnClick: Boolean;
begin
Result := False;
end;
function TcxCustomSpinButton.Increment(AButton: TcxSpinEditButton): Boolean;
begin
if Assigned(Associate) then SynchronizeEditValueFromAssociate;
Result := inherited Increment(AButton);
if not Result then
Exit;
KeyboardAction := True;
try
SynchronizeEditValue;
SetAssociateText(EditValue);
finally
KeyboardAction := False;
end;
end;
procedure TcxCustomSpinButton.SynchronizeEditValueFromAssociate;
var
FAssociateValue: TcxEditValue;
begin
if not((FAssociate is TCustomEdit) or (FAssociate is TcxCustomTextEdit)) then
Exit;
if ActiveProperties.ValueType = vtInt then
begin
if FAssociate is TcxCustomTextEdit then
FAssociateValue := cxStrToInt(TcxCustomTextEdit(FAssociate).Text, True)
else
FAssociateValue := cxStrToInt(TCustomEdit(FAssociate).Text, True);
end
else
begin
if FAssociate is TcxCustomTextEdit then
FAssociateValue := cxStrToFloat(TcxCustomTextEdit(FAssociate).Text, True)
else
FAssociateValue := cxStrToFloat(TCustomEdit(FAssociate).Text, True);
end;
if FAssociateValue <> Value then
Value := FAssociateValue;
end;
procedure TcxCustomSpinButton.SetSize;
var
AWidth: Integer;
begin
inherited SetSize;
if not AutoWidth then
Exit;
with ViewInfo do
begin
AWidth := (BorderRect.Right - BorderRect.Left) - (TextRect.Right - TextRect.Left);
if Painter <> nil then
Dec(AWidth)
else
if Length(ButtonsInfo) > 0 then
if not ButtonsInfo[0].Data.NativeStyle then
begin
AWidth := Succ(AWidth);
if Shadow then
AWidth := AWidth + cxContainerShadowWidth;
end;
end;
Width := AWidth;
end;
procedure TcxCustomSpinButton.Initialize;
begin
inherited Initialize;
FAutoWidth := True;
FSpinButtonControlHook := TcxSpinButtonControlHook.Create;
FSpinButtonControlHook.FParent := Self;
AutoSize := False;
TabStop := False;
end;
function TcxCustomSpinButton.InternalDoEditing: Boolean;
begin
Result := True;
end;
function TcxCustomSpinButton.GetActiveProperties: TcxCustomSpinButtonProperties;
begin
Result := TcxCustomSpinButtonProperties(InternalGetActiveProperties);
end;
function TcxCustomSpinButton.GetProperties: TcxCustomSpinButtonProperties;
begin
Result := TcxCustomSpinButtonProperties(FProperties);
end;
procedure TcxCustomSpinButton.SetAssociate(AValue: TWinControl);
var
I: Integer;
FCompoundControl: IcxCompoundControl;
function IsClass(ClassType: TClass; const Name: string): Boolean;
begin
Result := True;
while ClassType <> nil do
begin
if ClassType.ClassNameIs(Name) then Exit;
ClassType := ClassType.ClassParent;
end;
Result := False;
end;
begin
if AValue <> nil then
for I := 0 to Parent.ControlCount - 1 do {Is control already associated ?}
if (Parent.Controls[I] is TcxCustomSpinButton) and (Parent.Controls[I] <> Self) then
if TcxCustomSpinButton(Parent.Controls[I]).Associate = AValue then
raise EcxEditError.Create(AValue.Name +
cxGetResourceString(@scxUDAssociated) + Parent.Controls[I].Name);
if FAssociate <> nil then
begin
FSpinButtonControlHook.WinControl := nil;
FAssociate := nil;
end;
if (AValue <> nil) and (AValue.Parent = Self.Parent) and
not (AValue is TcxCustomSpinButton) and
not IsClass(AValue.ClassType, 'TcxDBTextEdit') and
not IsClass(AValue.ClassType, 'TcxDBMemo') and
not IsClass(AValue.ClassType, 'TDBTextEdit') and
not IsClass(AValue.ClassType, 'TDBMemo') then
begin
FAssociate := AValue;
if Supports(FAssociate, IcxCompoundControl, FCompoundControl) then
FSpinButtonControlHook.WinControl := FCompoundControl.ActiveControl
else
FSpinButtonControlHook.WinControl := FAssociate;
JoinToAssociate;
SetAssociateText(Value);
end;
end;
procedure TcxCustomSpinButton.SetAutoWidth(Value: Boolean);
begin
if FAutoWidth <> Value then
begin
FAutoWidth := Value;
if Value then
begin
CheckHandle;
ActiveProperties.ViewStyle := vsNormal;
end
else
ActiveProperties.ViewStyle := vsButtonsOnly;
if Value then
begin
SetSize;
ShortRefreshContainer(False);
end;
end;
end;
procedure TcxCustomSpinButton.SetProperties(Value: TcxCustomSpinButtonProperties);
begin
FProperties.Assign(Value);
end;
procedure TcxCustomSpinButton.JoinToAssociate;
begin
if FAssociate is TcxCustomEdit then
Font := TcxCustomEdit(FAssociate).Style.Font
else
Font := TWinControlAccess(FAssociate).Font;
Top := FAssociate.Top;
Left := FAssociate.Left + FAssociate.Width;
Height := FAssociate.Height;
end;
procedure TcxCustomSpinButton.SetAssociateText(const AValue: Variant);
begin
if (FAssociate = nil) or ((not (FAssociate is TcxCustomTextEdit)) and
(not (FAssociate is TCustomEdit))) then Exit;
if (FAssociate is TcxCustomTextEdit) then
TcxCustomTextEdit(FAssociate).Text := VarToStr(AValue)
else
if (FAssociate is TCustomEdit) then
TCustomEdit(FAssociate).Text := VarToStr(AValue);
end;
{ TcxSpinButton }
class function TcxSpinButton.GetPropertiesClass: TcxCustomEditPropertiesClass;
begin
Result := TcxSpinButtonProperties;
end;
function TcxSpinButton.GetActiveProperties: TcxSpinButtonProperties;
begin
Result := TcxSpinButtonProperties(InternalGetActiveProperties);
end;
function TcxSpinButton.GetProperties: TcxSpinButtonProperties;
begin
Result := TcxSpinButtonProperties(FProperties);
end;
procedure TcxSpinButton.SetProperties(Value: TcxSpinButtonProperties);
begin
FProperties.Assign(Value);
end;
end.