TheSwamp
Code Red => .NET => Topic started by: mohnston on January 09, 2007, 12:43:55 PM
-
I'm trying to add a piece of text to a drawing and then save and close the drawing.
This code runs without error but the text is not on the drawing when I open it to check.
There has to be something simple wrong.
Won't you help? Look deep inside yourself and do the right thing.
private void StampDrawing(string fullDwgPath, string stampString)
{
Document ThisDrawing = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.Open(fullDwgPa th);
ThisDrawing.LockDocument();
Database thisDB = ThisDrawing.Database;
Autodesk.AutoCAD.ApplicationServices.TransactionManager tm = ThisDrawing.TransactionManager;
using (Transaction trans = tm.StartTransaction())
{
BlockTable bt = (BlockTable)thisDB.BlockTableId.GetObject(OpenMode.ForWrite);
BlockTableRecord modelsp = (BlockTableRecord)trans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
DBText stampText = new DBText();
stampText.TextString = stampString;
stampText.Height = 12;
stampText.HorizontalMode = TextHorizontalMode.TextRight;
stampText.Rotation = 0;
modelsp.AppendEntity(stampText);
trans.TransactionManager.AddNewlyCreatedDBObject(stampText, true);
trans.Commit();
}
tm.Dispose();
ThisDrawing.CloseAndSave(fullDwgPath);
thisDB.Dispose();
}
-
I don't see where you have set the location of the text. Could that be it?
Here is some C++ code that might help. I know it's not C#, but it's close enough that you should be able to get the gist of it.
AcDbObjectId AcadUtilities::addText(
const AcGePoint3d& insertion,
const double& height,
const double& rotation,
const AcDb::TextHorzMode& horizMode,
const AcDb::TextVertMode& vertMode,
const string& textString,
const string& layerName) {
AcDbObjectPointer<AcDbText> textObj;
if(textObj.create() != Acad::eOk) {
acutPrintf("\nUnable to create text object.");
return AcDbObjectId::kNull;
}
textObj->setHeight(height);
textObj->setRotation(rotation);
textObj->setHorizontalMode(horizMode);
textObj->setVerticalMode(vertMode);
textObj->setTextString(textString.c_str());
appendObject(textObj.object());
textObj->setLayer(layerName.c_str());
if((horizMode == AcDb::kTextLeft) && (vertMode == AcDb::kTextBase))
textObj->setPosition(insertion);
else
textObj->setAlignmentPoint(insertion);
return textObj->objectId();
}
-
This works...
[CommandMethod("ADDTEXT")]
public void addText()
{
Document doc = acadApp.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
Database db = doc.Database;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
DBText stampText = new DBText();
stampText.TextString = "TESTING";
stampText.Height = 12;
stampText.HorizontalMode = TextHorizontalMode.TextRight;
stampText.Rotation = 0;
btr.AppendEntity(stampText);
tr.AddNewlyCreatedDBObject(stampText, true);
tr.Commit();
}
}
-
BlockTable bt = (BlockTable)thisDB.BlockTableId.GetObject(OpenMode.ForWrite);
BlockTableRecord modelsp = (BlockTableRecord)trans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
After reviewing your code a little more, the problem is on those lines, change it to:
BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
BlockTableRecord modelsp = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
Have fun
note: make sure you use your own thisDB instead of db
-
You might be on the right track LE.
I made the changes you suggest but not joy.
I suspect it has something to do with working on a drawing that is not the current drawing when the code starts.
private void StampDrawing(string fullDwgPath, string stampString, bool FullSize)
{
Document ThisDrawing = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.Open(fullDwgPath);
ThisDrawing.LockDocument();
Database thisDB = ThisDrawing.Database;
Autodesk.AutoCAD.DatabaseServices.TransactionManager tm = ThisDrawing.Database.TransactionManager;
using (Transaction trans = tm.StartTransaction())
{
BlockTable bt = (BlockTable)trans.GetObject(thisDB.BlockTableId, OpenMode.ForWrite);
BlockTableRecord modelsp = (BlockTableRecord)trans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
DBText stampText = new DBText();
stampText.TextString = stampString;
stampText.Height = 12;
stampText.HorizontalMode = TextHorizontalMode.TextRight;
stampText.Rotation = 0;
Point3d pIns = new Point3d(1070, 15, 0);
stampText.Position = pIns;
modelsp.AppendEntity(stampText);
trans.TransactionManager.AddNewlyCreatedDBObject(stampText, true);
trans.Commit();
}
tm.Dispose();
ThisDrawing.CloseAndSave(fullDwgPath);
thisDB.Dispose();
}
Your example code doesn't do what I need.
I need to open a document, add the text, save the document and close it.
Chuck, thanks for the C++ but I'm C++ illiterate. It might as well be C%$#@.
I was concerned about the location of the text also. I thought I would tackle this first and make location another thread.
There is no setPosition or setAlignmentpoint method for DBText.
There is a Position property which I set in this revised code.
Text is not on drawing when I open it.
-
Ok... I might end up running some tests if I had a chance.
For the alignment you need to use: TextHorizontalMode
-
If I use, a session command, at least adds the text, but shows an error...
[CommandMethod("TESTEXT", CommandFlags.Session)]
public void txt()
{
StampDrawing("C:\\test.dwg", "TESTING", true);
}
-
I see.... you know what, the call to ThisDrawing is doing a Read-Only....
-
Here is the code that is working, we need to make sure the preview will be saved...
[CommandMethod("TXT", CommandFlags.Session)]
public void txt()
{
StampDrawing("C:\\test.dwg", "TESTING", true);
}
private void StampDrawing(string fullDwgPath, string stampString, bool FullSize)
{
Document ThisDrawing = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.Open(fullDwgPath, false);
ThisDrawing.LockDocument();
Database thisDB = ThisDrawing.Database;
Autodesk.AutoCAD.DatabaseServices.TransactionManager tm = ThisDrawing.Database.TransactionManager;
using (Transaction trans = tm.StartTransaction())
{
BlockTable bt = (BlockTable)trans.GetObject(thisDB.BlockTableId, OpenMode.ForWrite);
BlockTableRecord modelsp = (BlockTableRecord)trans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
DBText stampText = new DBText();
stampText.TextString = stampString;
stampText.Height = 12;
stampText.HorizontalMode = TextHorizontalMode.TextRight;
stampText.Rotation = 0;
Point3d pIns = new Point3d(1070, 15, 0);
stampText.Position = pIns;
modelsp.AppendEntity(stampText);
trans.TransactionManager.AddNewlyCreatedDBObject(stampText, true);
trans.Commit();
}
tm.Dispose();
ThisDrawing.CloseAndSave(fullDwgPath);
thisDB.Dispose();
}
-
Here is the code that is working, we need to make sure the preview will be saved...
This is how I did it.
db.RetainOriginalThumbnailBitmap = true;
-
Just running past, no time to play ...
Luis, you may want to wrap the locdoc in a using statement so it behaves a little better
using (DocumentLock doclock = doc.LockDocument())
{
using (Transaction tr = doc.TransactionManager.StartTransaction())
{
// bla, bla
}
}
:added:
... or at least disposing it by adding :
docLock.Dispose();
-
Just running past, no time to play ...
Luis, you may want to wrap the locdoc in a using statement so it behaves a little better
using (DocumentLock doclock = doc.LockDocument())
{
using (Transaction tr = doc.TransactionManager.StartTransaction())
{
// bla, bla
}
}
Kerry;
That's scary.... I was about to implement that in this moment.... do you read minds?.... anyway, I think Mark has something that is working now :) - also, remember that Glenn mentioned that if it is wrap inside a using the transaction, there were no need of the lock doc?... or I am dreaming?
Thanks, Tim;
I have seen that statement but only before a SaveAs... no idea if it can be applied to CloseAndSave... care to test that anyone?
Cheers!
-
<snip>
no idea if it can be applied to CloseAndSave... care to test that anyone?
That is how I use it, before a SaveAs. I'm sick, and not well enough to think in C# right now or I would. Sorry Luis.
-
That's scary.... I was about to implement that in this moment.... do you read minds?....
Yes, but only the positive vibes, I filter out all the negative stuff ;-)
-
Kerry;
.... anyway, I think Mark has something that is working now :)...Cheers!
Not working.
I tried moving the procedure code out of my form class to regular class. No text.
:?
I think it might have something to do with where I'm calling the code from. In my case it's a modal dialog.
-
.... - also, remember that Glenn mentioned that if it is wrap inside a using the transaction, there were no need of the lock doc?... or I am dreaming? ...
That doesn't sound correct Luis
perhaps you mean it doesn't need disposing if it's wrapped in a using statement < As per my example >
-
Kerry;
.... anyway, I think Mark has something that is working now :)...Cheers!
Not working.
I tried moving the procedure code out of my form class to regular class. No text.
:?
I think it might have something to do with where I'm calling the code from. In my case it's a modal dialog.
Can you run the command as-is.... without seeing the other code, is not easy to make a full test.
-
.... - also, remember that Glenn mentioned that if it is wrap inside a using the transaction, there were no need of the lock doc?... or I am dreaming? ...
That doesn't sound correct Luis
perhaps you mean it doesn't need disposing if it's wrapped in a using statement < As per my example >
It's all right, was an old comment, and do not recall exactly (my age)... :)
-
............ and do not recall exactly (my age)... :)
Thats the excuse I use too ... it [ the excuse ] works most of the time :lol:
-
Kerry and Luis,
I did indeed say that you do in fact, as Kerry pointed out, wrap the locking of a document in a using ONLY if the command is being run in the DOCUMENT EXECUTION CONTEXT...if not, AutoCAD handles the locking implicitly for you and you don't need to lock (eg. modeless dialog you would need to lock).
Mark,
It sounds like you need to construct a new Database, then use Database.ReadDwg to read your dwg file into the newly created dbase, run your add text mojo on it, save it, then dispose of the dbase as you NEW'ed it in the first place. You should be able to do this from a modal dialog as well.
Note that the method I just described will do your mojo 'in memory' and you will not see the dwg in the editor. Make sure to add DataBase.RetainOriginalThumbnailBitmap = true to keep the thumbnail as Tim pointed out.
The problem with your original code is that DocumentManager.Open is ASYNCHRONOUS - which means the line of code to open the dwg will execute, but then the program will continue blissfully on, WITHOUT waiting for your dwg to finish opening.
Hope this helps.
Cheers from London,
Glenn.
-
Thanks Glenn,
The ASYNCHRONOUS hint helped me understand.
I went back to my orginal code with some minor modifications and things are working now.
Thanks everyone else who contributed.