Switching layouts in .net

Switching layouts in .net

Anonymous
Not applicable
1,288 Views
6 Replies
Message 1 of 7

Switching layouts in .net

Anonymous
Not applicable
Hello,
I've written a dll that cycles through a set of drawings using databaseservices. I'm using the readdwgfile method to open my drawings. All is going well with one exception. I need to delete some unused layouts. I can delete them, but when I reopen the drawing, I discover I need to recover them. This occurs because in some instances I'm deleting the current layout. Is there a way to switch the current layout without having to physically open the drawing? I'm trying the layoutmanager.current.currentlayout method without success. Any other ideas?

Thanks in advance,
Ceorl
0 Likes
1,289 Views
6 Replies
Replies (6)
Message 2 of 7

Anonymous
Not applicable
Try setting the value of the HostApplicationServices WorkingDatabase property to the database containing the layouts you're trying to switch.

Make sure to save the current value and restore it afterwards.

--
http://www.caddzone.com

AcadXTabs: MDI Document Tabs for AutoCAD 2009
Supporting AutoCAD 2000 through 2009

http://www.acadxtabs.com

Introducing AcadXTabs 2010:
http://www.caddzone.com/acadxtabs/AcadXTabs2010.htm

wrote in message news:5979608@discussion.autodesk.com...
Hello,
I've written a dll that cycles through a set of drawings using databaseservices. I'm using the readdwgfile method to open my drawings. All is going well with one exception. I need to delete some unused layouts. I can delete them, but when I reopen the drawing, I discover I need to recover them. This occurs because in some instances I'm deleting the current layout. Is there a way to switch the current layout without having to physically open the drawing? I'm trying the layoutmanager.current.currentlayout method without success. Any other ideas?

Thanks in advance,
Ceorl
0 Likes
Message 3 of 7

Anonymous
Not applicable
Hey, I appreciate the help. The code cycles through every drawing and switch layouts as intended, but when all is said and done, I get an exception error from:

inline void* CThreadSlotData::GetThreadValue(int nSlot)
{
EnterCriticalSection(&m_sect);
ASSERT(nSlot != 0 && nSlot < m_nMax);
ASSERT(m_pSlotData != NULL);
ASSERT(m_pSlotData[nSlot].dwFlags & SLOT_USED);
ASSERT(m_tlsIndex != (DWORD)-1);
if( nSlot <= 0 || nSlot >= m_nMax ) // check for retail builds.
{
LeaveCriticalSection(&m_sect);
return NULL;
}

CThreadData* pData = (CThreadData*)TlsGetValue(m_tlsIndex);
if (pData == NULL || nSlot >= pData->nCount)
{
LeaveCriticalSection(&m_sect);
return NULL;
}
void* pRetVal = pData->pData[nSlot];
LeaveCriticalSection(&m_sect);
return pRetVal;
}

The code stops on the return pRetVal line. Do you know what's happening here?

So you have something to visualize, I have a DWG class that looks like:

Public Class Dwg
Private DwgName As String
Private Visibility As Boolean
Private MyDwg As Autodesk.AutoCAD.ApplicationServices.Document
Private MyDb As Autodesk.AutoCAD.DatabaseServices.Database
Private MyTransMan As Autodesk.AutoCAD.DatabaseServices.TransactionManager
Private MyTrans As Autodesk.AutoCAD.DatabaseServices.Transaction
Private MyEd As Autodesk.AutoCAD.EditorInput.Editor
Private CurDb As Autodesk.AutoCAD.DatabaseServices.Database

Public Sub New(ByVal DrawingName As String, ByVal Visible As Boolean)
If Visible = True Then
Visibility = True
MyDwg = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.Open(DrawingName, False)
MyDb = MyDwg.Database
MyDwg.LockDocument()
MyTransMan = MyDwg.TransactionManager
MyTrans = MyTransMan.StartTransaction
Else
Visibility = False
MyDb = New DatabaseServices.Database(False, True)
MyDb.ReadDwgFile(DrawingName, IO.FileShare.ReadWrite, True, "")
MyTransMan = MyDb.TransactionManager
MyTrans = MyTransMan.StartTransaction
CurDb = HostApplicationServices.WorkingDatabase
HostApplicationServices.WorkingDatabase = MyDb
End If
DwgName = DrawingName
End Sub

Public Sub EndDrawing()
MyTrans.Commit()
MyTrans.Dispose()
MyTransMan.Dispose()
If Visibility = True Then
MyDwg.CloseAndSave(DwgName)
MyDb.Dispose()
mydwg.Dispose
Else
HostApplicationServices.WorkingDatabase = CurDb
CurDb.Dispose()
MyDb.SaveAs(DwgName, DwgVersion.Current)
MyDb.Dispose()
End If

End Sub
End Class

When I create the new drawing object, I provide a drawing name and a visibility option to determine whether the drawing opens as a drawing or a database. I establish my transactions, database, etc... I then use various methods that are unseen above and ultimately close the drawing/database using the EndDrawing method, which closes and disposes the transactions, databases, etc.

If I understand your suggestion, it was to set the the HostApplicationServices.WorkingDatabase to the database I have open and to reset it back to the default when I was done.

Record curent database:
CurDb = HostApplicationServices.WorkingDatabase

Set database:
HostApplicationServices.WorkingDatabase = MyDb

Set it back:
HostApplicationServices.WorkingDatabase = CurDb

And dispose of it?
CurDb.Dispose()

Once again, any thoughts or suggestions are very much appreciated.
Ceorl
0 Likes
Message 4 of 7

Anonymous
Not applicable
Sorry, but I don't see what the code you say is throwing the exception from has to do with switching layouts in managed code. That's C++.

Read my first reply again. You can't leave the current working database set to your database any longer than needed. Your code should change the current working database, switch layouts or do whatever else it needs to do with the LayoutManager, and then immediately switch the current working database back to what it was originally.

// Save the current working database

Database original = HostApplicationServices.WorkingDatabase;

// Set the current working database to the one
// you need to switch layouts in

HostApplicationServices.WorkingDatabase = myDb;

// switch layouts here or do whatever with LayoutManager
LayoutManager.Current.CurrentLayout = ....

// Restore the current working database IMMEDIATELY

HostApplicationServices.WorkingDatabase = original

--
http://www.caddzone.com

AcadXTabs: MDI Document Tabs for AutoCAD 2009
Supporting AutoCAD 2000 through 2009

http://www.acadxtabs.com

Introducing AcadXTabs 2010:
http://www.caddzone.com/acadxtabs/AcadXTabs2010.htm

wrote in message news:5980828@discussion.autodesk.com...
Hey, I appreciate the help. The code cycles through every drawing and switch layouts as intended, but when all is said and done, I get an exception error from:

inline void* CThreadSlotData::GetThreadValue(int nSlot)
{
EnterCriticalSection(&m_sect);
ASSERT(nSlot != 0 && nSlot < m_nMax);
ASSERT(m_pSlotData != NULL);
ASSERT(m_pSlotData[nSlot].dwFlags & SLOT_USED);
ASSERT(m_tlsIndex != (DWORD)-1);
if( nSlot <= 0 || nSlot >= m_nMax ) // check for retail builds.
{
LeaveCriticalSection(&m_sect);
return NULL;
}

CThreadData* pData = (CThreadData*)TlsGetValue(m_tlsIndex);
if (pData == NULL || nSlot >= pData->nCount)
{
LeaveCriticalSection(&m_sect);
return NULL;
}
void* pRetVal = pData->pData[nSlot];
LeaveCriticalSection(&m_sect);
return pRetVal;
}

The code stops on the return pRetVal line. Do you know what's happening here?

So you have something to visualize, I have a DWG class that looks like:

Public Class Dwg
Private DwgName As String
Private Visibility As Boolean
Private MyDwg As Autodesk.AutoCAD.ApplicationServices.Document
Private MyDb As Autodesk.AutoCAD.DatabaseServices.Database
Private MyTransMan As Autodesk.AutoCAD.DatabaseServices.TransactionManager
Private MyTrans As Autodesk.AutoCAD.DatabaseServices.Transaction
Private MyEd As Autodesk.AutoCAD.EditorInput.Editor
Private CurDb As Autodesk.AutoCAD.DatabaseServices.Database

Public Sub New(ByVal DrawingName As String, ByVal Visible As Boolean)
If Visible = True Then
Visibility = True
MyDwg = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.Open(DrawingName, False)
MyDb = MyDwg.Database
MyDwg.LockDocument()
MyTransMan = MyDwg.TransactionManager
MyTrans = MyTransMan.StartTransaction
Else
Visibility = False
MyDb = New DatabaseServices.Database(False, True)
MyDb.ReadDwgFile(DrawingName, IO.FileShare.ReadWrite, True, "")
MyTransMan = MyDb.TransactionManager
MyTrans = MyTransMan.StartTransaction
CurDb = HostApplicationServices.WorkingDatabase
HostApplicationServices.WorkingDatabase = MyDb
End If
DwgName = DrawingName
End Sub

Public Sub EndDrawing()
MyTrans.Commit()
MyTrans.Dispose()
MyTransMan.Dispose()
If Visibility = True Then
MyDwg.CloseAndSave(DwgName)
MyDb.Dispose()
mydwg.Dispose
Else
HostApplicationServices.WorkingDatabase = CurDb
CurDb.Dispose()
MyDb.SaveAs(DwgName, DwgVersion.Current)
MyDb.Dispose()
End If

End Sub
End Class

When I create the new drawing object, I provide a drawing name and a visibility option to determine whether the drawing opens as a drawing or a database. I establish my transactions, database, etc... I then use various methods that are unseen above and ultimately close the drawing/database using the EndDrawing method, which closes and disposes the transactions, databases, etc.

If I understand your suggestion, it was to set the the HostApplicationServices.WorkingDatabase to the database I have open and to reset it back to the default when I was done.

Record curent database:
CurDb = HostApplicationServices.WorkingDatabase

Set database:
HostApplicationServices.WorkingDatabase = MyDb

Set it back:
HostApplicationServices.WorkingDatabase = CurDb

And dispose of it?
CurDb.Dispose()

Once again, any thoughts or suggestions are very much appreciated.
Ceorl
Message 5 of 7

Anonymous
Not applicable
No, I apologize. I provided not enough information in some areas, and too much in others. The C++ code is in an AFXTLS.CPP file, and the error appears after all the code has been executed. The AFXTLS.CPP file is nothing I wrote, and its origin is unknown to me. Your suggestion worked, but now I'm dealing with a new error, and like you, I don't understand what the relationship is between switching layouts and the AFXTLS.CPP file is (there may not even be one), I just know I'm getting an error when I try to switch working databases. If I exclude my SetLayout method (see below), my layouts don't switch, but I'm error free.

The MyDb variable is a private class variable established when I create a new drawing object. I use it throughout the class, and so far, I haven't had any trouble with it (although, I wouldn't rule it out).

Public Sub SetLayout(ByVal LName As String)
Dim CurDb As Autodesk.AutoCAD.DatabaseServices.Database

CurDb = HostApplicationServices.WorkingDatabase
HostApplicationServices.WorkingDatabase = MyDb

Dim MyLayoutMan As Autodesk.AutoCAD.DatabaseServices.LayoutManager
MyLayoutMan = LayoutManager.Current
MyLayoutMan.CurrentLayout = LName

HostApplicationServices.WorkingDatabase = CurDb
CurDb.Dispose()

End Sub

Thank you,
Ceorl
0 Likes
Message 6 of 7

Anonymous
Not applicable
Get rid of the call to CurDb.Dispose() for starters, because
you don't call Dispose() on databases you did not create.

Second, what's the error?

--
http://www.caddzone.com

AcadXTabs: MDI Document Tabs for AutoCAD 2009
Supporting AutoCAD 2000 through 2009

http://www.acadxtabs.com

Introducing AcadXTabs 2010:
http://www.caddzone.com/acadxtabs/AcadXTabs2010.htm

wrote in message news:5983983@discussion.autodesk.com...
No, I apologize. I provided not enough information in some areas, and too much in others. The C++ code is in an AFXTLS.CPP file, and the error appears after all the code has been executed. The AFXTLS.CPP file is nothing I wrote, and its origin is unknown to me. Your suggestion worked, but now I'm dealing with a new error, and like you, I don't understand what the relationship is between switching layouts and the AFXTLS.CPP file is (there may not even be one), I just know I'm getting an error when I try to switch working databases. If I exclude my SetLayout method (see below), my layouts don't switch, but I'm error free.

The MyDb variable is a private class variable established when I create a new drawing object. I use it throughout the class, and so far, I haven't had any trouble with it (although, I wouldn't rule it out).

Public Sub SetLayout(ByVal LName As String)
Dim CurDb As Autodesk.AutoCAD.DatabaseServices.Database

CurDb = HostApplicationServices.WorkingDatabase
HostApplicationServices.WorkingDatabase = MyDb

Dim MyLayoutMan As Autodesk.AutoCAD.DatabaseServices.LayoutManager
MyLayoutMan = LayoutManager.Current
MyLayoutMan.CurrentLayout = LName

HostApplicationServices.WorkingDatabase = CurDb
CurDb.Dispose()

End Sub

Thank you,
Ceorl
0 Likes
Message 7 of 7

Anonymous
Not applicable
I got rid of the .dispose (I found that suggestion on another post you made). The error occurs on line:

return pRetVal;

in CThreadSlotData::GetThreadValue of the afxtls.cpp file. It is:

Unhandled exception at 0x004bd022 in acad.exe: 0xC0000005: Access violation reading location 0x7efea8bc.

Ceorl
0 Likes