ObjectARX: DWGPROPS

ObjectARX: DWGPROPS

Anonymous
Not applicable
308 Views
13 Replies
Message 1 of 14

ObjectARX: DWGPROPS

Anonymous
Not applicable
Manipulating the drawing properties is simple enough in ARX but I've
discovered that unless the DWGPROPS command has been run at least once, you
cannot post any properties to the drawing. After much searching, I have not
found a way to initialize the drawing properties. Any ideas?

--
Attitudes are contagious. Is yours worth catching?
http://www.acadx.com
0 Likes
309 Views
13 Replies
Replies (13)
Message 2 of 14

Anonymous
Not applicable
Frank:

> After much searching, I have not found a way to initialize the
> drawing properties. Any ideas?

Have you tried acrxLoadApp? 🙂
--
Owen Wengerd
President, ManuSoft ==> http://www.manusoft.com
VP Americas, CADLock, Inc. ==> http://www.cadlock.com
0 Likes
Message 3 of 14

Anonymous
Not applicable
It seems a bit trickier than that. Unless the DWGPROPS dictionary already
exists, any attempt to update the summary info crashes AutoCAD even with
ACSIOBJ.ARX loaded. I thought about creating the dictionary myself but I
don't know how to attach an xrecord directly to the dictionary itself rather
than as an entry.

--
Attitudes are contagious. Is yours worth catching?
http://www.acadx.com

"Owen Wengerd" wrote in message
news:D387C6EBAFB879F07B0C783226D8BE69@in.WebX.SaUCah8kaAW...
> Have you tried acrxLoadApp? 🙂
0 Likes
Message 4 of 14

Anonymous
Not applicable
Hi Frank,

I had the same problem with props that had never been used with a VBA
program. I cheated and used "sendcommand" to load some lisp to create it if
VBA returned an error. Its posted below if you don't mind hacking it like I
did.

(setq xlist
(list
'(0 . "XRECORD")
'(100 . "AcDbXrecord")
'(1 . "DWGPROPS COOKIE")
(cons 2 "IPETitle")
(cons 3 "IPESubject")
(cons 4 "IPEAuthor")
(cons 6 "IPEComments")
(cons 7 "IPEKeywords")
(cons 8 (getvar "loginname"))
(cons 9 "IPERevNo")
(cons 300 "IPE Custom 1=Ftype")
(cons 301 "IPE Custom 2=A")
(cons 302 "IPE Custom 3=B")
(cons 303 "IPE Custom 4=C")
(cons 304 "IPE Custom 5=D")
(cons 305 "IPE Custom 6=E")
(cons 306 "IPE Custom 7=F")
(cons 307 "IPE Custom 8=G")
(cons 308 "IPE Custom 9=H")
(cons 309 "IPE Custom 10=J")
(cons 40 (getvar "TDINDWG"))
(cons 41 (getvar "TDCREATE"))
(cons 42 (getvar "TDUPDATE"))
)
)

(dictadd (namedobjdict) "DWGPROPS" (entmakex xlist))
(setq xlist nil)

Gary
0 Likes
Message 5 of 14

Anonymous
Not applicable
I came across a post from Frank Whaley that explained the same thing so I
tried to translate it to ARX. I'm having limited success. For some reason,
the call the acdbDictAdd always fails. To make things even more interesting,
ERRNO gets set to 1083. The highest value listed in ol_errno.h is 105. Go
figure. Here's the code I'm using (I'm usre the word wrapping will be simply
hideous). Lots of code omitted for brevity:

if (pDict->getAt("DWGPROPS", (AcDbObject*&) pDict, AcDb::kForRead) ==
Acad::eKeyNotFound)
{
struct resbuf* pRbList = NULL;
struct resbuf* pRbEdit = NULL;
struct resbuf* pRbCreated = NULL;
struct resbuf* pRbSaved = NULL;
ads_name xname, maindict;
char* dictName = "DWGPROPS";

pRbEdit = acutNewRb(AcDb::kDxfReal);
pRbCreated = acutNewRb(AcDb::kDxfReal);
pRbSaved = acutNewRb(AcDb::kDxfReal);

if (acdbGetAdsName(maindict, pDict->objectId()) != Acad::eOk)
return E_FAIL;

acedGetVar("TDINDWG", pRbEdit);
acedGetVar("TDCREATE", pRbCreated);
acedGetVar("TDUPDATE", pRbSaved);
pRbList = acutBuildList(RTDXF0 , "XRECORD",
100, "AcDbXrecord",
1, "DWGPROPS COOKIE",
2, "",
3, "",
4, "",
5, "",
6, "",
7, "",
8, "",
9, "",
300, "=",
301, "=",
302, "=",
303, "=",
304, "=",
305, "=",
306, "=",
307, "=",
308, "=",
309, "=",
40, pRbEdit->resval.rreal,
41, pRbCreated->resval.rreal,
42, pRbSaved->resval.rreal,
RTNONE);

if (acdbEntMakeX(pRbList, xname) != RTNORM)
return E_FAIL
// This fails every time.
if (acdbDictAdd(maindict, dictName, xname) != RTNORM)
return E_FAIL;
}

--
Attitudes are contagious. Is yours worth catching?
http://www.acadx.com

"Gary McMaster" wrote in message
news:7948AFB114BD198A7EB28F5B98798322@in.WebX.SaUCah8kaAW...
> Hi Frank,
>
> I had the same problem with props that had never been used with a VBA
> program. I cheated and used "sendcommand" to load some lisp to create it
if
> VBA returned an error. Its posted below if you don't mind hacking it like
I
> did.
>
> (setq xlist
> (list
> '(0 . "XRECORD")
> '(100 . "AcDbXrecord")
> '(1 . "DWGPROPS COOKIE")
> (cons 2 "IPETitle")
> (cons 3 "IPESubject")
> (cons 4 "IPEAuthor")
> (cons 6 "IPEComments")
> (cons 7 "IPEKeywords")
> (cons 8 (getvar "loginname"))
> (cons 9 "IPERevNo")
> (cons 300 "IPE Custom 1=Ftype")
> (cons 301 "IPE Custom 2=A")
> (cons 302 "IPE Custom 3=B")
> (cons 303 "IPE Custom 4=C")
> (cons 304 "IPE Custom 5=D")
> (cons 305 "IPE Custom 6=E")
> (cons 306 "IPE Custom 7=F")
> (cons 307 "IPE Custom 8=G")
> (cons 308 "IPE Custom 9=H")
> (cons 309 "IPE Custom 10=J")
> (cons 40 (getvar "TDINDWG"))
> (cons 41 (getvar "TDCREATE"))
> (cons 42 (getvar "TDUPDATE"))
> )
> )
>
> (dictadd (namedobjdict) "DWGPROPS" (entmakex xlist))
> (setq xlist nil)
>
> Gary
>
0 Likes
Message 6 of 14

Anonymous
Not applicable
That stuff came to me from Frank via Kent Keller. I thought I was doing
something wrong when I was unable to create the props from VBA. I hate using
"sendcommand" but its the only thing I could get to work.

Gary
0 Likes
Message 7 of 14

Anonymous
Not applicable
Ok, I give up. After spotting some flaws in my original code, I went back
and performed what I believe to be an exact LISP to ARX translation of a
post from Frank Whaley. I simply cannot create the DWGPROPS dictionary.
Here's the code. Can anyone tell where I'm going wrong? acdbDictAdd fails
every time and sets ERRNO to 1083.

AcApDocument* pDoc = NULL;
pDoc = acDocManager->mdiActiveDocument();
AcDbObjectPointer
pDict(pDoc->database()->namedObjectsDictionaryId(), AcDb::kForRead);

if (pDict.openStatus() != Acad::eOk)
return E_FAIL;

struct resbuf* pDwgProps = NULL;
ads_name namedObj;

acdbNamedObjDict(namedObj);
pDwgProps = acdbDictSearch(namedObj, "DWGPROPS", 0);

if (pDwgProps == NULL)
{
if (acDocManager->lockDocument(pDoc, AcAp::kAutoWrite) != Acad::eOk)
return E_FAIL;
pDict->upgradeOpen();

struct resbuf* pRbEdit = NULL;
struct resbuf* pRbCreated = NULL;
struct resbuf* pRbSaved = NULL;
ads_name dictName;

pRbEdit = acutNewRb(AcDb::kDxfReal);
pRbCreated = acutNewRb(AcDb::kDxfReal);
pRbSaved = acutNewRb(AcDb::kDxfReal);
acedGetVar("TDINDWG", pRbEdit);
acedGetVar("TDCREATE", pRbCreated);
acedGetVar("TDUPDATE", pRbSaved);
pDwgProps = acutBuildList(RTDXF0 , "XRECORD",
100, "AcDbXrecord",
1, "DWGPROPS COOKIE",
2, "",
3, "",
4, "",
5, "",
6, "",
7, "",
8, "",
9, "",
300, "=",
301, "=",
302, "=",
303, "=",
304, "=",
305, "=",
306, "=",
307, "=",
308, "=",
309, "=",
40, pRbEdit->resval.rreal,
41, pRbCreated->resval.rreal,
42, pRbSaved->resval.rreal,
1, "",
RTNONE);

acdbEntMakeX(pDwgProps, dictName);
acutRelRb(pDwgProps);
acutRelRb(pRbEdit);
acutRelRb(pRbCreated);
acutRelRb(pRbSaved);

if (acdbDictAdd(namedObj, "DWGPROPS", dictName) != RTNORM)
return E_FAIL;

--
Attitudes are contagious. Is yours worth catching?
http://www.acadx.com
0 Likes
Message 8 of 14

Anonymous
Not applicable
Got it! Among other things (like my including a bogus group code 5), I've
discovered that acdbDictAdd fails if the object is already open. The
solution is to simply close the namedObjectDictionary pointer before calling
acdbDictAdd.

--
Attitudes are contagious. Is yours worth catching?
http://www.acadx.com

"Frank Oquendo" wrote in message
news:96E4F296DFF80CF7626F599C3525C601@in.WebX.SaUCah8kaAW...
> Ok, I give up. After spotting some flaws in my original code, I went back
> and performed what I believe to be an exact LISP to ARX translation of a
> post from Frank Whaley. I simply cannot create the DWGPROPS dictionary.
> Here's the code. Can anyone tell where I'm going wrong? acdbDictAdd fails
> every time and sets ERRNO to 1083.
0 Likes
Message 9 of 14

Anonymous
Not applicable
For anyone still reading this thread, the solution to manipulating the
DWGPROPS dictionary is to be sure that ACSIOBJ.ARX is loaded *before*
calling acdbGetSummaryInfo. That's it. Nice of Autodesk of to leave that
little tidbit out of the documentation, huh?

--
Attitudes are contagious. Is yours worth catching?
http://www.acadx.com

Frank Oquendo wrote in message
news:AA2AEF6A2B01CD4EE32223F1A9013177@in.WebX.SaUCah8kaAW...
> Manipulating the drawing properties is simple enough in ARX but I've
> discovered that unless the DWGPROPS command has been run at least once,
you
> cannot post any properties to the drawing. After much searching, I have
not
> found a way to initialize the drawing properties. Any ideas?
0 Likes
Message 10 of 14

Anonymous
Not applicable
Frank,

You left me in the dust with the arx stuff. Do your findings indicate that
it should be possible to perform the initialization from VBA?

Gary
0 Likes
Message 11 of 14

Anonymous
Not applicable
I honestly don't know. It appears that ACSIOBJ.ARX's only job is to support
the acdbDatabaseSummaryInfo object. Since this object doesn't appear to be
available to VB, I don't think loading it would help. The real puzzle is how
do you attach an xrecord to, and read it directly from, a Dictionary object
in VB. All the methods are aimed at manipulating entries rather than the
dictionary itself.

--
Attitudes are contagious. Is yours worth catching?
http://www.acadx.com

"Gary McMaster" wrote in message
news:4EE39C1719AA679C6A8E08B868A58736@in.WebX.SaUCah8kaAW...
> Frank,
>
> You left me in the dust with the arx stuff. Do your findings indicate that
> it should be possible to perform the initialization from VBA?
>
> Gary
>
0 Likes
Message 12 of 14

Anonymous
Not applicable
Thanks Frank. I have it working, but don't like the way I had to do it.

Gary
0 Likes
Message 13 of 14

Anonymous
Not applicable
Frank Oquendo wrote:

> I came across a post from Frank Whaley that explained the same thing so I
> tried to translate it to ARX.

In ARX, I do it a little differently:

// build resbuf chain
resbuf *rb = acutBuildList(
1, "DWGPROPS COOKIE",
...
RTNONE);
if ( rb == NULL )
return false;

// create Xrecord and attach resbuf chain
AcDbXrecord *props = new AcDbXrecord;
bool isOk;
if ( props != NULL )
isOk = EOK(props->setFromRbChain(*rb));
acutRelRb(rb);

// quit now if error
if ( !isOk )
{
delete props;
return false;
}

// add to Named Object Dictionary
AcDbDictionary *nod;
AcDbObjectId id;

isOk = false;
if ( EOK(acdbCurDwg()->getNamedObjectsDictionary(nod, AcDb::kForWrite)) )
{
if ( EOK(nod->setAt("DWGPROPS", props, id)) )
isOk = true;
nod->close();
}

props->close();
return isOk;

The 'EOK()' function used above looks like:

inline int EOK(Acad::ErrorStatus arg)
{ return arg == Acad::eOk; }
--
Frank Whaley
Autodesk, Inc.
0 Likes
Message 14 of 14

Anonymous
Not applicable
Actually, it turns out that none of that is necessary so long as ACSIOBJ.ARX
is loaded prior to calling acdbGetSummaryInfo. The ensuing call to
acdbPutSummaryInfo will create the dictionary if it doesn't exist. In fact,
if you use the AcDbDatabaseSummaryInfo object at all, loading acsiobj is not
optional as attempting to update the drawing properties will crash AutoCAD
without it.

Of course, if I ever decide to handle the drawing properties manually, you
can bet I'll be referring to this post. Thanks for the input.

--
Attitudes are contagious. Is yours worth catching?
http://www.acadx.com

"Frank Whaley" wrote in message
news:39A6A21A.F601BB70@autodesk.com...
> Frank Oquendo wrote:
>
> > I came across a post from Frank Whaley that explained the same thing so
I
> > tried to translate it to ARX.
>
> In ARX, I do it a little differently:
>
> // build resbuf chain
> resbuf *rb = acutBuildList(
> 1, "DWGPROPS COOKIE",
> ...
> RTNONE);
> if ( rb == NULL )
> return false;
>
> // create Xrecord and attach resbuf chain
> AcDbXrecord *props = new AcDbXrecord;
> bool isOk;
> if ( props != NULL )
> isOk = EOK(props->setFromRbChain(*rb));
> acutRelRb(rb);
>
> // quit now if error
> if ( !isOk )
> {
> delete props;
> return false;
> }
>
> // add to Named Object Dictionary
> AcDbDictionary *nod;
> AcDbObjectId id;
>
> isOk = false;
> if ( EOK(acdbCurDwg()->getNamedObjectsDictionary(nod,
AcDb::kForWrite)) )
> {
> if ( EOK(nod->setAt("DWGPROPS", props, id)) )
> isOk = true;
> nod->close();
> }
>
> props->close();
> return isOk;
>
> The 'EOK()' function used above looks like:
>
> inline int EOK(Acad::ErrorStatus arg)
> { return arg == Acad::eOk; }
> --
> Frank Whaley
> Autodesk, Inc.
>
0 Likes