| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667 | unit UpDownEdit;interfaceuses  Windows, ComCtrls, Controls, ExtCtrls, Classes, Graphics, Messages, Forms,  StdCtrls, Menus, SysUtils;{ TUpDownEdit }type  TValueType = (vtInt, vtFloat, vtHex);  TUpDownEditGetValue = procedure(Sender: TObject; Text: string;    var Value: Extended; var Handled: Boolean) of object;  TUpDownEditSetValue = procedure(Sender: TObject; Value: Extended;    var Text: string; var Handled: Boolean) of object;  TUpDownEdit = class(TCustomEdit)  private    FAlignment: TAlignment;    FMinValue: Extended;    FMaxValue: Extended;    FIncrement: Extended;    FDecimal: Byte;    FChanging: Boolean;    FEditorEnabled: Boolean;    FValueType: TValueType;    FArrowKeys: Boolean;    FButtonsVisible: Boolean;    FOnTopClick: TNotifyEvent;    FOnBottomClick: TNotifyEvent;    FUpDown: TCustomUpDown;    FOnGetValue: TUpDownEditGetValue;    FOnSetValue: TUpDownEditSetValue;    procedure UpDownClick(Sender: TObject; Button: TUDBtnType);    function GetMinHeight: Integer;    procedure GetTextHeight(var SysHeight, Height: Integer);    function GetValue: Extended;    function CheckValue(NewValue: Extended): Extended;    function GetAsInteger: Longint;    function IsIncrementStored: Boolean;    function IsMaxStored: Boolean;    function IsMinStored: Boolean;    function IsValueStored: Boolean;    procedure SetArrowKeys(Value: Boolean);    procedure SetAsInteger(NewValue: Longint);    procedure SetValue(NewValue: Extended);    procedure SetValueType(NewType: TValueType);    procedure SetDecimal(NewValue: Byte);    function GetButtonWidth: Integer;    procedure RecreateButton;    procedure ResizeButton;    procedure SetEditRect;    procedure SetAlignment(Value: TAlignment);    procedure SetButtonsVisible(Value: Boolean);    procedure WMSize(var Message: TWMSize); message WM_SIZE;    procedure CMEnter(var Message: TMessage); message CM_ENTER;    procedure CMExit(var Message: TCMExit); message CM_EXIT;    procedure WMPaste(var Message: TWMPaste); message WM_PASTE;    procedure WMCut(var Message: TWMCut); message WM_CUT;    procedure CMCtl3DChanged(var Message: TMessage); message CM_CTL3DCHANGED;    procedure CMEnabledChanged(var Message: TMessage); message CM_ENABLEDCHANGED;    procedure CMFontChanged(var Message: TMessage); message CM_FONTCHANGED;    procedure CMBiDiModeChanged(var Message: TMessage); message CM_BIDIMODECHANGED;  protected    procedure Change; override;    function IsValidChar(Key: Char): Boolean; virtual;    procedure UpClick(Sender: TObject); virtual;    procedure DownClick(Sender: TObject); virtual;    procedure KeyDown(var Key: Word; Shift: TShiftState); override;    procedure KeyPress(var Key: Char); override;    procedure CreateParams(var Params: TCreateParams); override;    procedure CreateWnd; override;    function DefBtnWidth: Integer;  public    constructor Create(AOwner: TComponent); override;    destructor Destroy; override;    property AsInteger: Longint read GetAsInteger write SetAsInteger default 0;    property Text;  published    property Alignment: TAlignment read FAlignment write SetAlignment      default taLeftJustify;    property ArrowKeys: Boolean read FArrowKeys write SetArrowKeys default True;    property Decimal: Byte read FDecimal write SetDecimal default 2;    property EditorEnabled: Boolean read FEditorEnabled write FEditorEnabled default True;    property Increment: Extended read FIncrement write FIncrement stored IsIncrementStored;    property MaxValue: Extended read FMaxValue write FMaxValue stored IsMaxStored;    property MinValue: Extended read FMinValue write FMinValue stored IsMinStored;    property ValueType: TValueType read FValueType write SetValueType default vtInt;    property Value: Extended read GetValue write SetValue stored IsValueStored;    property ButtonsVisible: Boolean read FButtonsVisible write SetButtonsVisible default True;    property AutoSelect;    property AutoSize;    property BorderStyle;    property Color;    property Ctl3D;    property DragCursor;    property DragMode;    property Enabled;    property Font;    property Anchors;    property BiDiMode;    property Constraints;    property DragKind;    property ParentBiDiMode;    property ImeMode;    property ImeName;    property MaxLength;    property ParentColor;    property ParentCtl3D;    property ParentFont;    property ParentShowHint;    property PopupMenu;    property ReadOnly;    property ShowHint;    property TabOrder;    property TabStop;    property Visible;    property OnBottomClick: TNotifyEvent read FOnBottomClick write FOnBottomClick;    property OnTopClick: TNotifyEvent read FOnTopClick write FOnTopClick;    property OnGetValue: TUpDownEditGetValue read FOnGetValue write FOnGetValue;    property OnSetValue: TUpDownEditSetValue read FOnSetValue write FOnSetValue;    property OnChange;    property OnClick;    property OnDblClick;    property OnDragDrop;    property OnDragOver;    property OnEndDrag;    property OnEnter;    property OnExit;    property OnKeyDown;    property OnKeyPress;    property OnKeyUp;    property OnMouseDown;    property OnMouseMove;    property OnMouseUp;    property OnStartDrag;    property OnContextPopup;    property OnMouseWheelDown;    property OnMouseWheelUp;    property OnEndDock;    property OnStartDock;  end;procedure Register;implementationuses  CommCtrl, PasTools, Math;procedure Register;begin  RegisterComponents('Martin', [TUpDownEdit]);end;type  TEmbededUpDown = class(TCustomUpDown)  private    FChanging: Boolean;    procedure ScrollMessage(var Message: TWMVScroll);    procedure WMHScroll(var Message: TWMHScroll); message CN_HSCROLL;    procedure WMVScroll(var Message: TWMVScroll); message CN_VSCROLL;    procedure WMSize(var Message: TWMSize); message WM_SIZE;  public    constructor Create(AOwner: TComponent); override;    destructor Destroy; override;  published    property OnClick;  end;constructor TEmbededUpDown.Create(AOwner: TComponent);begin  inherited Create(AOwner);  Orientation := udVertical;  Min := -1;  Max := 1;  Position := 0;end;destructor TEmbededUpDown.Destroy;begin  OnClick := nil;  inherited Destroy;end;procedure TEmbededUpDown.ScrollMessage(var Message: TWMVScroll);begin  if Message.ScrollCode = SB_THUMBPOSITION then begin    if not FChanging then begin      FChanging := True;      try        if Message.Pos > 0 then Click(btNext)        else if Message.Pos < 0 then Click(btPrev);        if HandleAllocated then          SendMessage(Handle, UDM_SETPOS, 0, 0);      finally        FChanging := False;      end;    end;  end;end;procedure TEmbededUpDown.WMHScroll(var Message: TWMHScroll);begin  ScrollMessage(TWMVScroll(Message));end;procedure TEmbededUpDown.WMVScroll(var Message: TWMVScroll);begin  ScrollMessage(Message);end;procedure TEmbededUpDown.WMSize(var Message: TWMSize);var  Def: Integer;begin  inherited;  Def := TUpDownEdit(Parent).DefBtnWidth;  if Width <> Def then Width := Def;end;{ TUpDownEdit }constructor TUpDownEdit.Create(AOwner: TComponent);begin  inherited Create(AOwner);  Text := '0';  ControlStyle := ControlStyle - [csSetCaption];  FIncrement := 1.0;  FDecimal := 2;  FEditorEnabled := True;  FArrowKeys := True;  FButtonsVisible := True;  RecreateButton;end;destructor TUpDownEdit.Destroy;begin  Destroying;  FChanging := True;  if FUpDown <> nil then  begin    FUpDown.Free;    FUpDown := nil;  end;  inherited Destroy;end;procedure TUpDownEdit.RecreateButton;begin  if (csDestroying in ComponentState) then Exit;  FUpDown.Free;  FUpDown := nil;  FUpDown := TEmbededUpDown.Create(Self);  with TEmbededUpDown(FUpDown) do begin    Visible := True;    SetBounds(0, 0, DefBtnWidth, Self.Height);    if (BiDiMode = bdRightToLeft) then Align := alLeft      else Align := alRight;    Parent := Self;    OnClick := UpDownClick;  end;end;procedure TUpDownEdit.SetArrowKeys(Value: Boolean);begin  FArrowKeys := Value;  ResizeButton;end;procedure TUpDownEdit.UpDownClick(Sender: TObject; Button: TUDBtnType);begin  if TabStop and CanFocus then SetFocus;  case Button of    btNext: UpClick(Sender);    btPrev: DownClick(Sender);  end;end;function TUpDownEdit.GetButtonWidth: Integer;begin  if FUpDown.Visible then Result := FUpDown.Width    else Result := 0;end;function TUpDownEdit.DefBtnWidth: Integer;begin  Result := 15;  if Parent <> nil then  begin    Result := ScaleByPixelsPerInch(Result, Self);    Result := Math.Min(GetSystemMetricsForControl(Self, SM_CXVSCROLL), Result);  end;end;procedure TUpDownEdit.ResizeButton;begin  if FUpDown <> nil then  begin    FUpDown.Width := DefBtnWidth;    if (BiDiMode = bdRightToLeft) then FUpDown.Align := alLeft      else FUpDown.Align := alRight;    FUpDown.Visible := ButtonsVisible;  endend;procedure TUpDownEdit.KeyDown(var Key: Word; Shift: TShiftState);begin  inherited KeyDown(Key, Shift);  if ArrowKeys and (Key in [VK_UP, VK_DOWN]) then  begin    if Key = VK_UP then UpClick(Self)      else    if Key = VK_DOWN then DownClick(Self);    Key := 0;  end;end;procedure TUpDownEdit.Change;begin  if not FChanging then inherited Change;end;procedure TUpDownEdit.KeyPress(var Key: Char);begin  if not IsValidChar(Key) then  begin    Key := #0;    MessageBeep(MB_ICONHAND)  end;  if Key <> #0 then  begin    inherited KeyPress(Key);    if (Key = Char(VK_RETURN)) or (Key = Char(VK_ESCAPE)) then    begin      { must catch and remove this, since is actually multi-line }      GetParentForm(Self).Perform(CM_DIALOGKEY, Byte(Key), 0);      if Key = Char(VK_RETURN) then Key := #0;    end;  end;end;function TUpDownEdit.IsValidChar(Key: Char): Boolean;var  ValidChars: TSysCharSet;begin  ValidChars := ['+', '-', '0'..'9'];  if ValueType = vtFloat then  begin    if Pos(FormatSettings.DecimalSeparator, Text) = 0 then      ValidChars := ValidChars + [FormatSettings.DecimalSeparator];    if Pos('E', AnsiUpperCase(Text)) = 0 then      ValidChars := ValidChars + ['e', 'E'];  end    else  if ValueType = vtHex then  begin    ValidChars := ValidChars + ['A'..'F', 'a'..'f'];  end;  Result := CharInSet(Key, ValidChars) or (Key < #32);  if not FEditorEnabled and Result and ((Key >= #32) or    (Key = Char(VK_BACK)) or (Key = Char(VK_DELETE))) then Result := False;end;procedure TUpDownEdit.CreateParams(var Params: TCreateParams);const  Alignments: array[Boolean, TAlignment] of DWORD =    ((ES_LEFT, ES_RIGHT, ES_CENTER), (ES_RIGHT, ES_LEFT, ES_CENTER));begin  inherited CreateParams(Params);  Params.Style := Params.Style or ES_MULTILINE or WS_CLIPCHILDREN or    Alignments[UseRightToLeftAlignment, FAlignment];end;procedure TUpDownEdit.CreateWnd;begin  inherited CreateWnd;  ResizeButton; // now we know the scaling factor  SetEditRect;  SetValue(Value);end;procedure TUpDownEdit.SetEditRect;var  Loc: TRect;begin  if (BiDiMode = bdRightToLeft) then      SetRect(Loc, GetButtonWidth + 1, 0, ClientWidth - 1, ClientHeight + 1)    else      SetRect(Loc, 0, 0, ClientWidth - GetButtonWidth - 2, ClientHeight + 1);  SendMessage(Handle, EM_SETRECTNP, 0, Longint(@Loc));end;procedure TUpDownEdit.SetAlignment(Value: TAlignment);begin  if FAlignment <> Value then  begin    FAlignment := Value;    RecreateWnd;  end;end;procedure TUpDownEdit.WMSize(var Message: TWMSize);var  MinHeight: Integer;begin  inherited;  MinHeight := GetMinHeight;  { text edit bug: if size to less than minheight, then edit ctrl does    not display the text }  if Height < MinHeight then    Height := MinHeight  else begin    ResizeButton;    SetEditRect;  end;end;procedure TUpDownEdit.GetTextHeight(var SysHeight, Height: Integer);var  DC: HDC;  SaveFont: HFont;  SysMetrics, Metrics: TTextMetric;begin  DC := GetDC(0);  GetTextMetrics(DC, SysMetrics);  SaveFont := SelectObject(DC, Font.Handle);  GetTextMetrics(DC, Metrics);  SelectObject(DC, SaveFont);  ReleaseDC(0, DC);  SysHeight := SysMetrics.tmHeight;  Height := Metrics.tmHeight;end;function TUpDownEdit.GetMinHeight: Integer;var  I, H: Integer;begin  GetTextHeight(I, H);  if I > H then I := H;  Result := H + (GetSystemMetricsForControl(Self, SM_CYBORDER) * 4) + 1;end;procedure TUpDownEdit.UpClick(Sender: TObject);var  OldText: string;begin  if ReadOnly then MessageBeep(MB_ICONHAND)  else begin    FChanging := True;    try      OldText := inherited Text;      Value := Value + FIncrement;    finally      FChanging := False;    end;    if CompareText(inherited Text, OldText) <> 0 then    begin      Modified := True;      Change;    end;    if Assigned(FOnTopClick) then FOnTopClick(Self);  end;end;procedure TUpDownEdit.DownClick(Sender: TObject);var  OldText: string;begin  if ReadOnly then MessageBeep(MB_ICONHAND)  else begin    FChanging := True;    try      OldText := inherited Text;      Value := Value - FIncrement;    finally      FChanging := False;    end;    if CompareText(inherited Text, OldText) <> 0 then    begin      Modified := True;      Change;    end;    if Assigned(FOnBottomClick) then FOnBottomClick(Self);  end;end;procedure TUpDownEdit.CMBiDiModeChanged(var Message: TMessage);begin  inherited;  ResizeButton;  SetEditRect;end;procedure TUpDownEdit.CMFontChanged(var Message: TMessage);begin  inherited;  ResizeButton;  SetEditRect;end;procedure TUpDownEdit.CMCtl3DChanged(var Message: TMessage);begin  inherited;  ResizeButton;  SetEditRect;end;procedure TUpDownEdit.CMEnabledChanged(var Message: TMessage);begin  inherited;  if FUpDown <> nil then  begin    FUpDown.Enabled := Enabled;    ResizeButton;  end;end;procedure TUpDownEdit.WMPaste(var Message: TWMPaste);begin  if not FEditorEnabled or ReadOnly then Exit;  inherited;end;procedure TUpDownEdit.WMCut(var Message: TWMCut);begin  if not FEditorEnabled or ReadOnly then Exit;  inherited;end;procedure TUpDownEdit.CMExit(var Message: TCMExit);begin  inherited;  SetValue(Value);end;procedure TUpDownEdit.CMEnter(var Message: TMessage);begin  if AutoSelect and not (csLButtonDown in ControlState) then SelectAll;  inherited;end;function TUpDownEdit.GetValue: Extended;var  Handled: Boolean;begin  Handled := False;  if Assigned(FOnGetValue) then FOnGetValue(Self, Text, Result, Handled);  if not Handled then  begin    try      if ValueType = vtFloat then Result := StrToFloat(Text)      else if ValueType = vtHex then Result := StrToInt('$' + Text)      else Result := StrToInt(Text);    except      if ValueType = vtFloat then Result := FMinValue      else Result := Trunc(FMinValue);    end;  end;end;procedure TUpDownEdit.SetValue(NewValue: Extended);var  Handled: Boolean;  AText: string;begin  NewValue := CheckValue(NewValue);  Handled := False;  if Assigned(FOnSetValue) then  begin    AText := Text;    FOnSetValue(Self, NewValue, AText, Handled);    if Handled then Text := AText;  end;  if not Handled then  begin    if ValueType = vtFloat then      Text := FloatToStrF(NewValue, ffFixed, 15, FDecimal)    else if ValueType = vtHex then      Text := IntToHex(Round(NewValue), 1)    else      Text := IntToStr(Round(NewValue));  end;end;function TUpDownEdit.GetAsInteger: Longint;begin  Result := Trunc(GetValue);end;procedure TUpDownEdit.SetAsInteger(NewValue: Longint);begin  SetValue(NewValue);end;procedure TUpDownEdit.SetValueType(NewType: TValueType);begin  if FValueType <> NewType then  begin    FValueType := NewType;    Value := GetValue;    if FValueType in [vtInt, vtHex] then    begin      FIncrement := Round(FIncrement);      if FIncrement = 0 then FIncrement := 1;    end;  end;end;function TUpDownEdit.IsIncrementStored: Boolean;begin  Result := FIncrement <> 1.0;end;function TUpDownEdit.IsMaxStored: Boolean;begin  Result := (MaxValue <> 0.0);end;function TUpDownEdit.IsMinStored: Boolean;begin  Result := (MinValue <> 0.0);end;function TUpDownEdit.IsValueStored: Boolean;begin  Result := (GetValue <> MinValue);end;procedure TUpDownEdit.SetDecimal(NewValue: Byte);begin  if FDecimal <> NewValue then  begin    FDecimal := NewValue;    Value := GetValue;  end;end;function TUpDownEdit.CheckValue(NewValue: Extended): Extended;begin  Result := NewValue;  if (FMaxValue <> FMinValue) then  begin    if NewValue < FMinValue then      Result := FMinValue    else if NewValue > FMaxValue then      Result := FMaxValue;  end;end;procedure TUpDownEdit.SetButtonsVisible(Value: Boolean);begin  if ButtonsVisible <> Value then  begin    FButtonsVisible := Value;    ResizeButton;    SetEditRect;  end;end;initializationend.
 |