Author Topic: How can I create the links on TypedValue of my Xrecord through the Fields?  (Read 3212 times)

0 Members and 1 Guest are viewing this topic.

Andrey Bushman

  • Swamp Rat
  • Posts: 864
I have read this article. How can I create the links on TypedValue of my Xrecord through the Fields?

kaefer

  • Guest
I have read this article. How can I create the links on TypedValue of my Xrecord through the Fields?

What is it with those links?

Quote
If you need to store some data related to particular objects in the drawing, consider using their Extension Dictionaries.


Andrey Bushman

  • Swamp Rat
  • Posts: 864
My English is bad. Perhaps I will show a code. Read comments in a code.
Code - C#: [Select]
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using cad = Autodesk.AutoCAD.ApplicationServices.Application;
  5. using AppSrv = Autodesk.AutoCAD.ApplicationServices;
  6. using DbSrv = Autodesk.AutoCAD.DatabaseServices;
  7. using EdInp = Autodesk.AutoCAD.EditorInput;
  8. using Geom = Autodesk.AutoCAD.Geometry;
  9. using Rtm = Autodesk.AutoCAD.Runtime;
  10.  
  11. [assembly:Rtm.CommandClass(typeof(AndreyBushman.CAD.Samples.FieldsSamples))]
  12.  
  13. namespace AndreyBushman.CAD.Samples
  14. {
  15.     public class FieldsSamples
  16.     {
  17.         const String ns = "bush";
  18.  
  19.         [Rtm.CommandMethod(ns, "cmd1", Rtm.CommandFlags.Modal)]
  20.         public void Cmd1() {
  21.             AppSrv.Document doc = cad.DocumentManager.MdiActiveDocument;
  22.             DbSrv.Database db = doc.Database;
  23.             EdInp.Editor ed = doc.Editor;
  24.  
  25.             using (DbSrv.Transaction tr = db.TransactionManager.StartTransaction()) {
  26.  
  27.                 DbSrv.DBDictionary dict = tr.GetObject(db.NamedObjectsDictionaryId, DbSrv.OpenMode.ForWrite)
  28.                     as DbSrv.DBDictionary;
  29.                 if (!dict.Contains(ns)) {
  30.                     DbSrv.Xrecord record = new DbSrv.Xrecord();
  31.                     record.Data = new DbSrv.ResultBuffer(new DbSrv.TypedValue((Int32) DbSrv.DxfCode.Text, "Hello World!"));
  32.                     dict.SetAt(ns, record);                    
  33.                     tr.AddNewlyCreatedDBObject(record, true);
  34.                    
  35.                     DbSrv.DBText text = new DbSrv.DBText();
  36.                     text.SetDatabaseDefaults();
  37.  
  38.                     // It not an exact code, but for an explanation (I don't know the right syntax for this case):
  39.                     // I need, the field must display the "Hello World!" message
  40.                     text.TextString = @"Field: %<\MyApplication NamedObjectsDictionary[bush][0]>%";
  41.                    
  42.                     DbSrv.BlockTableRecord btr = tr.GetObject(db.CurrentSpaceId, DbSrv.OpenMode.ForWrite)
  43.                         as DbSrv.BlockTableRecord;                  
  44.  
  45.                     btr.AppendEntity(text);
  46.                     tr.AddNewlyCreatedDBObject(text, true);
  47.                 }
  48.                 tr.Commit();
  49.             }
  50.         }
  51.     }
  52. }
  53.  

dgorsman

  • Water Moccasin
  • Posts: 2437
If I'm reading that right, you would like a field in a text (or similar) object to display the contents of an XRecord?  And the displayed value would update when the XRecord contents are updated?  Is that correct?
If you are going to fly by the seat of your pants, expect friction burns.

try {GreatPower;}
   catch (notResponsible)
      {NextTime(PlanAhead);}
   finally
      {MasterBasics;}

Andrey Bushman

  • Swamp Rat
  • Posts: 864
If I'm reading that right, you would like a field in a text (or similar) object to display the contents of an XRecord?  And the displayed value would update when the XRecord contents are updated?  Is that correct?
Yes

Jeff H

  • Needs a day job
  • Posts: 6150
That would be nice.


Once I messed around with overruling DBtext and Mtext where between a certain formatting the name of the entry in extension dictionary to display, or ### if empty, but nothing worth a poo.




I think Tony mentioned if you create your system or drawing variables you can display those in fields.

dgorsman

  • Water Moccasin
  • Posts: 2437
Thanks for the reminder - I keep forgetting the major changes done to the system variables implementation.  I have more than a few uses for those.  Just need to wait for the next office upgrade.
If you are going to fly by the seat of your pants, expect friction burns.

try {GreatPower;}
   catch (notResponsible)
      {NextTime(PlanAhead);}
   finally
      {MasterBasics;}

BlackBox

  • King Gator
  • Posts: 3770
If I'm reading that right, you would like a field in a text (or similar) object to display the contents of an XRecord?  And the displayed value would update when the XRecord contents are updated?  Is that correct?

Is it possible to register an ObjectModified Event for the XRecord, such that when the XRecord is changed, the Event handler updates the TextString for the 'linked' Text entity?  :? *not sure*

ETA - Re-reading your post, dgorsman, I am still not sure if the XRecord is for the Text Entity, or for another Object within the same Drawing. Forgive any confusion.
"How we think determines what we do, and what we do determines what we get."

Jeff H

  • Needs a day job
  • Posts: 6150
Would be a weird place to store them I guess but can also link fields to Custom properties of the Document


%<\AcVar CustomDP.CustomPropertyName>%

Chumplybum

  • Newt
  • Posts: 97
I looked at doing something similar quiet a while ago... you can create you're own field objects but only from ARX (from what i could tell) but i could never work out how to do via P/Invoke.

I ended up with a similar approach to Jeff H where i used an overrule that watched for particular coding. Once a match was found the overrule would then evaluate the 'text' within the codes and render the result. In my case the result was the return value of a .net function. The idea being that the one 'overrule field' could return the result of anything (ie. values from an external database, complex calculations, files, xdata, ... and not just properties of standard autocad objects).

Below is the code that i've been able to dig up that might help you decide to go down this path
Code: [Select]

Imports AADS = Autodesk.AutoCAD.DatabaseServices
Imports AAG = Autodesk.AutoCAD.Geometry
Imports AAGI = Autodesk.AutoCAD.GraphicsInterface

Imports System.Text.RegularExpressions

''' <summary>
'''
''' </summary>
''' <remarks></remarks>
''' <web>
''' http://stackoverflow.com/questions/608332/best-way-to-get-a-type-object-from-a-string-in-net
''' </web>
''' <todo>
''' 1. Errors for private methods and/or non shared methods
''' 2. MethodField
''' 3. ScriptField
''' 4. allow arguments
''' </todo>
Public Class MacroField_Overrule

    Inherits AAGI.DrawableOverrule

    Private Const MACROFIELD_REGEX As String = "(#<DotNetField\()(.*?)(\)>#)"
    Private Const MACROFIELD_BEGIN_CODE As String = "#<DotNetField("
    Private Const MACROFIELD_END_CODE As String = ")>#"


    Public Overloads Overrides Function WorldDraw(ByVal d As AAGI.Drawable, ByVal wd As AAGI.WorldDraw) As Boolean

        Dim CurrentText As AADS.DBText = DirectCast(d, AADS.DBText)

        Dim rx As Regex = New Regex(MACROFIELD_REGEX)

        If rx.IsMatch(CurrentText.TextString) = True Then

            Dim iStyle As New Autodesk.AutoCAD.GraphicsInterface.TextStyle()
            Dim styleId As AADS.ObjectId = CurrentText.TextStyleId

            Dim myEvaluator As MatchEvaluator = New MatchEvaluator(AddressOf MacroFieldEvaluator)

            If PInvoke.fromAcDbTextStyle(iStyle.UnmanagedObject, styleId) = Autodesk.AutoCAD.Runtime.ErrorStatus.OK Then
                Try
                    wd.Geometry.Text(CurrentText.Position, _
                                     CurrentText.Normal, _
                                     AAG.Vector3d.XAxis.RotateBy(CurrentText.Rotation, AAG.Vector3d.ZAxis), _
                                     Regex.Replace(CurrentText.TextString, MACROFIELD_REGEX, myEvaluator), _
                                     True, _
                                     iStyle)
                Catch ex As Exception
                    wd.Geometry.Text(CurrentText.Position, _
                                     CurrentText.Normal, _
                                     AAG.Vector3d.XAxis.RotateBy(CurrentText.Rotation, AAG.Vector3d.ZAxis), _
                                     Regex.Replace(CurrentText.TextString, MACROFIELD_REGEX, String.Format("{0}{1}{2}", "*", ex.Message, "*")), _
                                     True, _
                                    iStyle)
                End Try
            Else
                wd.Geometry.Text(CurrentText.Position, _
                                 CurrentText.Normal, _
                                 AAG.Vector3d.XAxis.RotateBy(CurrentText.Rotation, AAG.Vector3d.ZAxis), _
                                 Regex.Replace(CurrentText.TextString, MACROFIELD_REGEX, myEvaluator), _
                                 True, _
                                 New AAGI.TextStyle())
            End If

        Else
            MyBase.WorldDraw(d, wd)
        End If

        Return True

    End Function


    Private Function MacroFieldEvaluator(ByVal m As Match) As String

        Dim ClassMethod As String = m.Value.Replace(MACROFIELD_BEGIN_CODE, "").Replace(MACROFIELD_END_CODE, "")
        Dim FieldClassType As Type = FindType(ClassMethod.Substring(0, ClassMethod.LastIndexOf(".")))
        Dim FieldClass As Object = Activator.CreateInstance(FieldClassType)
        Dim FieldClassMethod As System.Reflection.MethodInfo = FieldClassType.GetMethod(ClassMethod.Substring(ClassMethod.LastIndexOf(".") + 1))

        'If ClassMethod.Contains("(*)") Then
        '    Dim ClassMethodName As String = ClassMethod.Substring(0, ClassMethod.IndexOf("("))
        '    'if "asdf" then string else number (regex)
        '    Dim ClassMethodArgs() As Object = ClassMethod.Substring(ClassMethod.IndexOf("(")).Replace("(", "").Replace(")", "").Split(",", options:=StringSplitOptions.RemoveEmptyEntries)
        '    Return FieldClassMethod.Invoke(FieldClass, Nothing)
        'Else
        Return FieldClassMethod.Invoke(FieldClass, Nothing)
        'End If

    End Function

    Private Function FindType(ByVal name As String) As Type

        Dim base As Type = Reflection.Assembly.GetExecutingAssembly.GetType(name, False, True)
        If base IsNot Nothing Then Return base

        For Each assembly As Reflection.Assembly In AppDomain.CurrentDomain.GetAssemblies
            base = assembly.GetType(name, False, True)
            If base IsNot Nothing Then Return base
        Next

        Throw New System.TypeLoadException(String.Format("Cannot find type '{0}'", name))

    End Function

End Class



hope this helps


cheers, Mark