It is possible to pass arguments to a command in a way similar to pushing them onto the callstack before calling the command?
I've got existing commands that use the OpenFileDialog to get a list of drawings to process. I'm using my new palette to send this list to commands. I've modified my old command as follows:Code - C#: [Select]
[CommandMethod("MyCommand")] public void MyCommand() { Blah Blah Blah... do open file dialog foreach (file in filenames) { Blah Blah Blah.... } } changed to: [CommandMethod("MyCommand")] public void MyCommand() { } public void MySubCommand(List<string> filenames) { using (DocumentLock docLock = Application.DocumentManager.MDIActiveDocument.LockDocument()) { Blah Blah Blah... if (filenames.Count == 0) { do open file dialog filenames = file dialog filenames } foreach (file in filenames) { Blah Blah Blah.... } } }
I know we can pass a selection set via UsePickSet flag, but not sure what is possible here. Can see it could be done using the stack, but not sure what stack interactions occur during command invocation so that method would very easily become a tragic failure.
Thanks for any input!
Not sure what 'stack' you're referring to. I don't know of any stack that AutoCAD takes command input from.back in my embedded programming days it was fairly common to pass values to subroutines by explicitly pushing them onto the call stack. I know that this is quite obscure from the high level perspective of .NET programming, but I suspect that when we are passing parameters to a subroutine this is being implicitly done. To clarify I am not proposing that AutoCAD takes the command from the stack, but that I could possibly push data onto it and the command could check for the presence of data, if such data were present it could bypass the call to OpenFileDialog
You can use Editor.GetString() to prompt for input, and supply the input via a call to the Command() wrapper for RunCommand(), acedCmd(), acedCommand(), etc.,Passing filenames explicitly via command line breaks the old functionality of the tools. I have a series of tools which operate on multiple drawings and those drawings are selected using the open file dialog. One example is a tool that will extract attributes from a given block and print them to an excel file, where they can be changed and imported again. Sort of like a batch ATTOUT/ATTIN.
But that really doesn't make sense if you are sending the input yourself. I'm really not sure I understand what it is you're trying to do, but if the problem is that you're trying to control a batch process from code in a PaletteSet, you can use the Application's Idle event to send command input via SendStringToExecute().
Search this group for 'Application.Idle' and you should find some code I posted some time back showing how the event is used in a transient way.
Hi Will,
Here is a bad example of what I think your asking.
I threw this together last week because we receive drawing from architects and they constantly send updates and it might just be a door swing changes or a wall moves, etc.....
Anyways a guy here opens each drawing received explodes everything because he does not understand how to change the color the block if the definition contains entities where the color is set by a layer other than zero or explicitly set, and changes every layer color to what he already has set 30 times. Also another guy copies the new drawing and paste it next to the old drawing and tries to eyeball what the changes are.
So I gave them some code to change all entities in blocks to layer zero and set ByLayer, and the code below which basic idea is to delete everything in model keeping all block and layer settings, etc... and WBlocking all the entities in from the new drawing. Did it for other reasons and tried to explain to them to freeze layers instead of deleting them because the archs usually already have closed polylines used for getting area that can be reused for automating creating ceiling grid for lights, etc......
Anyways just slapped this together to keep from slapping them and until I have time come up with something better or different workflow, but passes a string for filename by means of SendStringToExecute and Editor.GetString().
The main reason it is broken up into two methods is because it would crash and did not have time to figure out what was going on but a drawing with dynamic blocks seemed to crash every time.
I guess you could do something similar to AutoCAD's search paths by joining a collection of strings with a character that is invalid to use in a file path then splitting it.
However, I'm still not sure I understand what the problem is. In my own modeless UI's, I store the data that will be used in a process somewhere that is accessible to a command (whose CommandMethod may be in the same class or another class), and then I just use SendStringToExecute() to start the command. The command doesn't need to prompt for input, instead it just gets the data that was selected in the modeless UI and does its thing without any hitches.That's the trick, thank you! Since I've put a deep separation between the code of my UI and my functions I was struggling for a way to pass the data. I got the idea for the method I used from what I've seen with overloading functions. I hadn't considered hosting my commands in the same class as the UI, partially because I wasn't aware of exactly how AutoCAD would handle the class creation when the new method is called (i.e. I wasn't sure if AutoCAD would create a new instance of the class to call the method from).
In the case of the WPF UI thread, you may have to use SendStringToExecute() from the handler of the Application's Idle event, which isn't a big deal.I don't think that I will have any limitations with that. The cancel command issue you helped me solve successfully calls SendStringToExecute.
However, I'm still not sure I understand what the problem is. In my own modeless UI's, I store the data that will be used in a process somewhere that is accessible to a command (whose CommandMethod may be in the same class or another class), and then I just use SendStringToExecute() to start the command. The command doesn't need to prompt for input, instead it just gets the data that was selected in the modeless UI and does its thing without any hitches.That's the trick, thank you! Since I've put a deep separation between the code of my UI and my functions I was struggling for a way to pass the data. I got the idea for the method I used from what I've seen with overloading functions. I hadn't considered hosting my commands in the same class as the UI, partially because I wasn't aware of exactly how AutoCAD would handle the class creation when the new method is called (i.e. I wasn't sure if AutoCAD would create a new instance of the class to call the method from).
Something else I had considered was to create a static class which contained a stack which I could use to pass data to my functions.
The goal here is to maintain classic user interaction with these functions while adding new capabilities with the minimum of code duplication and rework.QuoteIn the case of the WPF UI thread, you may have to use SendStringToExecute() from the handler of the Application's Idle event, which isn't a big deal.I don't think that I will have any limitations with that. The cancel command issue you helped me solve successfully calls SendStringToExecute.
On that note, I think the reason that the error was still being thrown even after the escape characters were being sent and the drawings were opening had to do with document locking.
I'm not sure what you'd need a stack for. What I usually do is disable the modeless UI until the entire process is finished, so that it can't be reentered.
If you let the user continue to interact with your UI while the process it started is in-progress, that may be possible, but it would also make things more complicated, possibly requiring thread synchronization, and a Queue rather than a Stack.
The UI would add work items to the queue and start the command if it isn't already running, and the running command would continuously check the queue to see if there's more work items. If there is, the work items are processed and removed from the queue, and that entire process would repeat until the queue is empty.
You only need to store your data in a static class that both your UI and your command implementation have access to, which is preferable to making the CommandMethod a member of your UI class.