Convert Windows Form external rule to a called subroutine with arguments

JBerns
Advisor
Advisor

Convert Windows Form external rule to a called subroutine with arguments

JBerns
Advisor
Advisor
Community,
 
Goal:
Convert an external rule, containing a Windows Form, into a rule that can be included with 'AddVbFile'.
The WinForm, which contains a RichTextBox object, could then be used by any rule with the ability to specify arguments (width, height, formatted text, etc.).
 
Background:
I developed an iLogic custom windows form (not DLL) that includes a RichTextBox. This offers text formatting options and most importantly, scrollbars - which is an improvement over MsgBox.
A chose iLogic code over a DLL to allow others to customize more easily. (Visual Studio not required)
 
Reusing the WinForm code required copying from rule to rule.
 
I converted it to an external rule, which can run from the iLogic Browser, but the arguments (width, height, text) are now static.
 
With the Community assistance, I hope we can modify the code to leverage 'AddVbFile' and the ability to pass arguments as mentioned above. I hope to avoid parameter mapping.
 
For example:
 

 

AddVbFile "Form - RichTextBox.Vb"

Sub Main
   ShowCustomForm(600, 400, "Sample text")
End Sub

 

 
I have seen examples of external rules that have subs and functions that are passed arguments. However, none of those examples use windows forms.
 
If this is possible, I would welcome the Community assistance to make this a more re-useable tool.
 
Thank you for your time and attention. I look forward to your replies.
 
Regards,
Jerry
 
P.S.  I changed the file extension to '.txt' to allow the code to be attached to this post.

 

-----------------------------------------------------------------------------------------
CAD Administrator
Using Inventor 2022
Autodesk Certified Instructor
Autodesk Inventor 2020 Certified Professional
Autodesk AutoCAD 2017 Certified Professional
0 Likes
Reply
Accepted solutions (2)
750 Views
10 Replies
Replies (10)

WCrihfield
Mentor
Mentor

Hi @JBerns.  So, do you want to be able to use your Form code the way you showed in that small code window, or is that code window an example of how you do not want to have to use it?

 

Are you familiar with using the Property statement?  Within your Class, you can have private, hidden variables to hold onto the values you pass in, for internal use, that are declared at the main Class level, outside of any Subs/Functions.  Then you can also have Public Property statement blocks of code, where you can define Properties that your Class has for users to interact with.  These can be declared as ReadOnly, or not.  If not, then within that Property statement should be both a 'Set' statement, and a 'Get' statement, which dictate how the property works.  The Set statement simply passed an 'input parameter' to your private/internal variable.  The Get statement includes a 'Return' statement, just like a Function, and returns the value of your private/internal variable.

 

That is just one general idea.  You could likely also combine the two Classes into one Class.  But either way, you will likely need to use the 'New' keyword within the iLogic rule that uses your referenced Class, because you will need to create an instance of it, before you can use it.  And if using the 'New' keyword, you could just directly pass those input variables into the 'New' Sub routine, instead of having to go though the secondary Class, or its ShowCustomForm routine.  When the 'New' Sub routine has input variables, that is one of the two main ways to 'pass' data from the 'calling' routine (your regular rule) to the referenced Class.  The other way is how I mentioned in the first paragraph...the Class having public properties.  When that is the case, after you create a new instance of that Class, you then set those property values, before using any of the Subs/Functions within that Class.  Not the cleanest way, if some of those Subs/Functions rely on those input variables though.

 

Edit:  Forgot to mention the most important detail.  When converting an external iLogic rule to a file that you can reference using 'AddVbFile', you must turn the 'Straight VB Code' option on.  Doing so will usually show a brief warning, because that does change how the code is interpreted.  For example, it becomes much more strict, and certain terms (like "ThisApplication") are no longer recognized, requiring alternative variables be created locally, and values being set to them.  The Inventor.Application object is one of the most basic ones often passed from rules to externally referenced tools.  Other common ones are the 'Rule Object' type objects.

And on a side note, if your external rule (turned into reference) contained a Module, instead of a Class, then you would not need to create an instance of it before using its methods.  But those are a bit different to work with than Classes.  Modules are also good for defining 'extension' helpers for existing object types.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes

g.georgiades
Advocate
Advocate

I am personally not a fan of AddVBFile. I find that Inventor does not really recompile it properly when changes are made thus requiring a restart every time I edit the file.

 

I like to use ilogic rule runner instead and work off the input/output NameValueMap. This way I don't have to worry about straight vb code and can still use the default objects like ThisApplication in the child rule. And I don't have to restart inventor because it cached the old code from the AddVbFile statement.

 

Here is an example i use where I want to search vault for properties given a file name.

Dim map As NameValueMap = ThisApplication.TransientObjects.CreateNameValueMap()
map.Add("fPath", doc.FullFileName)
map.Add("fProps", {"State"})
iLogicVb.RunExternalRule("Vault - Get Property For Document.iLogicVb", map)
Dim returnvals = map.Item("fPropsRet")

 

 

Also if you set it up proper, you can use windows forms designer directly on ilogic rules without requiring an external dll. You are actually close to the required formatting with the example you posted.

 

 

 

WCrihfield
Mentor
Mentor

Hi @g.georgiades.  I like passing arguments between rules also, which keeps all code in iLogic realm.  However, I did not realize that code from sources referenced with AddVbFile were held in Inventor's memory until closing Inventor.  I am aware that if I create an event handler with an iLogic rule without a backdoor way to access it again, I will not be able to either change it or remove it, without restarting Inventor.  So, you are saying that even after the rule that used the AddVbRule in its header has finished and closed...the code of the external source is still held in Inventor's memory until you close Inventor?  If so then that does not sound very good.  However, I only put code out into a file formatted that way after it has been thoroughly tested in my regular rules, and should not require any further changes, so it does not sound like a huge problem.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes

JBerns
Advisor
Advisor

@g.georgiades,

The external rule as it is now works, it just has static values.

 

JBerns_0-1726597812388.png

 

I want to be able to pass arguments for width, height, text.

 

My goal is to make a better MsgBox that has scrollbars.

 

Regards,

Jerry

 

-----------------------------------------------------------------------------------------
CAD Administrator
Using Inventor 2022
Autodesk Certified Instructor
Autodesk Inventor 2020 Certified Professional
Autodesk AutoCAD 2017 Certified Professional
0 Likes

JBerns
Advisor
Advisor

@WCrihfield,

 

My original goal was to make a better MsgBox. I could have used a TextBox control, but saw others asking about font, color, bold, etc. I chose to use a RichTextBox control to gain that text formatting.

 

It would be great if I could call the subroutine as shown (with arguments). Myself or others could enhance the code as needed to pass additional arguments to modify the WinForm.

 

If a few more lines of code are required, so be it. It would still likely be shorter than copy/paste 150+ lines of code for each rule that could use a better MsgBox.

 

To share this WinForm between rules, I figured the subroutine would have to be external and therefore loaded (declared), so I thought I could use AddVbFile. However, I could not seem to resolve the errors when using the AddVbFile statement:

JBerns_0-1726598755124.png

 

I also tried adding the 'Straight Vb' option, but errors persisted.

 

The code works when I run from the External Rule tab of the iLogic browser, but many errors occur when I try to add the file to other rules.

 

I am aware of the public class properties and was experimenting with that before posting. Some success until I tried to use AddVbFile. If a few more declarations or lines of code are required, I could live with that.

 

* * * Is this a practical approach? Or should I have used a DLL? I would still want to pass arguments such as width, height, and text.

 

The goal to build a better mousetrap MsgBox seems to be getting complicated. 

 

Regards,

Jerry

 

 

  

-----------------------------------------------------------------------------------------
CAD Administrator
Using Inventor 2022
Autodesk Certified Instructor
Autodesk Inventor 2020 Certified Professional
Autodesk AutoCAD 2017 Certified Professional
0 Likes

JBerns
Advisor
Advisor
I just tested an external file that stores several common subs and functions.
I ran an internal rule that uses AddVbFile to load these subs and functions.
I called a sub that displays a MsgBox.
I modified and saved the external rule, and ran the internal rule again. The updated MsgBox appeared.
I did not have to exit Inventor to see the change.
Perhaps we are not comparing similar scenarios, but I too have not had to exit Inventor to see changes to code contained in a file loaded with AddVbFile.
-----------------------------------------------------------------------------------------
CAD Administrator
Using Inventor 2022
Autodesk Certified Instructor
Autodesk Inventor 2020 Certified Professional
Autodesk AutoCAD 2017 Certified Professional
0 Likes

Michael.Navara
Advisor
Advisor
Accepted solution

This is relatively easy. See the attached sample code files.

 

The main rule looks like

 

AddReference "System.Drawing"
AddVbFile "IC_13026300_Dlg.vb"
Sub Main
	CustomForm.ShowCustomForm(600, 400, "Sample text")
End Sub

 

 

In CustomForm implementaiton is important to create Shared (static C#) method, which creates new instance of CustomForm class and run its ShowDialog method and returns this result to the caller.

 

    Public Shared Function ShowCustomForm(width As Integer, height As Integer, message As String) As DialogResult

        Dim customForm As New CustomForm
        customForm.Width = width
        customForm.Height = height
        customForm.RichTextBox1.Text = message
        Return customForm.ShowDialog()
    End Function

 

 

Full code is in attachment

 

JBerns
Advisor
Advisor

@Michael.Navara ,

 

Brilliant!! Thank you, Michael!

I hope others will find the benefit of this enhanced 'MsgBox'.

I look forward to using this solution.

Thank you also to @WCrihfield , @g.georgiades , and all who contributed.

 

Regards,

Jerry

-----------------------------------------------------------------------------------------
CAD Administrator
Using Inventor 2022
Autodesk Certified Instructor
Autodesk Inventor 2020 Certified Professional
Autodesk AutoCAD 2017 Certified Professional
0 Likes

WCrihfield
Mentor
Mentor
Accepted solution

Hi @JBerns.  I have another example you can look at and review.  I will attach two text files, one will contain the code for the referenced Class called "RichMsg", while the other will contain the code for another example external iLogic rule that is using that referenced Class.  This just uses the New method of the referenced Class to optionally specify the message, title, width, & height of the dialog.  You can also simply not specify any of the optional inputs in the New routine, and specify them (or change them) later, after the instance has been created, because they are public properties of that Class, and setting their values applies those changes to the dialog.

 

One of the challenging things about creating referenced Classes that you intend to reference from other iLogic rules using AddVbFile is that we do not seem to be able to use the 'AddReference' lines within the header of those external rules.  They will accept the 'Imports' statements, but not the references.  So, I usually include the 'AddReference' lines (and the Imports lines) to the rule I we will be calling the referenced Class to run from.  In the case of my attached example, it was initially complaining about there not being a reference to the 'System.Drawing' resource, where the 'Font' and 'Size' object Types are defined.  I could have simply not included those in my example Class, but I am using them in only two key places.  I am using a 'Size' to limit the minimum size of the Form.  And I am using a 'Font' to customize how the text looks within the RichTextBox.  I simply like 'Arial' Font, and I generally prefer slightly larger than normal font in some situations.  But you can change that if wanted.

 

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes

JBerns
Advisor
Advisor

@WCrihfield,

 

Another brilliant solution! Thank you, Wes!

This community is awesome.

-----------------------------------------------------------------------------------------
CAD Administrator
Using Inventor 2022
Autodesk Certified Instructor
Autodesk Inventor 2020 Certified Professional
Autodesk AutoCAD 2017 Certified Professional
0 Likes