dwgOutFields does not get called

dwgOutFields does not get called

Anonymous
Not applicable
467 Views
4 Replies
Message 1 of 5

dwgOutFields does not get called

Anonymous
Not applicable
Hi!

I have encountered a strange situation:

First the short version:
------------------------
When I create a dictionary for a DWG-file, the dwgOutFields method gets
called when trying to close this document and the dictionary gets saved
correctly. When I then reopen the DWG-file, dwgInFields gets called (so
far, so good) and I modify some values of the Dictionary. When I then
try to close the document, dwgOutFields does _NOT_ get called and the
new values won't be stored.


Now the longer description:
---------------------------
I want to save the following class to my DWG file:

|| class AX3000_DWGData : public AcDbObject
|| {
|| private:
|| int m_nDimension;
||
|| public:
|| ACRX_DECLARE_MEMBERS(AX3000_DWGData);
|| AX3000_DWGData(): m_nDimension(0) {};
|| AX3000_DWGData(const int& val): m_nDimension(val) {};
||
|| int Dimension() { return m_nDimension; };
|| void Dimension(int _) { m_nDimension = _; };
||
|| virtual Acad::ErrorStatus dwgInFields(AcDbDwgFiler*);
|| virtual Acad::ErrorStatus dwgOutFields(AcDbDwgFiler*) const;
|| virtual Acad::ErrorStatus dxfInFields(AcDbDxfFiler*);
|| virtual Acad::ErrorStatus dxfOutFields(AcDbDxfFiler*) const;
|| };

I used the sample dwgInFields and dwgOutFields functions, which
look like this:

|| Acad::ErrorStatus AX3000_DWGData::dwgInFields(AcDbDwgFiler* pFiler)
|| {
|| assertWriteEnabled();
||
|| AcDbObject::dwgInFields(pFiler);
|| if (pFiler->filerType() == AcDb::kWblockCloneFiler) {
|| AcDbHardPointerId id;
|| pFiler->readItem(&id);
|| }
|| pFiler->readItem(&m_nDimension);
|| return pFiler->filerStatus();
|| }


|| Acad::ErrorStatus AX3000_DWGData::dwgOutFields(AcDbDwgFiler* pFiler) const
|| {
|| assertReadEnabled();
||
|| AcDbObject::dwgOutFields(pFiler);
|| if (pFiler->filerType() == AcDb::kWblockCloneFiler)
|| pFiler->writeHardPointerId((AcDbHardPointerId)ownerId());
|| pFiler->writeItem(m_nDimension);
|| return pFiler->filerStatus();
|| }

I use the overloaded "Dimension()" of AX3000_DWGData to store and read
the property "m_nDimension" from AX3000_DWGData, which works fine -
during runtime.

Everytime I retreive the dictionary handle from anywhere in my
ARX-Application, I get the correct value of m_nDimension.
If one part of my application increases m_nDimension, another part of my
Application retreives the correct value for it (Note: I always reget the
dictionary from the NamedObjectsDictionary just to be sure).

When I load a DWG-file with a dictionary in it, AutoCAD calls the above
listed dwgInFields Method and correctly reads in the value for the
property "m_nDimension", but when I then change m_nDimension with my
application and want to close AutoCad, no saving is done. Even If I
manually hit the "SAVE"-Button in AutoCAD, it does not call my
dwgOutFields method, so the value for m_nDimension is not updated in the
database.

Do I have to set a "dirty"-bit or something else for this dictionary to
be written out to the DWG-file?

Maybe some addiontal useful information:
When I open a new drawing in AutoCAD, which does not contain my
dictionary, I add this dictionary to the dwg-file with the following
function:

|| bool CreateDictionary()
|| {
|| AcDbDictionary *pNamedobj;
|| AcDbObjectId objId1;
|| AcDbDictionary *pDict;
|| AcDbDatabase *pCurDwg = acdbHostApplicationServices()->workingDatabase();
|| pCurDwg ->getNamedObjectsDictionary(pNamedobj, AcDb::kForWrite);
||
|| if(pNamedobj->getAt("AX3000_DATA", (AcDbObject*&) pDict, AcDb::kForWrite) == Acad::eKeyNotFound)
|| {
|| pDict = new AcDbDictionary;
|| AcDbObjectId DictId;
|| if(pNamedobj ->setAt("AX3000_DATA", pDict, DictId) != eOk)
|| {
|| pNamedobj ->close();
|| return false;
|| }
|| }
|| pNamedobj->close();
|| if (pDict)
|| {
|| if(pDict ->has("AX3000_DWGData"))
|| {
|| pDict ->close();
|| return true;
|| }
||
|| /* Add one instance of the AX3000_DWGData class to the dictionary */
|| AX3000_DWGData *pObj1 = new AX3000_DWGData(1);
|| AcDbObjectId rId1;
|| ErrorStatus es;
|| if((es = pDict->setAt("AX3000_DWGData", pObj1, rId1)) != eOk)
|| {
|| acutPrintf("\n%s\n", acadErrorStatusText(es));
|| pObj1 ->close();
|| pDict ->close();
|| return false;;
|| }
|| pObj1 ->close();
|| pDict->close();
|| }
|| else
|| return false;
|| return true;
|| }

When I then try to close AutoCAD, my dwgOutFields method gets called and
the dictionary is correctly stored inside the dwg-file.

Thanks in Advance,
--
| .-. | CCNA Alexander Griesser | .''`. |
| /v\ \ Software Developer, EDV Software Service / : :' : |
| /( )\ | Bahnhofstr. 8, 9500 Villach | `. `' |
| ^^ ^^ `-------------------------------------------------' `- |
0 Likes
468 Views
4 Replies
Replies (4)
Message 2 of 5

Anonymous
Not applicable
Alexander Griesser wrote:

Hi Alexander,

[...]
>|| int Dimension() { return m_nDimension; };
>|| void Dimension(int _) { m_nDimension = _; }; try this:

int Dimension() { assertReadEnabled(); return m_nDimension; };
void Dimension(int _) { if (_ != m_nDimension) { assertWriteEnabled();
m_nDimension = _;} };

HTH
Arnold
0 Likes
Message 3 of 5

Anonymous
Not applicable
* Arnold Eibel :
> >|| int Dimension() { return m_nDimension; };
> >|| void Dimension(int _) { m_nDimension = _; }; try this:
>
> int Dimension() { assertReadEnabled(); return m_nDimension; };
> void Dimension(int _) { if (_ != m_nDimension) { assertWriteEnabled();
> m_nDimension = _;} };

Ah, thanks, that does the trick.
Now, dwgOutFields gets called and when I step over it in the debugger, I
also can see the right value for m_nDimension before the call of
"pFiler ->writeItem(m_nDimension);". This call to writeItem then
returns "eOk" and everything seems fine, but when I then reload the
drawing again, "dwgInFields" always reads the default value for the
dictionary's property "m_nDimension", which I set when creating the
dictionary.

Any hints?

Again, thanks in Advance,
--
| .-. | CCNA Alexander Griesser | .''`. |
| /v\ \ Software Developer, EDV Software Service / : :' : |
| /( )\ | Bahnhofstr. 8, 9500 Villach | `. `' |
| ^^ ^^ `-------------------------------------------------' `- |
0 Likes
Message 4 of 5

Anonymous
Not applicable
Alexander Griesser wrote:

Hi,

> * Arnold Eibel :
>>>|| int Dimension() { return m_nDimension; };
>>>|| void Dimension(int _) { m_nDimension = _; }; try this:
>>
>> int Dimension() { assertReadEnabled(); return
>> m_nDimension; }; void Dimension(int _) { if (_ != m_nDimension)
>> { assertWriteEnabled(); m_nDimension = _;} };
>
> Ah, thanks, that does the trick.
> Now, dwgOutFields gets called and when I step over it in the
> debugger, I also can see the right value for m_nDimension before
> the call of "pFiler ->writeItem(m_nDimension);". This call to
> writeItem then returns "eOk" and everything seems fine, but when I
> then reload the drawing again, "dwgInFields" always reads the
> default value for the dictionary's property "m_nDimension", which
> I set when creating the dictionary.
>
> Any hints?

Because there is no function writeItem(int), writeItem(m_nDimension)
will call writeBool(). Try
this:

dwgOutFields:

...
filer->writeInt32(m_nDimension);
...

dwgInFields:

...
Adesk::Int32 i(0);
filer->readInt32(&i);
m_nDimension = i;
...

Grüße aus dem (herbstlichen) Odenwald
Arnold
0 Likes
Message 5 of 5

Anonymous
Not applicable
* Arnold Eibel :
> > * Arnold Eibel :
> >>>|| int Dimension() { return m_nDimension; };
> >>>|| void Dimension(int _) { m_nDimension = _; }; try this:
> >>
> >> int Dimension() { assertReadEnabled(); return
> >> m_nDimension; }; void Dimension(int _) { if (_ != m_nDimension)
> >> { assertWriteEnabled(); m_nDimension = _;} };
> >
> > Ah, thanks, that does the trick.
> > Now, dwgOutFields gets called and when I step over it in the
> > debugger, I also can see the right value for m_nDimension before
> > the call of "pFiler ->writeItem(m_nDimension);". This call to
> > writeItem then returns "eOk" and everything seems fine, but when I
> > then reload the drawing again, "dwgInFields" always reads the
> > default value for the dictionary's property "m_nDimension", which
> > I set when creating the dictionary.
>
> Because there is no function writeItem(int), writeItem(m_nDimension)
> will call writeBool().

In my documentation of the ObjectARX Interface, there is such a
function:

|| inline Acad::ErrorStatus
|| writeItem(
|| int val);
||
|| val int to be written out
||
|| This inline method calls the class's writeInt method (see
|| AcDbDwgFiler::writeInt for more information).

And therefore, I assumed, that that this would do just fine. But when I
tried to directly call WriteInt, I got an error, that the function does
not exist, which states, that you're right.

Now I use WriteInt32 and everything works fine, thanks for your help!
Mislead by Documentation 😕

ciao,
--
| .-. | CCNA Alexander Griesser | .''`. |
| /v\ \ Software Developer, EDV Software Service / : :' : |
| /( )\ | Bahnhofstr. 8, 9500 Villach | `. `' |
| ^^ ^^ `-------------------------------------------------' `- |
0 Likes