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

#74938 by dhs
Sat Oct 06, 2018 1:01 am
Hi,
The Delphi version of the Lyr_Set procedure does not appear to work.
I have written a simple test macro which simply attempts to create a new layer and then set it as the active layer. The new layer is created ok, but it is not set as the active layer. Code of this test macro is below:
Code: Select alllibrary LyrTest;

{$E dmx}  // dmx is the extension for DCAL Dll's
{$R *.res}

uses
  UConstants in 'C:\DataCAD 20\DCAL for Delphi\Header Files\UConstants.pas',
  UInterfaces in 'C:\DataCAD 20\DCAL for Delphi\Header Files\UInterfaces.pas',
  UInterfacesRecords in 'C:\DataCAD 20\DCAL for Delphi\Header Files\UInterfacesRecords.pas',
  URecords in 'C:\DataCAD 20\DCAL for Delphi\Header Files\URecords.pas',
  UVariables in 'C:\DataCAD 20\DCAL for Delphi\Header Files\UVariables.pas';

type
  LyrTestL = record
    state: asint;
    LyrName : str255;
    case byte of
      0: (gete: getescarg);
      1: (gets: DgetstrArg);
    end;

  PLyrTestL = ^LyrTestL;

function LyrTest_world_main(act: action; pl, pargs: Pointer): wantType;
var
  retval: asint;
  l: PLyrTestL;
  addr : lyraddr;
begin
  l := PLyrTestL(pl);

  if act = aagain then begin
    case l^.state of
      1: case l^.gete.key of
            f1: l^.state := 2;
            s0: l^.state := 0;
         end;
      2: begin
           wrtmsg('');
           if  l^.gets.Result = res_normal then begin
              lyr_create (l^.LyrName, addr);
              lyr_set (addr);
           end;
           l^.state := 1;
         end;
      else l^.state := 0;
    end;
  end;

  if act = Afirst then
    l^.state := 1
  else if act = AlSize then
    SetLocalSize(sizeof(l^));

  if act <> AlSize then begin
    case l^.state of
      1: begin
          wrtlvl('LyrTest');
          lblsinit;
          lblset(1, 'New Layer', 'Create new layer and set it as active');
          lblset(20, 'Exit');
          lblson;
          getesc(l^.gete, retval);
        end;
      2: begin
          lblsinit;
          lblson;
          wrtmsg('Layer Name: ', true);
          callDGetstr255(l^.LyrName, 70, l^.gets, retval);
        end;
      else retval := XDone;
    end;
  end;
  Result := retval;
end;

function Main(dcalstate: asint; act: action; pl, pargs: Pointer): wantType; stdcall;
begin
  case dcalstate of
    XDcalStateBegin: Result := LyrTest_world_main(act, pl, pargs);
  else Result := XDone;
  end;
end;

exports
  Main;

begin

end.

I don't think I am doing anything wrong? Can anybody offer advice on the use of Lyr_Set in D4D ?
#75653 by Mark F. Madura
Thu Feb 07, 2019 2:08 pm
Tracing through the debugger in DataCAD, the procedure lyr_set makes a call to valid_addr which returns false and the subsequent call to lyr_setcurr never gets called.
#75654 by Mark F. Madura
Thu Feb 07, 2019 3:33 pm
I'm still digging into this a bit. It looks like you'll have to declare a layer record to store the layer address.

rlyr: Rlayer

Once the address for the layer you want is stored in the record, you can call...

lyr_set(rlyr.addr)
#75658 by dhs
Thu Feb 07, 2019 9:28 pm
Thanks Mark,

Given the lack of any response to my post 4 months ago I assumed I was correct in thinking Lyr_Set did not work. Following your posts I have had another look at it and discovered that the problem is actually with Lyr_Create.
I had assumed that Lyr_Create returned the address of the created layer in the var addr parameter. I still think that is probably the intention, but it appears that it does not return a valid address.

I have used Rlayer in the past, but didn't quite follow your logic to store the layer address in an Rlayer variable. I tried adding a lyr_get call to put the address in the Rlayer parameter, but that resulted in a drawing crash (fault 19 Error from: 73). See the commented lines in the code fragment below for that logic.

Next I tried retrieving the new layer by name using lyr_find, and passing the address returned by lyr_find to lyr_set. That did in fact work. The updated code fragment (from the code in my first post) is shown below:

Code: Select all      2: begin
           wrtmsg('');
           if  l^.gets.Result = res_normal then begin
              lyr_create (l^.LyrName, addr);

              {following code results in fault 19 Error from: 73 }
              //if lyr_get(addr, rlyr) then
                //lyr_set (rlyr.addr);

              {following code works}
              if lyr_find (l^.LyrName, addr) then
                lyr_set (addr);
           end;
           l^.state := 1;
         end;


Note: using the name to retrieve the new layer is not 100% reliable as duplicate layer names are possible ... I think the DataCAD UI prevents duplicates, but the underlying database allows them and a macro can still create duplicates. This is not a problem for me at this stage, just mentioning it out of interest.

Who is online

Users browsing this forum: No registered users and 2 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