The DataCAD Developer Network (DDN) is an online resource for information and support for DCAL® (DataCAD Applications Language) developers as well as anyone interested in creating fonts, toolbars, hatch patterns, or linetypes for use in DataCAD.

Moderator: pjdixit

#71849 by dhs
Thu Jul 13, 2017 10:41 pm
Hi,
I s there an existing method to allow entry of distances in a VCL form? I am looking for is something to format a distance for display in an edit field, and also to parse the input from that field and return a number in 1/32".
Hopefully this exists and I just haven't found it ... It would be possible to write my own logic based on the scale type, but there are quite a few scale types and the logic must already exist in DataCAD itself so I am hoping I can hook into that.
Rgds,
David H.
#71885 by Jsosnowski
Wed Jul 19, 2017 7:45 pm
Conversion to strings can be performed directly by DCAl. See "Chapter 6 Data Routines" for:

Code: Select allPROCEDURE cvdisst (dis : real; str : OUT string);

cvdisst converts a distance to a string. The distance is in DataCAD units as described earlier.
The returned string depends upon the current scale type (metric, architectural, etc.).

This will work inside a macro, but not in an independent form Program in which case you must write your own method.

There is no conversion available in DCAl to go back to the real variable value. You willhave to generate this yourself.
#71906 by dhs
Tue Jul 25, 2017 12:37 pm
Thanks Joe,

I had not considered cvdisst because I felt that it formatted a string for display rather than for input (e.g. for the DataCAD's Arch scale an input of 12.11.31/32 is formatted as '12-11 31/32' by cvdisst if Units is disabled in the scale type menu, or as 12'-11 31/32" if units are enabled).

So it seems that if I want to be able to accept distance input in a VCL form I do in fact need to write both format & parse functions. They need to take into account not only the current scale type but also various other parameters (e.g. dofloat, sig digits for mm scale, 32nds/64ths/128ths etc for Arch scale, and possibly other settings for other scale types), so it is not a particularly simple piece of code.
... When I think about it, the formatting code could probably use cvdisst as a starting point and just replace spaces and dashes with dots (for Arch Scale) and remove units characters(you can of course use cvdisst in a VCL form that is part of a DCAL for Delphi project so long as you include UInterfaces in the uses clause). Might just work ...

I've put aside the project that I was working on when I asked this question, but will most likely return to it at some point (was more of a concept than a very worked out project). If I do come back to it I will be tempted to just accept mm or decimal inch inputs at least in the initial version, as they will both be pretty simple to parse.

Regards,
David H.
#74012 by dhs
Fri Jun 01, 2018 10:10 am
ok, a year later and I am starting to look at D4D again, and have discovered that the procedures I was looking for did in fact exist all along (and are used in the sample AEC_Model macro, which is how I found them).

To convert a distance to string (in the input format) use:
toStr (dis: double; var trash80: ShortString; RoundIt: boolean);
(the variable trash80 on output is the appropriately formatted string)

To convert a distance string (in the input format) back to a double use:
toDis(str: ShortString; var dis: double): boolean;

Glad to have found these, as they did seem to be glaring omissions from the interface if they did not exist!

Rgds,
David H.
#74142 by dhs
Mon Jun 18, 2018 12:54 pm
Looking at the code in the sample AEC_Model macro, and I notice it allows the user to enter a comma in the distance/angle/number input field. I can't think of any distance or angle format that requires (or even allows) a comma in the input.

Can anybody enlighten me as to when a comma would be acceptable in a distance or angle entry ?

Thanks,
David H.
#74143 by joshhuggins
Mon Jun 18, 2018 1:24 pm
dhs wrote:Looking at the code in the sample AEC_Model macro, and I notice it allows the user to enter a comma in the distance/angle/number input field. I can't think of any distance or angle format that requires (or even allows) a comma in the input.

Can anybody enlighten me as to when a comma would be acceptable in a distance or angle entry ?
It's a numeric separator used in Brazilian Portuguese and probably some other languages.
#74144 by David A. Giesselman
Mon Jun 18, 2018 3:08 pm
Josh is correct. A comma is used as a decimal separator in a large portion of the world.

Dave
#74145 by dhs
Mon Jun 18, 2018 5:12 pm
Thanks Josh .... blatantly obvious (once you pointed it out!)

I've written my own Delphi component for accepting DataCAD Numbers (Distances, Decimal Angles, DegMinSec Angles etc.). I've chosed to use the Delphi DecimalSeparator field (which I believe is locale specific) rather than specify both period and comma as acceptable keystrokes.

Not sure if anybody other than me or Joe are developing anything using D4D, but if anybody is interested in using it, the source code for my component is below:

Code: Select allunit DcadNumericEdit;

interface

uses
  System.SysUtils, System.Classes, Vcl.Controls, Vcl.StdCtrls, UInterfaces;

type

  NumType      = (Distance, DecDegrees, DegMinSec, IntegerNum, DecimalNum);

  TDcadNumericEdit = class(TCustomEdit)
  private
    function isValid : boolean;
    var datatype : NumType;
    var number : double;
    var allowNeg : boolean;
    procedure setNumber (num : double);   overload;
    procedure setNumber (num : integer);   overload;
    function getNumber : double;
  protected
    procedure KeyPress(var Key: Char); override;
  public
    property valid : boolean
      read isvalid;
    property NumValue : double
      read getnumber write setNumber;
  published
    property NumberType : NumType
      read dataType write dataType default Distance;
    property AllowNegative : boolean
      read allowNeg write allowNeg default true;

    { publish properties }
    property Align;
    property Alignment;
    property AlignWithMargins;
    property Anchors;
    property AutoSelect;
    property AutoSize;
    property BevelEdges;
    property BevelInner;
    property BevelKind;
    property BevelOuter;
    property BevelWidth;
    property BiDiMode;
    property BorderStyle;
    property Color;
    property Constraints;
    property Ctl3D;
    property Cursor;
    property CustomHint;
    property Enabled;
    property Font;
    property Height;
    property Hint;
    property Left;
    property Margins;
    property MaxLength;
    property Name;
    property ParentColor;
    property ParentCtl3D;
    property ParentFont;
    property ReadOnly;
    property ShowHint;
    property StyleElements;
    property TabOrder;
    property TabStop;
    property Text;
    property Top;
    property Visible;
    property Width;
    property OnChange;
    { publish events }
    property OnClick;
    property OnDblClick;
    property OnEnter;
    property OnExit;
    property OnKeyDown;
    property OnKeyPress;
    property OnKeyUp;
end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('DataCAD', [TDcadNumericEdit]);
end;

function TDcadNumericEdit.isValid : boolean;
var
  i : integer;
begin
  case datatype of
    Distance : result := toDis (shortstring(text), number);
    DegMinSec : result := Str2Ang (shortstring(text), true, number);
    DecDegrees : begin
      result := cvstrll(shortstring(text), number);
      number := number*Pi/180;
    end;
    IntegerNum : begin
      result := cvstint (shortstring(text), i);
      number := i;
    end
    else result := cvstrll(shortstring(text), number);
   end;
end;

procedure TDcadNumericEdit.setNumber(num: Double);
var
  ss : shortstring;
begin
  number := num;
  if not allowNeg then number := abs(number);

  case datatype of
    Distance : tostr (number, ss, false);
    DegMinSec : Ang2Str (number, ss, true, false);
    DecDegrees : cvrllst (number*180/Pi, ss);
    IntegerNum : cvintst (round(num), ss);
    else  cvrllst (number, ss);
  end;
  text := string (ss);
end;

procedure TDcadNumericEdit.setNumber(num: integer);
var
  ss : shortstring;
begin
  number := num;
  if not allowNeg then number := abs(number);

  case datatype of
    Distance : tostr (number, ss, false);
    DegMinSec : Ang2Str (number, ss, true, false);
    DecDegrees : cvrllst (number*180/Pi, ss);
    else cvintst (round(number), ss);
  end;
  text := string (ss);
end;


function TDcadNumericEdit.getNumber : Double;
begin
  if isValid then begin
    if datatype = IntegerNum then
      result := double(round(number))
    else
      result := number;

    if not allowNeg then
      result := abs(result);
  end
  else
    result := 0.0;
end;


procedure TDcadNumericEdit.KeyPress(var Key: Char);
begin
  if not (key in ['0'..'9', '-', FormatSettings.DecimalSeparator , '/', #8, #13, #127]) then
    key := #0;

  if not allowNeg then
    if key = '-' then key := #0;

  if ((PGSaveVar^.scaletype <> 1) and (PGSaveVar^.scaletype <> 4))
  or (datatype <> Distance) then begin
    if key = '/' then key := #0;
  end;

  if (datatype = IntegerNum) and (key = FormatSettings.DecimalSeparator) then
    key := #0;

  if key = #0 then beep;

  inherited KeyPress(Key)
end;

end.

If using the above you should check .valid property as well as .NumValue (as .NumValue will return zero if the text in the component is not a valid value for the type specified).

Who is online

Users browsing this forum: No registered users and 4 guests

About DataCAD Forum

The DataCAD Forum is a FREE online community we provide to enhance your experience with DataCAD.

We hope you'll visit often to get answers, share ideas, and interact with other DataCAD users around the world.

DataCAD

Software for AEC Professionals Since 1984