TheSwamp
Code Red => .NET => Topic started by: DaveW on March 19, 2007, 06:27:47 PM
-
I have been looking at the labs for 2 days and have a few things working, but I must say the lack of practical examples in the ACAD help is really making this difficult. I am not a programmer by trade and there is still a whole world in VB6 I still do not understand. I have been able to code quite a bit by using other source code as an example and modifying it as needed.
After an hour or so I finally had it working in design time by loading the dll in the bin folder and setting the 2 dlls res in the ACAD dir to false. About an hour or so later I had the active document. After that it has been a stand still. I have tried a bunch of example code snippets and can never seem to get where I want.
In vb6 if I wanted to parse through every entity in modelspace I would:
Dim ent as acadentity
Dim thisdrawing as acaddocument
Set thsidrawing as acadactivedocument
for each ent in thissdrawing.modlespace
If ent.objectname = "AcDb3dSolid then
msgbox "I have a solid"
next
In vb.net I have gotten modelspace though the db, blah blah, from example code, but how to iterate through and look for what I want, I have no idea. I have even passed out the ids of the objects selected to a message box, but still cannot find a objectfromobjectid or objectfromhandleid method.
This is just one of about100 typical things that I would expect to have available in the help file.
Instead, it points you to the password protected ADN site of which I refuse to enroll in due to the nature of the licence agreement. The cost is not an issue at all.
Is anyone here game for creating a library of functions and methods for public use?
I am thinking about taking a day or two and creating 50 or so typical VB6 pieces of code that do things like set an object color, layer, linetype, etc., add layers, get the coords of pline, work with multiple documents and on and on and then sending it off to a programming company, each as its own project not to load down too much in each area, and have them convert it to vb.net.
What do you guys think?
-
Have you looked at the Transaction class yet? Database access in .NET is basically controlled there.
I've mostly been working in C#.NET so far, and with Civil-3D, but you can try checking out what I've done here (http://www.ejsurveying.com/sincpacc3d.htm). VB.NET and C#.NET are close enough that just looking at this code might give you lots of ideas, even if you don't have Civil-3D and can't actually run any of my code.
-
Here is what was posted by Kerry to help me out. It's C#, but I think it can help you.
// Posted by Kerry Brown
[CommandMethod("PrintMSpacev02")]
public static void MyPrintMspace_1()
{
Database db = HostApplicationServices.WorkingDatabase;
Editor ed = AcadApp.DocumentManager.MdiActiveDocument.Editor;
using (Transaction trans = db.TransactionManager.StartTransaction())
{
BlockTable bt = (BlockTable)(trans.GetObject(db.BlockTableId, OpenMode.ForRead));
foreach (ObjectId ObjId in
(BlockTableRecord)trans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead))
{
Entity Ent = (Entity)trans.GetObject(ObjId, OpenMode.ForRead, true);
ed.WriteMessage("\n Layer: " + Ent.Layer);
}
}
}
-
This may be indicative ..
[CommandMethod("test103")]
static public void test()
{
Database db = HostApplicationServices.WorkingDatabase;
Editor ed = AcadApp.DocumentManager.MdiActiveDocument.Editor;
using (Transaction trans = db.TransactionManager.StartTransaction())
{
BlockTable bt = (BlockTable)(trans.GetObject(db.BlockTableId, OpenMode.ForRead));
foreach (ObjectId ObjId in
(BlockTableRecord)trans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead))
{
Entity Ent = (Entity)trans.GetObject(ObjId, OpenMode.ForRead, true);
ed.WriteMessage(string.Format(
"\n Layer: {0} \tObjectType: {1} \tHandle: {2}",
Ent.Layer,
Ent.GetType().Name,
Ent.Handle ));
}
}
}
added:
and the piccy for example output ..
-
Here is what was posted by Kerry to help me out. It's C#, but I think it can help you.
I think so and thanks to KWB :)
Here is VB.NET version translated from
example above
Imports System
Imports Autodesk.AutoCAD.Runtime
Imports Autodesk.AutoCAD.Geometry
Imports Autodesk.AutoCAD.EditorInput
Imports Autodesk.AutoCAD.DatabaseServices
Imports acApp = Autodesk.AutoCAD.ApplicationServices.Application
Namespace Properties
Public Class EntProps
<CommandMethod("ShowLays", CommandFlags.Modal Or CommandFlags.Session)> _
Public Shared Sub PrintLayers()
Dim db As Database = HostApplicationServices.WorkingDatabase
Dim ed As Editor = acApp.DocumentManager.MdiActiveDocument.Editor
Using trans As Transaction = db.TransactionManager.StartTransaction()
Dim bt As BlockTable = CType(trans.GetObject(db.BlockTableId, OpenMode.ForRead), BlockTable)
Dim btr As BlockTableRecord = (CType(trans.GetObject(db.CurrentSpaceId, OpenMode.ForRead), BlockTableRecord))
For Each ObjId As ObjectId In btr
Dim Ent As Entity = CType(trans.GetObject(ObjId, OpenMode.ForRead, True), Entity)
ed.WriteMessage(vbCrLf & " Layer: " & Ent.Layer)
Next
End Using
End Sub
End Class
End Namespace
~'J'~
-
and from the more explicit example
Public Class kdubTest103
'
' TODO: Add constructor logic here
'
Public Sub New()
End Sub
<CommandMethod("test103")> _
Public Shared Sub test()
Dim db As Database = HostApplicationServices.WorkingDatabase
Dim ed As Editor = AcadApp.DocumentManager.MdiActiveDocument.Editor
Using trans As Transaction = db.TransactionManager.StartTransaction()
Dim bt As BlockTable = DirectCast((trans.GetObject(db.BlockTableId, OpenMode.ForRead)), BlockTable)
For Each ObjId As ObjectId In DirectCast(trans.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForRead), BlockTableRecord)
Dim Ent As Entity = DirectCast(trans.GetObject(ObjId, OpenMode.ForRead, True), Entity)
ed.WriteMessage(String.Format("" & Chr(10) & " Layer: {0} " & Chr(9) & "ObjectType: {1} " & Chr(9) & "Handle: {2}", Ent.Layer, Ent.[GetType]().Name, Ent.Handle))
Next
End Using
End Sub
End Class
added:
I get the burps when I use VB. This was translated using SharpDevelop 2.1 .. There are a few things that are not conventional to ACAD .. DirectCast for example
perhaps someone should tart-up the code.
-
Kerry - VB...shame on you :evil:
-
Sorry Glenn
I'm just a masochist I guess ..
[*slinks away*]
-
Here is another example from masochist too :)
Select then rotate entity
Imports System
Imports System.Collections
Imports Autodesk.AutoCAD.Runtime
Imports Autodesk.AutoCAD.Geometry
Imports Autodesk.AutoCAD.EditorInput
Imports Autodesk.AutoCAD.DatabaseServices
Imports graph = Autodesk.AutoCAD.GraphicsInterface
Imports acApp = Autodesk.AutoCAD.ApplicationServices.Application
'//<--->
Public Class EntityRot
<CommandMethod("ROE", CommandFlags.Modal Or
CommandFlags.Session)> _
Public Sub RotEnt()
Dim ed As Editor = acApp.DocumentManager.MdiActiveDocument.Editor
Dim db As Database =
acApp.DocumentManager.MdiActiveDocument.Database
Dim tr As Transaction = db.TransactionManager.StartTransaction()
Try
'// select object
Dim selOpts As New PromptSelectionOptions()
Dim res As PromptSelectionResult
selOpts.SingleOnly = True
selOpts.MessageForAdding = " Select an entity"
res = ed.GetSelection(selOpts)
If res.Status <> PromptStatus.OK Then Return
Dim id As ObjectId = res.Value.GetObjectIds(0)
Dim ent As Entity = tr.GetObject(id, OpenMode.ForWrite, False)
'// get point
Dim orig As Point3d
Dim ptRes As PromptPointResult
ptRes = ed.GetPoint(" Specify base point")
If ptRes.Status <> PromptStatus.OK Then Return
orig = ptRes.Value
'// get angle
Dim ang As Double
Dim angOPts As PromptAngleOptions = New PromptAngleOptions("
Specify rotation angle or pick a second point: ")
'// add another options to prompt
angOPts.AllowNone = False
angOPts.AllowZero = False
angOPts.UseBasePoint = True
angOPts.BasePoint = orig
'// get result
Dim angRes As PromptDoubleResult = ed.GetAngle(angOPts)
If angRes.Status <> PromptStatus.OK Then Return
ang = angRes.Value
'// rotate entity by using transformation matrix
Dim v3d As Vector3d =
ed.CurrentUserCoordinateSystem.CoordinateSystem3d.Zaxis
Dim m3d As Matrix3d = Matrix3d.Rotation(ang, v3d, orig)
ent.TransformBy(m3d)
tr.Commit()
Catch ex As Autodesk.AutoCAD.Runtime.Exception
tr.Abort()
MsgBox(ex.Message)
Finally
tr.Dispose()
End Try
End Sub
End Class
~'J'~
-
Sample to iterate a SymbolTable. Thanks to T.T. for the original idea - although I added the SymbolTableEnumerator. It's in c++ but just ignore all the funny symbols and you have c# - then add a few more funny symbols and you have VB...~) : Update - removed 'doc' from 'HasName' arguments in Tests...oops)
static void
Tests()
{
Document ^ doc = GetActiveDoc();
Database ^ db = doc->Database;
Editor ^ ed = doc->Editor;
String ^ recordName = "foo";
ed->WriteMessage
(HasName(db->BlockTableId, recordName).ToString() + "\n");
ed->WriteMessage
(HasName(db->LayerTableId, recordName).ToString() + "\n");
}
static bool
HasName(ObjectId ^ symbolTableId, String ^ recName)
{
Document ^ doc = GetActiveDoc();
Database ^ db = doc->Database;
Editor ^ ed = doc->Editor;
SymbolTableRecord ^ str;
Transaction ^ tr =
db->TransactionManager->StartTransaction();
try
{
SymbolTable ^ st =
(SymbolTable^)tr->GetObject(*symbolTableId, OpenMode::ForRead);
SymbolTableEnumerator ^ ste = st->GetEnumerator();
while (ste->MoveNext())
{
str = (SymbolTableRecord^)ste->Current.GetObject(OpenMode::ForRead);
if (str->Name == recName)
return true;
}
}
finally
{
delete tr;
}
return false;
}
static Document ^
GetActiveDoc()
{
Document ^ doc =
Application::DocumentManager->MdiActiveDocument;
return doc;
}
EDIT: Tony Tanzillo recommends against using SymbolTableEnumerator as I have here. Use For Each instead! Teach me to modify his code...:)
-
Thanks guys. Great stuff. I see I had the ID's, but
For Each ObjId As ObjectId In btr
Dim Ent As Entity = CType(trans.GetObject(ObjId, OpenMode.ForRead, True), Entity)
was the way to go. I would have never figured that out!
There is one small step. Once I have something to share for beginners like me I will post some too.
Needlessto say I will never catch you guys.
Thanks again,
Dave
-
Sample to iterate a SymbolTable. Thanks to T.T. for the original idea - although I added the SymbolTableEnumerator. It's in c++ but just ignore all the funny symbols and you have c# - then add a few more funny symbols and you have VB...~) : Update - removed 'doc' from 'HasName' arguments in Tests...oops)
Dear Paul,
I couldn't to convert your example on VB.NET,
because of my browser not found SymbolTable name
Can you upload here a VB.NET (or on C#),version?
Thanks in advance,
Regards,
Oleg :|
~'J'~
-
Sample to iterate a SymbolTable. Thanks to T.T. for the original idea - although I added the SymbolTableEnumerator. It's in c++ but just ignore all the funny symbols and you have c# - then add a few more funny symbols and you have VB...~) : Update - removed 'doc' from 'HasName' arguments in Tests...oops)
Dear Paul,
I couldn't to convert your example on VB.NET,
because of my browser not found SymbolTable name
Can you upload here a VB.NET (or on C#),version?
Thanks in advance,
Regards,
Oleg :|
~'J'~
Here is the link to Tony's original post in c#... Not sure why you don't have a SymbolTable datatype - I assume you've referenced 'acdbmgd.dll' - What version of AutoCAD are you using?
http://discussion.autodesk.com/thread.jspa?messageID=5437715
-
Here is the link to Tony's original post in c#... Not sure why you don't have a SymbolTable datatype - I assume you've referenced 'acdbmgd.dll' - What version of AutoCAD are you using?
http://discussion.autodesk.com/thread.jspa?messageID=5437715
Here is complete code
Well, the debugger have not found any error
there, but this is not working for now... :(
Imports System
Imports System.Collections
Imports Autodesk.AutoCAD.Runtime
Imports Autodesk.AutoCAD.Geometry
Imports Autodesk.AutoCAD.EditorInput
Imports Autodesk.AutoCAD.DatabaseServices
Imports graph = Autodesk.AutoCAD.GraphicsInterface
Imports Autodesk.AutoCAD.ApplicationServices
Imports acApp = Autodesk.AutoCAD.ApplicationServices.Application
Namespace WorkSpace
Public Class InfoDoc
'//not working for now
<CommandMethod("DwgCont", CommandFlags.Modal Or CommandFlags.Session)> _
Public Sub Tests()
Dim doc As Document = GetActiveDoc()
Dim db As Database = doc.Database
Dim ed As Editor = doc.Editor
Dim recordName As String = "foo"
ed.WriteMessage _
(HasName(doc.Database.BlockTableId, recordName).ToString() & vbNewLine)
ed.WriteMessage _
(HasName(doc.Database.LayerTableId, recordName).ToString() & vbNewLine)
End Sub
Public Function HasName(ByVal symbolTableId As ObjectId, ByVal recName As String) As Boolean
Dim doc As Document = GetActiveDoc()
Dim db As Database = doc.Database
Dim ed As Editor = doc.Editor
Dim str As SymbolTableRecord
Dim tr As Transaction = _
db.TransactionManager.StartTransaction()
Try
Dim st As SymbolTable = CType(tr.GetObject(symbolTableId, OpenMode.ForRead, False), SymbolTable)
Dim ste As SymbolTableEnumerator = st.GetEnumerator()
While ste.MoveNext()
str = CType(ste.Current.GetObject(OpenMode.ForRead, False), SymbolTableRecord)
If str.Name = recName Then
Return True
End If
End While
Finally
tr.Dispose()
End Try
Return False
End Function
Public Function GetActiveDoc() As Document
Dim doc As Autodesk.AutoCAD.ApplicationServices.Document = _
Application.DocumentManager.MdiActiveDocument()
Return doc
End Function
End Class
End Namespace
~'J'~
-
Here is the link to Tony's original post in c#... Not sure why you don't have a SymbolTable datatype - I assume you've referenced 'acdbmgd.dll' - What version of AutoCAD are you using?
http://discussion.autodesk.com/thread.jspa?messageID=5437715
Here is complete code
Well, the debugger have not found any error
there, but this is not working for now... :(
Imports System
Imports System.Collections
Imports Autodesk.AutoCAD.Runtime
Imports Autodesk.AutoCAD.Geometry
Imports Autodesk.AutoCAD.EditorInput
Imports Autodesk.AutoCAD.DatabaseServices
Imports graph = Autodesk.AutoCAD.GraphicsInterface
Imports Autodesk.AutoCAD.ApplicationServices
Imports acApp = Autodesk.AutoCAD.ApplicationServices.Application
Namespace WorkSpace
Public Class InfoDoc
'//not working for now
<CommandMethod("DwgCont", CommandFlags.Modal Or CommandFlags.Session)> _
Public Sub Tests()
Dim doc As Document = GetActiveDoc()
Dim db As Database = doc.Database
Dim ed As Editor = doc.Editor
Dim recordName As String = "foo"
ed.WriteMessage _
(HasName(doc.Database.BlockTableId, recordName).ToString() & vbNewLine)
ed.WriteMessage _
(HasName(doc.Database.LayerTableId, recordName).ToString() & vbNewLine)
End Sub
Public Function HasName(ByVal symbolTableId As ObjectId, ByVal recName As String) As Boolean
Dim doc As Document = GetActiveDoc()
Dim db As Database = doc.Database
Dim ed As Editor = doc.Editor
Dim str As SymbolTableRecord
Dim tr As Transaction = _
db.TransactionManager.StartTransaction()
Try
Dim st As SymbolTable = CType(tr.GetObject(symbolTableId, OpenMode.ForRead, False), SymbolTable)
Dim ste As SymbolTableEnumerator = st.GetEnumerator()
While ste.MoveNext()
str = CType(ste.Current.GetObject(OpenMode.ForRead, False), SymbolTableRecord)
If str.Name = recName Then
Return True
End If
End While
Finally
tr.Dispose()
End Try
Return False
End Function
Public Function GetActiveDoc() As Document
Dim doc As Autodesk.AutoCAD.ApplicationServices.Document = _
Application.DocumentManager.MdiActiveDocument()
Return doc
End Function
End Class
End Namespace
~'J'~
How about "And" instead of "Or"
CommandFlags.Session And CommandFlags.Modal
-
That would a trick! Thanks a ton Paul! :-)
It works like a charm now
Regards,
Oleg
~'J'~
-
That would a trick! Thanks a ton Paul! :-)
It works like a charm now
Regards,
Oleg
~'J'~
Cool! In C#/VB you can wrap the Transaction in Using block instead of the try catch. Might want to try it...
Update:
I see you've used 'using' in your posts...
-
:-)
Thank you Fatty
Help me solve about this Problem