Hi.
I have a program to read standard (line, mtext, etc) coordinates.
But, I need to read custom properties added to objects (I can see with right button, properties).
What is the method?
I'm writing a module in c#.
My code:
Database db=HostApplicationServices.WorkingDatabase;
Transaction tr=db.TransactionManager.StartTransaction();
BlockTable bt=(BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
BlockTableRecord btr=(BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead);
foreach(ObjectId idobj in btr)
{
ed.WriteMessage(idobj.ObjectClass.DxfName);
if(idobj.ObjectClass.DxfName.CompareTo("LINE")==0)
{
Line e=tr.GetObject(idobj, OpenMode.ForRead, false) as Line;
ed.WriteMessage(e.StartPoint+" "+e.EndPoint); // coordinates
}
}
You can see a printscreen with information of custom properties (title "Personalizado" and values "diamertro", "material", "espesor")
Solved! Go to Solution.
Solved by ActivistInvestor. Go to Solution.
It depends on what kind of "custom properties" you are talking about. For plain AutoCAD, a standard AutoCAD entity could be extend to have some kind of "custom properties" by using XData or ExtentionDisctionary, for example. You can use AutoCAD .NET API to access these kind of "properties",
For AutoCAD vertical products (AutoCAD Map/Civil/MEP...), custom properties could be added to either standard AutoCAD entities, or Vertical products' custom entities. Basically, you need Vertical product-specific APIs (that only comes with the vertical product) to access them, well, only if the APIs support doing it.
So, you need to know what exactly the "custom properties" are from (plain AutoCAD, vertical products, or even third party add-ins...). From the picture you attached, (sorry, I do not know what language is shown in the picture), it seems you are using AutoCAD MAP, and the custom properties you are referring to look like ObjectData (or ObjectClass?). If that is the case, you need to use AutoCAD Map ObjectARX .NET API to access it. You can download AutoCAD Map ObjectARX SDK and learn how to access AutoAD Map specific data from the sample code coming with the SDK.
Also, AutoCAD Map also has COM API available (not as powerful as its .NET API).
Norman Yuan
...... I did download the objectarx 2016, ...
When you say objectarx 2016, probably, you mean AutoCAD ObjectARX SDK, which is only for PLAIN AutoCAD. To work with AutoCAD Map specific data (ObjectData/ObjectClass/..., there is AutoCAD Map ObjectARX SDK. You do not have to download to work with AutoCAD Map .NET API technically. All you need to do is to set reference of your project to ManagedMapApi.dll (found in [AutoCAD installation\\Map folder (make sure you set "Copy Local" to False).
However, if the custom properties you are after are from Map objects (created by connecting to FDO data source), then things are a lot more complicated, because these Map objects are not native AutoCAD entities. You then need to learn another set of .NET API - AutoCAD Map geospatial platform API. Hopefully, you are only interested in ObjectData/ObjectClass, thus the learning curve would be not as steep.
Norman Yuan
ObjectData and ObjectClass (Object Classification) are different things. The latter was introduced into AutoCAD Map well later than ObjectData, and originally called Feature Class/Classification. It is not widely used as ObjectData.
You need to look at the code samples "ClassifactionCS/VB", if you indeed know the data you are after in ObjectClass data.
Before you write code to manipulate Object Class data, I strongly recommend you get familiar to it by manually create Object class definition, classifying and declassifying AutoCAD entities in AutoCAD Map as AutoCAD Map user
Norman Yuan
The example code below will display the properties shown in the Properties palette for a selected object:
using System; using System.Collections.Generic; using System.Runtime.InteropServices; using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.Internal.PropertyInspector; using Autodesk.AutoCAD.Runtime; namespace Namespace1 { public static class OPMPropsExample { /// Example: Dumps the OPM properties of a selected object to the console: [CommandMethod("OPMPROPS")] public static void ListOpmProps() { Document doc = Application.DocumentManager.MdiActiveDocument; Editor ed = doc.Editor; var psr = ed.GetEntity("\nSelect object: "); if(psr.Status != PromptStatus.OK) return; var props = GetOPMProperties(psr.ObjectId); if(props.Count == 0) { ed.WriteMessage("\nNo properties found."); return; } ed.WriteMessage("\n\n"); foreach(var pair in props) { ed.WriteMessage("\n {0} = {1}", pair.Key, pair.Value); if(Marshal.IsComObject(pair.Value)) Marshal.ReleaseComObject(pair.Value); } } /// Gets the names and values of OPM properties for the given object public static IDictionary<string, object> GetOPMProperties(ObjectId id) { Dictionary<string, object> map = new Dictionary<string, object>(); IntPtr pUnk = ObjectPropertyManagerPropertyUtility.GetIUnknownFromObjectId(id); if(pUnk != IntPtr.Zero) { using(CollectionVector properties = ObjectPropertyManagerProperties.GetProperties(id, false, false)) { int cnt = properties.Count(); if(cnt != 0) { using(CategoryCollectable category = properties.Item(0) as CategoryCollectable) { CollectionVector props = category.Properties; int propCount = props.Count(); for(int j = 0; j < propCount; j++) { using(PropertyCollectable prop = props.Item(j) as PropertyCollectable) { if(prop == null) continue; object value = null; if(prop.GetValue(pUnk, ref value) && value != null) { if(!map.ContainsKey(prop.Name)) map[prop.Name] = value; } } } } } } Marshal.Release(pUnk); } return map; } } }
Hello AI(short for Activist Investor),
Youre sample of OPM is returning a value of "Com Object" for Color and Hyperlink.
I could get the proper values directly from the ObjectId,
but what would be the more generic way of returning the underlying values for those Com Objects.
I would rather like to convert based on if (value=="Com Object")... instead of if (name=="COLOR")...
See sample below.
For the Color Value i used a dynamic to get the Color value, but this approach failed for the Hyperlink
The Albert(AutoCAD Team) mentioned using the FromAcadObject methode to get properties of "COM object" for ".net object" and the other way around in : http://through-the-interface.typepad.com/through_the_interface/2007/02/using_the_com_i.html
Attached is the full source, a littlebit changed version of your sample of OPM
... if (prop.GetValue(pUnk, ref value)) //&& value != null) { //Color and Hyperlink Values are returned as Com Object if (propName.Equals("COLOR", StringComparison.OrdinalIgnoreCase)) { //var x1 = DBObject.FromAcadObject(prop); dynamic propDisp = prop.DISP; value = propDisp.Color; var colorName = ColorNames.BYLAYER; if (Enum.TryParse<ColorNames>(value.ToString(), out colorName)) { value = colorName; } } else if (propName.Equals("HYPERLINK", StringComparison.OrdinalIgnoreCase)) { //var x1 = DBObject.FromAcadObject(prop); dynamic propDisp = prop.DISP; //value = ???; } map[$"{catName}.{propName}"] = value; } ...
I'm afraid there's no more 'generic' way to convert COM objects to managed counterparts, other than for DBObjects.
The main purpose of reading OPM properties is as a quick/dirty way to access data that is either difficult or impossible to access via other means, so unless you're trying to reinvent the properties palette, for those things that are easily available through the managed API, that going to be the easiest way to use that data.
@SENL1362 wrote:Hello AI(short for Activist Investor),
Youre sample of OPM is returning a value of "Com Object" for Color and Hyperlink.
I could get the proper values directly from the ObjectId,
but what would be the more generic way of returning the underlying values for those Com Objects.
I would rather like to convert based on if (value=="Com Object")... instead of if (name=="COLOR")...
See sample below.
For the Color Value i used a dynamic to get the Color value, but this approach failed for the Hyperlink
The Albert(AutoCAD Team) mentioned using the FromAcadObject methode to get properties of "COM object" for ".net object" and the other way around in : http://through-the-interface.typepad.com/through_the_interface/2007/02/using_the_com_i.html
Attached is the full source, a littlebit changed version of your sample of OPM
... if (prop.GetValue(pUnk, ref value)) //&& value != null) { //Color and Hyperlink Values are returned as Com Object if (propName.Equals("COLOR", StringComparison.OrdinalIgnoreCase)) { //var x1 = DBObject.FromAcadObject(prop); dynamic propDisp = prop.DISP; value = propDisp.Color; var colorName = ColorNames.BYLAYER; if (Enum.TryParse<ColorNames>(value.ToString(), out colorName)) { value = colorName; } } else if (propName.Equals("HYPERLINK", StringComparison.OrdinalIgnoreCase)) { //var x1 = DBObject.FromAcadObject(prop); dynamic propDisp = prop.DISP; //value = ???; } map[$"{catName}.{propName}"] = value; } ...
ok, thank you for your thoughts.
It was merely a question of interest and to learn about the more advanced subjects than as you stated "reinventing the properties palette".
In this case the missing information is easily available.
Again thanks.
Thanks to all.
I did try the solution, and works ok.
I'm trying to do a "saveas" from current dwg to wfs read/write service (I can't use the connection wfs, because is read only).
A difference of a connection to a database, which requires permissions on base tables, a wfs connection (in my case geoserver, authenticating users by ldap / ad) is much better.
But, for that, it has to obtain the list of graphic elements, but also the list of alphanumeric elements informed by the operator for the object.
For this last, I spent almost two weeks consulting a lot of specialists, and finally, you gave me the solution.
I'm going to try a little more, but I think I can convert all the objects in the model space.
TIA
Thanks so much for sharing this code. It helped me a lot.
I was wondering how can I change the value of the custom property of a dynamic block?
The AutoCAD managed API provides a way to manipulate Dynamic block properties without the need to use the OPM API. You can find plenty of examples for manipulating Dynamic block properties by searching this forum.
@Anonymous wrote:
Thanks so much for sharing this code. It helped me a lot.
I was wondering how can I change the value of the custom property of a dynamic block?
Hi,
Your cade seems a solution to a problem I have.
I could not implement it because I did not understand what ColorNames is. I could not find it in the API.
Can you please help?
Best Regards.
Modar Mayya
Hi ActivistInvestor,
Thanks for the code. It helped me at right time.
Can you please point me to some place where I can list required properties from multiple selected objects and write to xls!!!
Thanks in anticipation,
Samir.
Can't find what you're looking for? Ask the community or share your knowledge.