Text Height Update In C Sharp

Text Height Update In C Sharp

muckmailer
Collaborator Collaborator
4,143 Views
45 Replies
Message 1 of 46

Text Height Update In C Sharp

muckmailer
Collaborator
Collaborator

The following Lisp route will update text by style. Can this be done in C sharp?

 

I am looking for a c sharp routine that would have an select all so I can make changes to all text in the drawing.

 

 

;;  TextHeightUpdate.lsp [command name: THU]
;;  To Update the Height of Text and Mtext in Styles with defined heights,
;;    when height has been changed in Style definition.  Checks Style of all
;;    selected Text/Mtext, and it has a defined height, imposes that on object.
(defun C:THU (/ ss n obj ht)
  (prompt "\nTo Update the Height of fixed-height Text/Mtext,")
  (if (setq ss (ssget '((0 . "TEXT,MTEXT"))))
    (repeat (setq n (sslength ss))
      (setq obj (vlax-ename->vla-object (ssname ss (setq n (1- n)))))
      (if
        (> (setq ht (cdr (assoc 40 (tblsearch "style" (vla-get-StyleName obj))))) 0)
        (vla-put-Height obj ht); then
      ); if
    ); repeat
  ); if
  (princ)
); defun
(vl-load-com)
(prompt "\nType THU for Text Height Update.")

Thank you

 

0 Likes
Accepted solutions (1)
4,144 Views
45 Replies
Replies (45)
Message 2 of 46

_gile
Consultant
Consultant

Hi,

 

When you say "select all", do you mean:

  • in the current space
  • in all spaces
  • in all spaces and block definition


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 3 of 46

_gile
Consultant
Consultant

This mimics the LISP except it does a (ssget "_X" ...)

 

        [CommandMethod("THU")]
        public void TextHeightUpdate()
        {
            var doc = Application.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            var ed = doc.Editor;
            
            var filter = new SelectionFilter(new[] { new TypedValue(0, "MTEXT,TEXT") });
            var psr = ed.SelectAll(filter);
            if (psr.Status != PromptStatus.OK)
                return;

            using (var tr = db.TransactionManager.StartTransaction())
            {
                foreach (SelectedObject so in psr.Value)
                {
                    var id = so.ObjectId;
                    if (id.ObjectClass.DxfName == "TEXT")
                    {
                        var text = (DBText)tr.GetObject(id, OpenMode.ForRead);
                        var textStyle = (TextStyleTableRecord)tr.GetObject(text.TextStyleId, OpenMode.ForRead);
                        if (textStyle.TextSize > 0)
                        {
                            tr.GetObject(id, OpenMode.ForWrite);
                            text.Height = textStyle.TextSize;
                        }
                    }
                    else
                    {
                        var mtext = (MText)tr.GetObject(id, OpenMode.ForRead);
                        var textStyle = (TextStyleTableRecord)tr.GetObject(mtext.TextStyleId, OpenMode.ForRead);
                        if (textStyle.TextSize > 0)
                        {
                            tr.GetObject(id, OpenMode.ForWrite);
                            mtext.Height = textStyle.TextSize;
                        }
                    }
                }
                tr.Commit();
            }
        }


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 4 of 46

_gile
Consultant
Consultant

Here's an optimization of the previous routine which first collect all the names and heights of textsyles which TextSize is greater than 0.

 

        [CommandMethod("THU")]
        public void TextHeightUpdate()
        {
            var doc = Application.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            var ed = doc.Editor;

            var textStyles = GetFixedHeightTextStyles(db);
            if (!textStyles.Any())
                return;

            var filter = new SelectionFilter(new[] 
            {
                new TypedValue(0, "MTEXT,TEXT"),
                new TypedValue(7, string.Join(",", textStyles.Keys))
            });
            var psr = ed.SelectAll(filter);
            if (psr.Status != PromptStatus.OK)
                return;

            var textClass = RXObject.GetClass(typeof(DBText));

            using (var tr = db.TransactionManager.StartTransaction())
            {
                foreach (SelectedObject so in psr.Value)
                {
                    var id = so.ObjectId;
                    if (id.ObjectClass.IsDerivedFrom(textClass))
                    {
                        var text = (DBText)tr.GetObject(id, OpenMode.ForWrite);
                        text.Height = textStyles[text.TextStyleName];
                    }
                    else
                    {
                        var mtext = (MText)tr.GetObject(id, OpenMode.ForRead);
                        mtext.Height = textStyles[mtext.TextStyleName];
                    }
                }
                tr.Commit();
            }
        }

        Dictionary<string, double> GetFixedHeightTextStyles(Database db)
        {
            using (var tr = db.TransactionManager.StartOpenCloseTransaction())
            {
                return ((TextStyleTable)tr.GetObject(db.TextStyleTableId, OpenMode.ForRead))
                    .Cast<ObjectId>()
                    .Select(id => (TextStyleTableRecord)tr.GetObject(id, OpenMode.ForRead))
                    .Where(ts => ts.TextSize > 0.0)
                    .ToDictionary(ts => ts.Name, ts => ts.TextSize);
            }
        }


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 5 of 46

muckmailer
Collaborator
Collaborator

I would like to select all Text, Mtext and I think dtext if in the drawing if that is possable.

If I could controll include attributes and text in blocks that would be great but I think that would make things too complex.

 

I plan on putting the routine in a batch loop.  I am hoping to eventually control text height, width and maybe style. Especially Height & width.

 

I have modified that ssget in that lisp routine to select all text but I would have to load it and use command send to use it in VS.

 

Thank

0 Likes
Message 6 of 46

_gile
Consultant
Consultant

The above codes select all Texts and Mtexts in the drawing, like: (ssget "_X" '((0 . "TEXT.MTEXT")))



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 7 of 46

muckmailer
Collaborator
Collaborator

On the last routine I got the following error.

 

Error.PNG

0 Likes
Message 8 of 46

GiaBach
Contributor
Contributor

Please change this line : 

var mtext = (MText)tr.GetObject(id, OpenMode.ForRead);

to :

var mtext = (MText)tr.GetObject(id, OpenMode.ForWrite);

 

0 Likes
Message 9 of 46

muckmailer
Collaborator
Collaborator

That made it have an e-lock violation.

Error1.PNG

0 Likes
Message 10 of 46

_gile
Consultant
Consultant

@GiaBach wrote:

Please change this line : 

var mtext = (MText)tr.GetObject(id, OpenMode.ForRead);

to :

var mtext = (MText)tr.GetObject(id, OpenMode.ForWrite);

 


@GiaBach thanks for correcting this.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 11 of 46

_gile
Consultant
Consultant

@muckmailer wrote:

That made it have an e-lock violation.

Error1.PNG


Please describe how do you use the command, this error won't occur when calling the THU command from command line.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 12 of 46

muckmailer
Collaborator
Collaborator

I make a form and use allow me to a button.

Here is the code I have now I think it works. I put lockdoc code in it.

  private void button11_Click(object sender, EventArgs e)
        {
            //ObjMycommands.RemoveTxtOverrides();   
            //Test();
            // ChangeTextsize();
            //SendACommandToAutoCAD();
            TextHeightUpdate();
        }     
       //Update Routine
        public void TextHeightUpdate()
        {
            System.Windows.Forms.MessageBox.Show("THU");
            var doc = Autodesk.AutoCAD.ApplicationServices.Core.Application.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            var ed = doc.Editor;

            var textStyles = GetFixedHeightTextStyles(db);
            if (!textStyles.Any())
                return;

            var filter = new SelectionFilter(new[] 
            {
                new TypedValue(0, "MTEXT,TEXT"),
                new TypedValue(7, string.Join(",", textStyles.Keys))
            });
            var psr = ed.SelectAll(filter);
            if (psr.Status != PromptStatus.OK)
                return;

            var textClass = RXObject.GetClass(typeof(DBText));
            using (DocumentLock docLock = doc.LockDocument())
            {


                using (var tr = db.TransactionManager.StartTransaction())
                {
                    foreach (SelectedObject so in psr.Value)
                    {
                        var id = so.ObjectId;
                        if (id.ObjectClass.IsDerivedFrom(textClass))
                        {
                            var text = (DBText)tr.GetObject(id, OpenMode.ForWrite);
                            text.Height = textStyles[text.TextStyleName];
                        }
                        else
                        {
                            //var mtext = (MText)tr.GetObject(id, OpenMode.ForRead);
                            var mtext = (MText)tr.GetObject(id, OpenMode.ForWrite);
                            mtext.Height = textStyles[mtext.TextStyleName];
                        }
                    }
                    tr.Commit();


                }//using
            }
            }//Routine

        Dictionary<string, double> GetFixedHeightTextStyles(Database db)
        {
            using (var tr = db.TransactionManager.StartOpenCloseTransaction())
            {
                return ((TextStyleTable)tr.GetObject(db.TextStyleTableId, OpenMode.ForRead))
                    .Cast<ObjectId>()
                    .Select(id => (TextStyleTableRecord)tr.GetObject(id, OpenMode.ForRead))
                    .Where(ts => ts.TextSize > 0.0)
                    .ToDictionary(ts => ts.Name, ts => ts.TextSize);
            }
        }



//Update Routine
0 Likes
Message 13 of 46

_gile
Consultant
Consultant

The request in the OP was to mimic a LISP command, so I replied with a .NET command.

I could not guess that you wanted an event handler for a button.

 

Anyway, Im glad you get it work.

 

You could avoid using the LockDocument by calling the command from the button event handler (safer way):

 

private void button11_Click(object sender, EventArgs e)
{
var doc = Autodesk.AutoCAD.ApplicationServices.Core.Application.DocumentManager.MdiActiveDocument;
if (doc != null)
doc.SendStringToExecute("THU ", false, false, false);
}    

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 14 of 46

muckmailer
Collaborator
Collaborator

What does false do in  "THU ", false, false, false.

I never did find any information true/false keywords on that in the Autodesk webpages.

 

Thank you,

0 Likes
Message 15 of 46

_gile
Consultant
Consultant

Have a look >>here <<.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 16 of 46

muckmailer
Collaborator
Collaborator

So if I put your routine in Mycommands and start it with a type-in command I do not have the e-lock problem.

 

If place that same routine in a form module that introduces the e-lock violation.

 

If it try something like the code I have in button 12 I still have the e-lock violation.

 

So is placing AutoCAD routines in Mycommands and using command send to avoid e-lock violations
is the preferred menhod if you wnat to use form controls?

 

I the past I thought they recommand not using command sends. Why is it prefered over
using LockDocument? Why is that safer?

//Start Update Routine
        private void button11_Click(object sender, EventArgs e)
        {
            var doc = Autodesk.AutoCAD.ApplicationServices.Core.Application.DocumentManager.MdiActiveDocument;
            if (doc != null)
                doc.SendStringToExecute("THU ", false, false, false);
         }
        private void button12_Click(object sender, EventArgs e)
        {
            // This gives elock Violation,
            MyCommands ObjTHUStart = new MyCommands();
            ObjTHUStart.TextHeightUpdate();  
          }
  
  //Start Update Routine   

 

 

0 Likes
Message 17 of 46

_gile
Consultant
Consultant

Extract from Kean Walmsley blog:

 

Once again there’s our important rule of thumb when it comes to implementing a modeless UI: rather than manually locking the current document, it’s safer to define a command – which will implicitly lock the current document – and call that from the UI via SendStringToExecute().

 

 

 

I'ts safer because you let AutoCAD take care of locking the document (and setting the focus to the AutoCAD window).

Another advantage is that it also allows the user to hit Enter to re-launch the command.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 18 of 46

muckmailer
Collaborator
Collaborator

I would like to expand this routine to also update mtext & text widths

so I add the following lines to your code.

 

 

text.Height = textStyles[text.TextStyleName];
text.WidthFactor = textStyles[text.TextStyleName];
// mtext.How do I know what intellisense keywords do?

}
else
{
//var mtext = (MText)tr.GetObject(id, OpenMode.ForRead);
var mtext = (MText)tr.GetObject(id, OpenMode.ForWrite);
mtext.Height = textStyles[mtext.TextStyleName];
//mtext.??? = textStyles[text.TextStyleName];
// mtext.How do I know what intellisense keywords do?
 

So I thinik I might have guessed the text.WidthFactor to for text width but I am puzzled on how the control M text width by looking at 

intellsense keywords. So how can I control Mtext width in this routine and how know learn how to use effectivly use 
intellisense keywords? How do I learn the intellsense roadmap for AutoCAD? Is there a good guide or tutorial for these words?

 

0 Likes
Message 19 of 46

_gile
Consultant
Consultant

Hi,

 

With MText instances, the width factor in MTEXT formatting (\W) which can affect only a portion of the text.

See >>here<< and >>there<<.

 

You can easily remove all mtext formatting doing:

mtext.TextString = mtext.Text;

but only removing some formatting is not so trivial.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 20 of 46

_gile
Consultant
Consultant

You can try using regular expression:

var regex = new Regex(@"\\W\d*(\.\d+)?;", RegexOptions.IgnoreCase);
mtext.Contents = regex.Replace(mtext.Contents, "");


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes