TheSwamp

Code Red => .NET => Topic started by: badjo_5 on November 30, 2018, 01:26:50 PM

Title: Things are getting complicated ...
Post by: badjo_5 on November 30, 2018, 01:26:50 PM
Hi All,

this is my first post, so far I haven't need to ask anything because you have asked all the questions that I had :smitten:

I've created a custom palette with the user control, I'm putting the block with attributes in the drawing. I have about 100 different values for attributes, they are all sorted in 6 comboboxe's. The code is a classic while loop build around the GetPoint.

Code: [Select]
public void insBlok(string code)
        {
            Document doc = AcAp.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            Utils.SetFocusToDwgView();
            Point3d ptPoint = new Point3d(0, 0, 0);
            try
            {
                while (ptPoint != null)
                {
                    PromptPointResult pPtRes;
                    PromptPointOptions pPtOpts = new PromptPointOptions("");
                    pPtOpts.AllowNone = true;
                    pPtOpts.Message = "\nSelect point: ";
                    pPtRes = doc.Editor.GetPoint(pPtOpts);
                    if (pPtRes.Status == PromptStatus.None || pPtRes.Status == PromptStatus.Cancel || pPtRes.Status == PromptStatus.Error)
                    {
                        return;
                    }
                    ptPoint = pPtRes.Value;
                    using (DocumentLock loc = doc.LockDocument())
                    {
                        using (Transaction tr = db.TransactionManager.StartTransaction())
                        {
...................
                            using (BlockReference blockRef = new BlockReference(ptPoint, btr.ObjectId))
                            {
                               
                                foreach (ObjectId id in btr)
                                {
                                       //insert value in attribute,
                                }
                            }
                            tr.Commit();
                        }
                    }                   
                }
            }
            catch (System.Exception x)
            {
                ed.WriteMessage("\nError: " + x.Message);
            }
            finally
            {
                ed.WriteMessage("\n");
            }
        }

This is a code for button click:

Code: [Select]
private void cboBtn_ButtonClick(object sender, EventArgs e)
        {
            string buttonText = ((ComboBox1)sender).Text;
            buttonText = buttonText.Substring(0, 3);
            insBlok(buttonText);
        }

When I click on the button, ewerything work as sholud, but when I select different attribut from ComboBox and click again on the button (without ending first command with Enter or Esc), same command fire's once again, this time nested in previous transaction. After ending second command, first command is active.

I could create bool active_command, but there is another User Form with similar code (different block with different attribute values), so I am able to change palette, select attribute value, click on button on that User Form, insert that block, and after that first command is active.

Command is without CommandMethod atribut, it can be called only from custom palette.

What now? I can remove whilw loop, but then user must click every time on the button. With CommandMethod atribute i should have 100 commands (this is addin not only for Autocad). SendCommand ^C^C is not an option, I think.....
Title: Re: Things are getting complicated ...
Post by: Atook on November 30, 2018, 03:55:51 PM
Not sure why your shying away from the CommandMethod attribute.

Almost all my palettes execute commands via SendStringToExecute, there's too much tom!@#$ tomfoolery with document locks, etc.

\x03\x03 at the beginning of the string to execute cancels the current command before executing the new one.

Maybe you'll find this useful:
Code - C#: [Select]
  1. [CommandMethod("MyCommand")]
  2. public void MyCommand()
  3. {
  4.   try
  5.   {
  6.     string attText = myPalette.AttString
  7.     inBlock(attText);
  8.   }
  9.   catch (Exception e)
  10.   {
  11.     ErrorHandler.HandleError(e);
  12.   }
  13. }
  14.  
  15. private void btnMyButton_Click(object sender, EventArgs e)
  16. {
  17.   Active.Document.SendStringToExecute("\x03\x03MyCommand ", true, false, false);
  18. }
Title: Re: Things are getting complicated ...
Post by: badjo_5 on November 30, 2018, 04:07:02 PM
Interesting.....

I must try it first. Thanks!
Title: Re: Things are getting complicated ...
Post by: Grrr1337 on November 30, 2018, 07:17:03 PM
@Atook
If the GetPoint method is used, wouldn't that mean that the whole method MyCommand must be wrapped within
Form1.Hide();
SendStringToExecute("MyCommand");
Form1.Show();


And if so, isn't there a risk of synchronous execution?
Where the SendStringExecute will just throw the command for execution and won't wait for any user inputs and the .NET will just continue on Form1.Show();
So the user will be instantly interrupted because of the form/dialog redisplaying.
I'm mentioning that because recently had a discussion (https://www.cadtutor.net/forum/topic/66402-command-save-to-visual-lisp/?tab=comments#comment-544996) about the SendCommand method, which may perform similarly to the SendStringToExecute.

Talking blindly, so excuse me if I'm totally off track.
Assuming its a modal dialog ofcourse, not sure if its possible to do it with modeless.
Title: Re: Things are getting complicated ...
Post by: Atook on November 30, 2018, 10:13:11 PM
@Grrr1337 it's my understanding the command is running from a palette, not a form.

Title: Re: Things are getting complicated ...
Post by: badjo_5 on December 01, 2018, 06:30:16 AM
You are correct Atook, from palette.
Title: Re: Things are getting complicated ...
Post by: n.yuan on December 01, 2018, 10:19:44 AM
@Grrr1337 it's my understanding the command is running from a palette, not a form.

@Grrr1337 may refer to modeless form, which would behaves the same as PaletteSet in this case.

To the OP:

Using SendStringToExecute() is the recommended way to do work from PaletteSet, especially in your case (inserting blocks). Not only user can click button on the PalateeSet again with previous inserting loop still active, user can do the same with other AutoCAD command active. So, you do need to handle this situation: when button clicked, the first thing is to test if there is a command active. If yes, you either warning user and stop; or you cancel the active command and then continue. You can always prefix your command in SendStringToExecute() with "^C^C" ("\x03\x03") with your command (now you see why SendStringToExecute() is recommended way for ding things from PalateSet, or modeless form).

It may also be good idea to hide the PaletteSet/modeless form during the inserting loop, so that the form only shows back when the inserting loop completes explicitly, after all, hiding the UI would allow more AutoCAD screen being exposed for picking.

There is recent discussion in AutoCAD .NET forum on this, and I wrote an article in respond that might be helpful:

https://drive-cad-with-code.blogspot.com/2018/10/executing-command-from-paletteset.html (https://drive-cad-with-code.blogspot.com/2018/10/executing-command-from-paletteset.html)


Title: Re: Things are getting complicated ...
Post by: badjo_5 on December 01, 2018, 03:44:24 PM
Many thanks Yuan. Hiding PaleteSet is not a a good idea, I can only scare users with that (over half of them are still asking why I didn't created toolbars to insert blocks - ansever is that I don't have enough icons :knuppel2:).
Allready implemented Atook solution with minor change: I found a extra room for Command Window wersion of command, some of blocks are more frequently inserted then others... sory, block is the same, it is all about attributes, atribute is the code for land use :-I
Other commands from PaletteSet are not problematic, they are simply click/select/change.

And I tried with CMDACTIVE, but without result. And once again, to many things to read in short time.