Visual LISP, AutoLISP and General Customization
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Autocad 2008 - Calling Mleaders with Mtext via Lisp.

12 REPLIES 12
Reply
Message 1 of 13
qupola
549 Views, 12 Replies

Autocad 2008 - Calling Mleaders with Mtext via Lisp.

I'm finding Mleaders with Mtext don't seem to play well with command calls. All works fine until one tries to enter the mleader text. Before testing this, be sure your mleader style is set to use mtext. I recommend starting the leader with the arrow first.

Compare this mleader's text entry behavior in this basic lisp command call:

(command "_.acad_dim.mleader")

with the following routine that relies on an open ended command prompt (useful if you want to add more commands after calling the mleader command):

(defun c:mlx (/ cc_echo)
(prompt "\nExample showing mleader mtext misbehaving")
(setq cc_echo (getvar "cmdecho"))
(setvar "cmdecho" 1)
(command "_.acad_dim.mleader")
(while (= (logand (getvar "cmdactive") 1) 1)
(command pause)
)
(setvar "cmdecho" cc_echo)
(princ)
)

Note the loss of the usual pop-up text editor. Also note that the first space entered after a word prematurely ends the command.

Did I miss something? If not, I'm looking for a workaround.

Oddly enough, qleaders don't exhibit this annoying text behavior.

(defun c:qlx (/ cc_echo)
(prompt "\nExample showing qleader mtext behaving properly")
(setq cc_echo (getvar "cmdecho"))
(setvar "cmdecho" 1)
(command "_.acad_dim.qleader")
(while (= (logand (getvar "cmdactive") 1) 1)
(command pause)
)
(setvar "cmdecho" cc_echo)
(princ)
)

With qleaders, the leader and text are separate entities. Not so with mleaders, which I suspect is at the root of this funky lisp behavior.
12 REPLIES 12
Message 2 of 13
Anonymous
in reply to: qupola

Seems fairly clear the problems you mentioned are caused by the while statement. It
works as expected if that's commented out.

Just an observation, not meant as a solution.

Joe Burke


wrote in message news:5753191@discussion.autodesk.com...
I'm finding Mleaders with Mtext don't seem to play well with command calls. All
works fine until one tries to enter the mleader text. Before testing this, be sure
your mleader style is set to use mtext. I recommend starting the leader with the
arrow first.

Compare this mleader's text entry behavior in this basic lisp command call:

(command "_.acad_dim.mleader")

with the following routine that relies on an open ended command prompt (useful if you
want to add more commands after calling the mleader command):

(defun c:mlx (/ cc_echo)
(prompt "\nExample showing mleader mtext misbehaving")
(setq cc_echo (getvar "cmdecho"))
(setvar "cmdecho" 1)
(command "_.acad_dim.mleader")
(while (= (logand (getvar "cmdactive") 1) 1)
(command pause)
)
(setvar "cmdecho" cc_echo)
(princ)
)

Note the loss of the usual pop-up text editor. Also note that the first space
entered after a word prematurely ends the command.

Did I miss something? If not, I'm looking for a workaround.

Oddly enough, qleaders don't exhibit this annoying text behavior.

(defun c:qlx (/ cc_echo)
(prompt "\nExample showing qleader mtext behaving properly")
(setq cc_echo (getvar "cmdecho"))
(setvar "cmdecho" 1)
(command "_.acad_dim.qleader")
(while (= (logand (getvar "cmdactive") 1) 1)
(command pause)
)
(setvar "cmdecho" cc_echo)
(princ)
)

With qleaders, the leader and text are separate entities. Not so with mleaders,
which I suspect is at the root of this funky lisp behavior.
Message 3 of 13
qupola
in reply to: qupola

Yes, pretty much. The command pauses in the while loop trigger the funky mleader text behavior. You may already know that a while loop like this one is a pretty standard way of handling a command that features a variable number of user inputs. It pauses for user input as many times as needed until the command is complete. It can be important in lisp to know when such a command IS complete.

One can replace the while loop with a fixed set of command pauses and still see the same unwanted mtext behavior, e.g.:

(defun c:mlx2 (/ cc_echo)
(prompt "\n2nd example showing mleader mtext misbehaving")
(setq cc_echo (getvar "cmdecho"))
(setvar "cmdecho" 1)
(command "_.acad_dim.mleader" pause pause pause)
(setvar "cmdecho" cc_echo)
(princ)
)

Note that the code above is much less flexible than the while loop approach, because it assumes a very specific number of pauses for user input before the lisp routine may reliably make another command call (such as a command call to add addional geometry or to establish an undo point). Here it's assuming 2 pauses to accept the leader head and tail, and one more for the mtext input.
Message 4 of 13
Anonymous
in reply to: qupola

Agreed. That's why I said it's not a solution. Just a hint at what's causing the
problem.

Joe Burke


wrote in message news:5753439@discussion.autodesk.com...
Yes, pretty much. The command pauses in the while loop trigger the funky mleader text
behavior. You may already know that a while loop like this one is a pretty standard
way of handling a command that features a variable number of user inputs. It pauses
for user input as many times as needed until the command is complete. It can be
important in lisp to know when such a command IS complete.

One can replace the while loop with a fixed set of command pauses and still see the
same unwanted mtext behavior, e.g.:

(defun c:mlx2 (/ cc_echo)
(prompt "\n2nd example showing mleader mtext misbehaving")
(setq cc_echo (getvar "cmdecho"))
(setvar "cmdecho" 1)
(command "_.acad_dim.mleader" pause pause pause)
(setvar "cmdecho" cc_echo)
(princ)
)

Note that the code above is much less flexible than the while loop approach, because
it assumes a very specific number of pauses for user input before the lisp routine
may reliably make another command call (such as a command call to add addional
geometry or to establish an undo point). Here it's assuming 2 pauses to accept the
leader head and tail, and one more for the mtext input.
Message 5 of 13
qupola
in reply to: qupola

I should have mentioned that the usual tricks of adding (initdia) and/or (setvar "texteval" 1) before the command call have no effect on the mleader mtext behavior, as they do with plain mtext or qleader command calls thru lisp. I suspect there's little that can be done short of Autodesk's intervention to change the current behavior. Very likely it's somehow tied to the mleader's combination of mtext and leader line as a single entity.

For now I'll probably have to settle for an approach that won't make any additional autocad command calls in lisp after invoking the mleader command. I'm not thrilled about that, but it's not exactly world ending either. 😉 But if someone here can suggest another possible solution, I'd love to hear about it.
Message 6 of 13
Anonymous
in reply to: qupola

Maybe a solution?

Setup an mleader style with a default mtext string "".

Then simply this in code with that style active:

(command "._mleader" "options" "content" "mtext" "exit")

You can feed command options, though the mleader command does not have a (-mleader)
command line equivalent.

It seems to solve the issue, but I'm still playing with it...

Joe Burke



wrote in message news:5754085@discussion.autodesk.com...
I should have mentioned that the usual tricks of adding (initdia) and/or (setvar
"texteval" 1) before the command call have no effect on the mleader mtext behavior,
as they do with plain mtext or qleader command calls thru lisp. I suspect there's
little that can be done short of Autodesk's intervention to change the current
behavior. Very likely it's somehow tied to the mleader's combination of mtext and
leader line as a single entity.

For now I'll probably have to settle for an approach that won't make any additional
autocad command calls in lisp after invoking the mleader command. I'm not thrilled
about that, but it's not exactly world ending either. 😉 But if someone here can
suggest another possible solution, I'd love to hear about it.
Message 7 of 13
qupola
in reply to: qupola

Thanks Joe, I really appreciate your time and thought into this matter, but I'm not seeing how that bit of code puts the matter to rest. Maybe I didn't explain the problem I'm seeing well enough. I'll try to clarify:

With mleaders styles that use mtext content, a simple (command "_.acad_dim.mleader") (or the variant you have included above) will allow mleaders and their mtext to work just fine. But that's only if it's the last (command ...) called in the lisp routine. Have to be careful even with that, the mtext portion of the mleader may try to swallow ANY lisp code or text that follows as input.

I'd like to issue another command call in lisp after mleader command in lisp is complete. Doing so always seems to prevent the text editor from popping up as usual. It doesn't matter if it's a repeating pause for user input, or another kind of command call like (command ".undo "mark"). Any (command "do_stuff") following the code (command "_.acad_dim.mleader" ...) prevents the mleader's in place mtext editor from opening as one might like (I think we need a texteval or initdia like variable or function that understands mleaders for that to happen). Without the editor, the mleader's mtext command prompt evaluates whatever it gets in response as a literal string. That might be the next line of code if you didn't put the command in a "while command pause loop". I've found that the mtext command prompt will accept spaces in the text string if you surround the string you enter in quotes. The quoted string doesn't seem to like line breaks ASFAICT though, e.g "This is\pa test" will yield the text "This is" (minus the quotes) without the second line. Without the quotes, it interprets the first space it reads as a return and ends the mtext.

Setting mleaders to use no content might offer a workaround if the mleader mtext could be appended to the mleader afterward. I see several inherent problems with that approach though. Ideally, we need some means to control whether or not the mtext editor pops up prior to issuing the mtext portion of the mleader command.
Message 8 of 13
Anonymous
in reply to: qupola

Agreed, it doesn't help.

I tried an mleader with content type none. That property can be changed from 0 (none)
to 2 (mtext) afterwards. But an attempt to change the TextString property returns an
error.

(vlax-put obj 'textstring "abc")
error: Exception occurred

Joe Burke

wrote in message news:5756194@discussion.autodesk.com...
Thanks Joe, I really appreciate your time and thought into this matter, but I'm not
seeing how that bit of code puts the matter to rest. Maybe I didn't explain the
problem I'm seeing well enough. I'll try to clarify:

With mleaders styles that use mtext content, a simple (command "_.acad_dim.mleader")
(or the variant you have included above) will allow mleaders and their mtext to work
just fine. But that's only if it's the last (command ...) called in the lisp
routine. Have to be careful even with that, the mtext portion of the mleader may try
to swallow ANY lisp code or text that follows as input.

I'd like to issue another command call in lisp after mleader command in lisp is
complete. Doing so always seems to prevent the text editor from popping up as usual.
It doesn't matter if it's a repeating pause for user input, or another kind of
command call like (command ".undo "mark"). Any (command "do_stuff") following the
code (command "_.acad_dim.mleader" ...) prevents the mleader's in place mtext editor
from opening as one might like (I think we need a texteval or initdia like variable
or function that understands mleaders for that to happen). Without the editor, the
mleader's mtext command prompt evaluates whatever it gets in response as a literal
string. That might be the next line of code if you didn't put the command in a "while
command pause loop". I've found that the mtext command prompt will accept spaces in
the text string if you surround the string you enter in quotes. The quoted string
doesn't seem to like line breaks ASFAICT though, e.g "This is\pa test" will yield the
text "This is" (minus the quotes) without the second line. Without the quotes, it
interprets the first space it reads as a return and ends the mtext.

Setting mleaders to use no content might offer a workaround if the mleader mtext
could be appended to the mleader afterward. I see several inherent problems with
that approach though. Ideally, we need some means to control whether or not the
mtext editor pops up prior to issuing the mtext portion of the mleader command.
Message 9 of 13
Anonymous
in reply to: qupola

Plus this from developer help regarding the mleader object type:

"Any annotation attached to the end of the leader line is associated with the MLeader
object and can be found using the Annotation property."

A Leader object has an Annotation property, but an MLeader does not. The developer
docs are wrong in this case. Not to mention the fact documentation regarding
annotative objects is totally lacking at least from the lisp/vlisp standpoint AFAIK.

While I'm at it, the new "features" added in 2008 feel like Autodesk scratching its
ass to me. Like they don't know what to do next, so toss in a bunch of poorly thought
out crap. And likewise, don't document the crap.

During the twenty plus years I've been using CAD I can't recall ever disliking a new
version of any program. ACAD 2008 is the first.

Joe Burke
Message 10 of 13
qupola
in reply to: qupola

Hi Joe,

I found another avenue to explore, partly inspired by your idea about trying to modify the textstring property of mleaders. (It does indeed work, as I'll demonstrate below.) I completely agree with you about the crappy documentation.

Anyway, try this:

Set up a mleader style with mtext content. This will NOT work if you set the mleader content to none.

Draw a mleader. It doesn't matter whether you enter in mtext or leave it blank. What's important is that the mleader understands that mtext COULD be attached.

Then run the following code at the autocad command line, which grabs the last entity and then substitutes a new mleader textstring:

(setq obj (vlax-ename->vla-object (entlast)))
(vlax-put-property obj 'textstring "This is\\Ptest number 1.")

or alternatively for the second line:

(vla-put-TextString obj "This is\\Ptest number 2.")



Note that one can get the textstring contents of obj this way:

(vla-get-TextString obj)


Previously I had been stymied by the loss of the pop-up editor once the mleader command was coupled with a "while command pause" loop. I've since found a workaround that shows some promise. My biggest complaint with it is that it requires an extra return or space at the prompt before the user sees the mtext pop up editor. That can be confusing for users, especially since the command prompt provides no clue. I'm still thinking about how I might get around that without limiting the command in other ways.

Anyway, here's the latest, warts and all. I'll be adding some more stuff, but this is the meat of it.


(defun c:mly (/ cc_echo cc_ss cc_texteval)
(prompt "\nImproved mleader mtext behavior")
(setq cc_texteval (getvar "texteval"))
(setvar "texteval" 1)
(setq cc_echo (getvar "cmdecho"))
(setvar "cmdecho" 1)
(command "_.acad_dim.mleader")
(while (= (logand (getvar "cmdactive") 1) 1)
(command pause)
)
(setvar "cmdecho" cc_echo)
(setvar "texteval" cc_texteval)
(setq cc_ss (entlast))
(if (= (vla-get-ContentType (vlax-ename->vla-object cc_ss)) 2) ;check availability of mtext content
(command "_.ddedit" cc_ss "") ;edit text and exit command
)
(princ)
)



One thing I like about the command pause loop approach is that it allows the mleader command to function in lisp much as it would on the Autocad command line. Users may change the mleader options at the command line as they see fit, and not be locked into a predetermined pattern and number of responses in order to proceed with the command.

Note that I ended up including the texteval variable, even though it doesn't control the appearance of the pop up mtext editor in mleaders. I found it DOES have an effect on the block content option when selected via the mleader command line. if not set to 1, the routine will pass an endless stream of backslashes to the block name prompt.
Message 11 of 13
Anonymous
in reply to: qupola

Nice work. It seems to address the issue at hand.

BTW, I always assumed a custom mleader style with content type mtext would be used.

I'll have to study it further to fully understand. More later once I have a handle.

Regards
Joe


wrote in message news:5758766@discussion.autodesk.com...
Hi Joe,

I found another avenue to explore, partly inspired by your idea about trying to
modify the textstring property of mleaders. (It does indeed work, as I'll demonstrate
below.) I completely agree with you about the crappy documentation.

Anyway, try this:

Set up a mleader style with mtext content. This will NOT work if you set the mleader
content to none.

Draw a mleader. It doesn't matter whether you enter in mtext or leave it blank.
What's important is that the mleader understands that mtext COULD be attached.

Then run the following code at the autocad command line, which grabs the last entity
and then substitutes a new mleader textstring:

(setq obj (vlax-ename->vla-object (entlast)))
(vlax-put-property obj 'textstring "This is\\Ptest number 1.")

or alternatively for the second line:

(vla-put-TextString obj "This is\\Ptest number 2.")



Note that one can get the textstring contents of obj this way:

(vla-get-TextString obj)


Previously I had been stymied by the loss of the pop-up editor once the mleader
command was coupled with a "while command pause" loop. I've since found a workaround
that shows some promise. My biggest complaint with it is that it requires an extra
return or space at the prompt before the user sees the mtext pop up
editor. That can be confusing for users, especially since the command prompt
provides no clue. I'm still thinking about how I might get around that without
limiting the command in other ways.

Anyway, here's the latest, warts and all. I'll be adding some more stuff, but this
is the meat of it.


(defun c:mly (/ cc_echo cc_ss cc_texteval)
(prompt "\nImproved mleader mtext behavior")
(setq cc_texteval (getvar "texteval"))
(setvar "texteval" 1)
(setq cc_echo (getvar "cmdecho"))
(setvar "cmdecho" 1)
(command "_.acad_dim.mleader")
(while (= (logand (getvar "cmdactive") 1) 1)
(command pause)
)
(setvar "cmdecho" cc_echo)
(setvar "texteval" cc_texteval)
(setq cc_ss (entlast))
(if (= (vla-get-ContentType (vlax-ename->vla-object cc_ss)) 2) ;check availability
of mtext content
(command "_.ddedit" cc_ss "") ;edit text and exit
command
)
(princ)
)



One thing I like about the command pause loop approach is that it allows the mleader
command to function in lisp much as it would on the Autocad command line. Users may
change the mleader options at the command line as they see fit, and not be locked
into a predetermined pattern and number of responses in order to proceed with the
command.

Note that I ended up including the texteval variable, even though it doesn't control
the appearance of the pop up mtext editor in mleaders. I found it DOES have an
effect on the block content option when selected via the mleader command line. if
not set to 1, the routine will pass an endless stream of backslashes to the block
name prompt.
Message 12 of 13
qupola
in reply to: qupola

Thanks. The way the mtext pop up editor gets triggered is a bit kludgy IMHO, but I don't see a way that does it any better yet.

Regarding your assumption, I actually wanted the routine to offer the user all the usual options and behavior of mleader. It's intended (with some additional code) as a replacement for the usual mleader command. While the working of mleaders with mtext content was my focus here, I wanted the routine to accommodate every kind of mleader content. I simply wanted to wrap the command with a few other commands. Eg. things that addressed layering, setting the mleader style (if needed), and the ability to undo the newly defined command in a single swoop.

Of course I am also interested in establishing my own mleaderstyles programmatically. While the documentation of mleaderstyles leaves much unsaid, I've uncovered most of what I need to do the job. Fortunately, the vlax-put-property commands allow one to establish and manipulate most of the necessary mleaderstyle settings.

The only mleaderstyle setting eluding me via vlisp is the Always left justify checkbox option. AFAICT, it's a setting that may only be controlled thru the manipulation of the mleaderstyle dictionary entries, which are both poorly documented and complex (especially because they contain so many darn subentities). 297 seems the dxf code for the thing.

Anyway, I look forward to further collaboration in the future.
Message 13 of 13
kudzuman
in reply to: qupola

2013 still has this issue.

The loop can be nice, but if you wanted to specify mleader options so that you know where the "Enter text" prompt should be, then put in double quotes there and this works pretty smoothly:

 

  (command "._mleader" "o" "m" "2" "c" "m" "x" pause pause "")
  (command "_.ddedit" (entlast) "")

 

Thanks for the ddedit (entlast) tip!

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report

”Boost