dotNet.addEventHandler

Become a member of the CGSociety

Connect, Share, and Learn with our Large Growing CG Art Community. It's Free!

 
Thread Tools Display Modes
  1 Week Ago
dotNet.addEventHandler

Trying to update my script to work in max 2019.
It was working fine in Max2016 where I added an event within a struct to a button within a group defined in the struct...but 2019 now has this documention:

"NOTE:You can only add functions that are registered in the global scope as event handlers. If you need to register a function that is hidden from the global scop (for example, contained in a struct), you need to define a global function to point to the hidden function."
which is new in 2018 :(
so I create a member function in a struct,
the struct is part of a rollout
it creates a button which attaches an event handler which executes the member function...
this is what I am kind of doing.
MasterValue = rollout ThisRollout "" width:200
(
   local MyForm
   struct MyStruct =
   (
      PUBLIC
      sName,
      function dunny = (print "nothing"),
      function CreateGui
      (
         MyButton = dotnetObject "button"
         MyForm.controls.add MyButton
         global gdunny = this.dunny -- added this line to try and make events in the struct global
         dotnet.addEventHander MyButton "click" gdunny
      ),
      on create do
      (
         CreateGui()
      )
   )
   function CreateWinform =
   (
      MyForm = dotNetObject "MaxCustomControls.MaxForm"
      MyForm.showmodeless()
   )
   button Maxbutton ""
   holderforstruct = #()
   on Maxbutton pressed do
   (
      MyForm = CreateWinform()
      holderforstruct= MyStruct sName:"YANstruct"
   )
)

The code doesn't actually work, the only additional lines I have put in to is the line "global gdunny = this.dunny" to essentiallymake a global variable and assign it to a function. I can execute the function from the listener, but the dotnet button refuses to do much at all.
 
  1 Week Ago
in 2019,The event must be a global function
But there are some syntax error in your code
 
  1 Week Ago
Quite a few ways around that while keeping the function inside the struct, for example:

masterValue = rollout thisRollout "" width:200
(
 struct myStruct
 (
  name,
  form,
  fn dunny = print name,
  fn createGui =
  (
   ::myButton = dotNetObject "Button"
   myButton.FlatStyle = myButton.FlatStyle.Flat
   myButton.Text = name

   form.Controls.Add myButton
  ),
  on create do createGui()
 )
 fn createWinform =
 (
  myForm = dotNetObject "MaxCustomControls.MaxForm"
  myForm.showModeless()
  return myForm
 )

 button maxButton "Show Form"
 
 on maxButton pressed do
 (
  myForm = createWinform()
  ::holderForStruct = myStruct name:"YANstruct" form:myForm
  dotNet.addEventHandler myButton "Click" (fn _ = ::holderForStruct.dunny())
 )
)
createDialog masterValue
__________________
Scripts :: linkedin
 
  6 Days Ago
Thanks for responding, and great to hear from you after so many years.
Thanks also for fixing my mockup of code such that it actually works.
my code that i wrote that mock template from generates multiple group objects in a maxform and cascades them down the page as more maxobjects are added to the scene. It also deletes each instance of the window and the object if the window is closed or the individual object interface is closed. So I use multiple instances of the struct, and let the user remove them and add them back in etc. So each event is tied to a particular window which is a struct.
So as I don't know how many windows/objects/events will need to be present, and they need to know which window to update with the particular maxform button press, I generate a unique handler for each window/struct/object.
I understood your solution until this line:
dotNet.addEventHandler myButton "Click" (fn _ = ::holderForStruct.dunny())

i've never seen the syntax:
 fn _ = ::holderForStruct.dunny()

I know the "::" makes the variable global, but I don't know how "fn _ =" works?
your code makes the button global, and the struct global, and the event handler global. I can't seem to figure out how to adapt this to a situation where there are multiple unique instances of structs spawned and each has to have a global event - wanted to avoid creating lots of global stuff which why I used a struct in the first place.
It was all working so well in max2016, max2017. I never even installed 2018, but jumped straight to 2019. I will try to modify your code more to adapt it. I'll post up here if I succeed.

Last edited by RajDarge : 6 Days Ago at 10:49 PM.
 
  6 Days Ago
Instead of a holder of one variable, hold an array of variables in that case, something along the lines of:

masterValue = rollout thisRollout "" width:200
(
   global buttonHolders = #()
   struct myStruct
   (
      index,
      form,
      button,
      fn dunny = print index,
      fn createGui =
      (
         button = dotNetObject "Button"
         button.FlatStyle = button.FlatStyle.Flat
         button.Bounds = dotNetObject "System.Drawing.Rectangle" (30 * mod index 10) 10 25 25
         button.Text = index as string
         form.Controls.Add button
      ),
      on create do createGui()
   )
   fn createWinform =
   (
      local myForm = dotNetObject "MaxCustomControls.MaxForm"
      myForm.showModeless()
      return myForm
   )
   button maxButton "Show Form"
   on maxButton pressed do
   (
      localmyForm = createWinform()
      
      for i = 1 to 5 do
      (
         local holder = myStruct index:i form:myForm
         append buttonHolders holder
         dotNet.addEventHandler holder.button "Click" (execute ("fn _ = buttonHolders[" + i as string + "].dunny()"))
      )
   )
)
createDialog masterValue


The underscore is just a name of a function wrapping the global function call (the event handler itself is not global btw.)
__________________
Scripts :: linkedin
 
  4 Days Ago
Thanks for that solution, it does work , and I can adapt it to my needs.
It feels like a little bit of a hack - everywhere I use the execute function feels like a bit of a hack .

I copied and pasted your code, and for some reason it decided that there was a scope violation so I think this version it is fixed. Not really sure what I did but it seems to work now (for any following this conversation....)
masterValue = rollout thisRollout "" width:200
(
 global buttonHolders = #()
 struct myStruct
 (
   index,
   form,
   button,
   fn dunny = print index,
   fn createGui =
   (
    button = dotNetObject "Button"
    button.FlatStyle = button.FlatStyle.Flat
    button.Bounds = dotNetObject "System.Drawing.Rectangle" (30 * mod index 10) 10 25 25
    button.Text = index as string
    form.Controls.Add button
   ),
   on create do createGui()
 )
 fn createWinform =
 (
   local myForm = dotNetObject "MaxCustomControls.MaxForm"
   myForm.showModeless()
   return myForm
 )
 button maxButton "Show Form"
 on maxButton pressed do
 (
   local myForm = createWinform()
   for i = 1 to 5 do
   (
    holder = myStruct index:i form:myForm
    append buttonHolders holder
       dotNet.addEventHandler holder.button "Click" (execute ("fn _ = buttonHolders[" + i as string + "].dunny()"))
   )
 )
)
createDialog masterValue



I will try and figure out a more elegant solution - but really any global variable makes me feel a little dirty - thank you autodesk. For the moment I am using Max2016 and importing the scene into max2019 to use its features.

I wonder why they made this change? Probably a whole lot of windows stack problems if and when max crashes leaving a lot of events, without parent buttons and no way to remove them... Still I don't know how this fixes things?

I am still interested in more info on "fn _=" I cannot find any reference to it and what it does and why people use it. Do you have an article, reference ? It seems to be a wild card way of referencing a function. ANyway more documentation of this would be helpful.
Is there any other way of removing a global variable than
globalvars.remove "my_number"

as it seem you have to convert the variable name into a string in order to delete it.

Last edited by RajDarge : 4 Days Ago at 09:12 PM.
 
  4 Days Ago
I did finally work out the correct syntax. But I am trying to use the Sender and eventArgs discussed in the addeventhandler documention
Why are both Sender and eventArgs undefined in this version:
masterValue = rollout thisRollout "" width:200
(
 global buttonHolders = #()
 struct myStruct
 (
   index,
   form,
   button,
   fn dunny Sender eventArgs = (
         print index
         print Sender
         print eventArgs
       ),
   fn createGui =
   (
    button = dotNetObject "Button"
    button.FlatStyle = button.FlatStyle.Flat
    button.Bounds = dotNetObject "System.Drawing.Rectangle" (30 * mod index 10) 10 25 25
    button.Text = index as string
    form.Controls.Add button
   ),
   on create do createGui()
 )
 fn createWinform =
 (
   local myForm = dotNetObject "MaxCustomControls.MaxForm"
   myForm.showModeless()
   return myForm
 )
 button maxButton "Show Form"
 on maxButton pressed do
 (
   local myForm = createWinform()
   for i = 1 to 5 do
   (
    holder = myStruct index:i form:myForm
    append buttonHolders holder
       dotNet.addEventHandler holder.button "Click" (execute ("fn _ = buttonHolders[" + i as string + "].dunny Sender eventArgs"))
   )
 )
)
createDialog masterValue
 
  4 Days Ago
Once again, _ is just a name like any other, no special syntax. fn _ is the same thing as say fn test, it has no arguments so you need to add them if you want to use them.
__________________
Scripts :: linkedin
 
  4 Days Ago
Btw. 2019.1 Update is out now and it's fixed there so you don't have to do it that way anyway.
__________________
Scripts :: linkedin
 
  4 Days Ago
I saw the documentation for the update, not seeing anything about event handlers?
I thought that when an event triggered it automtically parsed sender and eventargs to the custom max function (if it took args) so that you could figure out which button caused the event and if it was a single, double, middle or right click.
I got it working how passing args as expected:
masterValue = rollout thisRollout "" width:200
(
 global buttonHolders = #()
 struct myStruct
 (
   index,
   form,
   button,
   fn dunny sender eventArgs = (
    print index
    print Sender
    print eventArgs
    ),
   fn createGui =
   (
    button = dotNetObject "Button"
    button.FlatStyle = button.FlatStyle.Flat
    button.Bounds = dotNetObject "System.Drawing.Rectangle" (30 * mod index 10) 10 25 25
    button.Text = index as string
    form.Controls.Add button
   ),
   on create do createGui()
 )
 fn createWinform =
 (
   local myForm = dotNetObject "MaxCustomControls.MaxForm"
   myForm.showModeless()
   return myForm
 )
 button maxButton "Show Form"
 on maxButton pressed do
 (
 local myForm = createWinform()
   for i = 1 to 5 do
   (
    holder = myStruct index:i form:myForm
    append buttonHolders holder
       dotNet.addEventHandler holder.button "MouseClick" (execute ("fn _ a b = buttonHolders[" + i as string + "].dunny a b"))
   )
 )
)
createDialog masterValue

thanks for all your help. I have a script that checks the MaxVer (an undocumented Global Var) before executing the conditional code.
It seems a hell of a lot more logical to just allow a function which is not global ... so I can set the event handler within the struct without utilizing that "execute 'string'" is always in the global scope.
thanks again. Back to the grindstone.

Last edited by RajDarge : 4 Days Ago at 10:16 AM.
 
  4 Days Ago
MaxVer is likely a global variable introduced by one of the scripts you are using, it's definitely undefined on my end. Might be more reliable to use the maxVersion output.
All I know is that I'm using update 1 and the issue seems to be fixed there, no idea what the ID of the fix is though.
__________________
Scripts :: linkedin
 
  3 Days Ago
I think it might be Vray or Phoenix FD that is registering it as they are the only plugins that I have installed as yet.. I will take your advice and use MaxVersion() though.
I could see no documentation regarding the change to having global functions for event handlers, but I loaded an unmodified script for 2016 in 2019.1 and it worked perfectly.
What gives?
Still now I know of the problem I will still have to have conditional code based on (maxversion())[1] < 21000 and(maxversion())[1] > 19000 - except I wont ever be able to test it now as I never installed 2018... and max2019 has been upraded....
oh well. If I ever release my script the 2018 users can message me ....
 
reply share thread



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
CGSociety
Society of Digital Artists
www.cgsociety.org

Powered by vBulletin
Copyright 2000 - 2006,
Jelsoft Enterprises Ltd.
Minimize Ads
Forum Jump
Miscellaneous

All times are GMT. The time now is 05:38 PM.


Powered by vBulletin
Copyright ©2000 - 2018, Jelsoft Enterprises Ltd.