btraemoore Posted May 14, 2013 Posted May 14, 2013 I'm trying to load a linetype into the active document so i can set a layers linetype to the one i'm trying to load. Now the problem is when i try to load it, autocad is giving me an exception of: eWasOpenForRead. so i tried to send it via the command line and it worked, BUT the application that im writing just ended... does anybody have any idea as to why this is happening? code: private void defaultLayerFix() { // Open a transaction for fixing layers that have the correct name // but not the correct color or linetype. using(curTrans = db.TransactionManager.StartOpenCloseTransaction()) { // Open the layerTable and lineType table for read. dwgLyrTbl = curTrans.GetObject( db.LayerTableId,OpenMode.ForRead) as LayerTable; acLinTbl = curTrans.GetObject( db.LinetypeTableId,OpenMode.ForRead) as LinetypeTable; // Check each layer against the standard layers DataSet. foreach (ObjectId layID in dwgLyrTbl) { LayerTableRecord curLayer = curTrans.GetObject( layID,OpenMode.ForRead) as LayerTableRecord; var layerFound = _LayerDataTable.Rows.Find(curLayer.Name.ToUpper()); if(layerFound != null){ // Upgrade the layerTable and LayerRecord for write. dwgLyrTbl.UpgradeOpen(); curLayer.UpgradeOpen(); // modify the color of the layer curLayer.Color = Autodesk.AutoCAD.Colors.Color.FromColorIndex( Autodesk.AutoCAD.Colors.ColorMethod.ByAci, (short)layerFound[2]); // I tried to put it in its own transaction in hopes that it would help.. but it didnt using(Transaction tempTrans = db.TransactionManager.StartOpenCloseTransaction()){ // if the layer is not loaded in the current dwg if(!acLinTbl.Has((string)layerFound[3])) try { db.LoadLineTypeFile((string)layerFound[3], "acad.lin"); } catch (Autodesk.AutoCAD.Runtime.Exception e) { Editor ed = acDoc.Editor; ed.WriteMessage(e.Message); } tempTrans.Commit(); } // Change current layer linetype to... curLayer.LinetypeObjectId = acLinTbl[(string)layerFound[3]]; // Downgrade the layerTable, lineTable and the LayerRecord for read. curLayer.DowngradeOpen(); dwgLyrTbl.DowngradeOpen(); // Remove the layer from the standards list // so we do not attempt to have redundant layers. for(int i = _LayerDataTable.Rows.Count-1; i >= 0; i--) { System.Data.DataRow dr = _LayerDataTable.Rows[i]; if (dr["NAME"] == layerFound[0]){ dr.Delete(); break; } } } else { // if the layer is not in within standard add it to a data set // to fix manually. if(curLayer.Name == "0") continue; var newRow = LayersToFix.NewRow(); newRow["NAME"] = curLayer.Name; // TODO get color name.. newRow["COLOR"] = curLayer.Color.ColorName; newRow["COLOR_ID"] = 0; LinetypeTableRecord Ltype = (LinetypeTableRecord)curTrans.GetObject( curLayer.LinetypeObjectId,OpenMode.ForRead ); newRow["LINETYPE"] = Ltype.Name; LayersToFix.Rows.Add(newRow); } } // accept the changes made in this transaction curTrans.Commit(); } } Quote
fixo Posted May 14, 2013 Posted May 14, 2013 On the quick glance if you've deleted row from datatable you have to end this action with AcceptChanges method right after that, also why StartOpenCloseTransaction? better yet to use StartTransaction I think I will be look at your code closely tomorrow, Cheers Quote
fixo Posted May 14, 2013 Posted May 14, 2013 One more about Lock Document http://adndevblog.typepad.com/autocad/2013/01/lock-a-document-preventing-others-from-modifying.html Quote
btraemoore Posted May 14, 2013 Author Posted May 14, 2013 I think i may have found something here, but im not sure. From what i think he is saying, you have to set a commandflag.session to be able to load/reload a layer synchronously. Im not really clear, forgive me. Quote
BlackBox Posted May 14, 2013 Posted May 14, 2013 I think i may have found something here, but im not sure. From what i think he is saying, you have to set a commandflag.session to be able to load/reload a layer synchronously. Im not really clear, forgive me. Perhaps I'm overlooking something... Why the need to invoke Command synchronously when there's an API available to load linetype? Quote
fixo Posted May 15, 2013 Posted May 15, 2013 Here is an excerpt from my form Pay attention how you could to use color and linetype, all within top transaction, no temporary transaction is needed private void btnUsed_Click(object sender, EventArgs e) { List<string> used = GetUsedLayers(); this.listBox1.DataSource = used;// populate listBox to show used layers } public List<string> GetUsedLayers() { List<string> used = new List<string>(); Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; using (Transaction tr = db.TransactionManager.StartTransaction()) { LayerTable lt = tr.GetObject( db.LayerTableId, OpenMode.ForRead ) as LayerTable; lt.GenerateUsageData(); foreach (ObjectId oid in lt) { LayerTableRecord ltr = tr.GetObject (oid, OpenMode.ForRead ) as LayerTableRecord; if (ltr.IsUsed == true) { used.Add(ltr.Name); } } return used; } } public void CreateLayer(string layerName, string ltpname, params short[] color) { ObjectId layerId; ObjectId ltrid = ObjectId.Null; Database db = HostApplicationServices.WorkingDatabase; using (Transaction tr = db.TransactionManager.StartTransaction()) { LayerTable lt = (LayerTable)tr.GetObject(db.LayerTableId, OpenMode.ForRead); if (lt.Has(layerName)) { layerId = lt[layerName]; } else { LayerTableRecord ltr = new LayerTableRecord(); ltr.Name = layerName; if (color.Length == 1) { ltr.Color = Autodesk.AutoCAD.Colors.Color.FromColorIndex(ColorMethod.ByAci, color[0]); // return; } else { if (color.Length == 3) { byte red = Convert.ToByte(color[0]); byte green = Convert.ToByte(color[1]); byte blue = Convert.ToByte(color[2]); ltr.Color = Autodesk.AutoCAD.Colors.Color.FromRgb(red, green, blue); } else return; } LinetypeTable ltt = tr.GetObject(db.LinetypeTableId, OpenMode.ForRead) as LinetypeTable; if (ltt.Has(ltpname)) { ltrid = ltt[ltpname]; ltt.UpgradeOpen(); ltr.LinetypeObjectId = ltrid; } else { LoadLineType(ltpname); LinetypeTableRecord lttr = tr.GetObject(ltt[ltpname], OpenMode.ForRead, false) as LinetypeTableRecord; ltr.LinetypeObjectId = ltt[ltpname]; } lt.UpgradeOpen(); layerId = lt.Add(ltr); tr.AddNewlyCreatedDBObject(ltr, true); db.Clayer = layerId;// set layer current, optional, may remove this line } tr.Commit(); } } // without check MEASUREINIT system variable // public void LoadLineType(string ltname) { Database db = HostApplicationServices.WorkingDatabase; using (Transaction tr = db.TransactionManager.StartTransaction()) { LinetypeTable tbl = (LinetypeTable)tr.GetObject(db.LinetypeTableId, OpenMode.ForRead); if (!tbl.Has(ltname)) { db.LoadLineTypeFile(ltname, "acad.lin");// imperic } tr.Commit(); } } privatevoid btnCreate_Click(object sender, EventArgs e) { string layerName = this.txtGrid.Text;// text box for input layer name // this.Hide(); CreateLayer(layerName+"1", "Phantom2", 64,128,64); CreateLayer(layerName+"2", "Center", 107, 62, 132);// arguments are 3 digits fo RGB or single one for colorindex CreateLayer(layerName+"3", "Hidden", 1); // this.Show(); } Quote
btraemoore Posted May 15, 2013 Author Posted May 15, 2013 @BlackBox you were not overlooking anything, i know there is a perfectly good API for this i just couldn't figure out why it was not working... My assumption was because of the transaction placement. I still don't know exactly why it was not working but, i did get it functioning after some rewriting.. @Fixo thank you for your implementation of this, I do however want several sub-transactions so that it can be undone in steps. (if im even correct on my assumption that the undo feature ties in with transactions) if not, then i will consider changing it for simplicity sake. I've only been writing in C# for about a week, I still have a lot to learn. code: private void defaultLayerFix (){ using(var DLFTrans = db.TransactionManager.StartTransaction()){ // Open the layerTable table for read. dwgLyrTbl = DLFTrans.GetObject( db.LayerTableId,OpenMode.ForRead) as LayerTable; // Foreach layer in current DWG foreach (ObjectId layID in dwgLyrTbl) { var curLayer = DLFTrans.GetObject( layID,OpenMode.ForRead) as LayerTableRecord; FixLayer(curLayer); } DLFTrans.Commit(); } } private void FixLayer(LayerTableRecord curLayer){ // Open a transaction for fixing layers that have the correct name // but not the correct color or linetype. using(curTrans = db.TransactionManager.StartTransaction()) { // Check Standard layer data table for current layer var layerFound = _LayerDataTable.Rows.Find(curLayer.Name.ToUpper()); // If found if(layerFound != null) { // Open the Line Type table for read acLinTbl = curTrans.GetObject( db.LinetypeTableId,OpenMode.ForRead) as LinetypeTable; // Send to load. LoadLinetype((string)layerFound[3]); // If linetype table has the needed linetype. if (acLinTbl.Has((string)layerFound[3])){ // Upgrade the current layer for Write. curLayer.UpgradeOpen(); // Change the layers Linetype. curLayer.LinetypeObjectId = acLinTbl[(string)layerFound[3]]; // Change the layers color. curLayer.Color = Autodesk.AutoCAD.Colors.Color.FromColorIndex( Autodesk.AutoCAD.Colors.ColorMethod.ByAci, (short)layerFound[2]); // Downgrade the layer from write to read. curLayer.DowngradeOpen(); // Remove the layer from the Standard Layers Dataset within current dwg. for(int i = _LayerDataTable.Rows.Count-1; i >= 0; i--) { var dr = _LayerDataTable.Rows[i]; if (dr["NAME"] == layerFound[0]){ dr.Delete(); break; } } } else { MessageBox.Show("awe ****, still not working"); } } else { // If the layer is not in within standard add it to a data set // to fix manually. if(curLayer.Name != "0") { // Create a new row in dataset var newRow = LayersToFix.NewRow(); newRow["NAME"] = curLayer.Name; // TODO get color name.. newRow["COLOR"] = curLayer.Color.ColorName; newRow["COLOR_ID"] = 0; var Ltype = (LinetypeTableRecord)curTrans.GetObject( curLayer.LinetypeObjectId,OpenMode.ForRead ); newRow["LINETYPE"] = Ltype.Name; // Add the new row to the dataset. LayersToFix.Rows.Add(newRow); } } // Accept changes and dispose of the transacton curTrans.Commit(); } } private void LoadLinetype(string ltName) { // Start a transaction using (var acTrans = db.TransactionManager.StartTransaction()) { // Open the Linetype table for read var acLineTypTbl = acTrans.GetObject(db.LinetypeTableId, OpenMode.ForRead) as LinetypeTable; // If the linetype does not exist if (!acLineTypTbl.Has(ltName)) { // Load the Center Linetype db.LoadLineTypeFile(ltName, "acad.lin"); } // Save the changes and dispose of the transaction acTrans.Commit(); } } Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.