[Closed] dotNet.addEventHandler cannot access struct members?
I鈥檝e got a little problem when using dotNet.addEventHandler within a struct.
For example, I have a function in a struct which creates a System.IO.FileSystemWatcher object. I add an eventhandler to that object, which is a function in the same struct.
This function is called, no problem so far.
However, if I want to do anything with the struct members, that鈥檚 when things fail:
>> MAXScript dotNet event handler Exception: 鈥?Runtime error: Struct member access requires instance: kbd_actions <<
in this case kbd_actions is just a member of the same struct in which the handler is defined (and yes it is defined prior to the handler). When I explicitly point to the instance when adding the handler (which is bad to begin with) the handler isn鈥檛 even executed when the event is fired鈥?/p>
I wonder, is the handler actually operating in global scope or something? What鈥檚 going on here? And more importantly, how do I overcome this?
i don鈥檛 see a problem:
struct formHolder
(
form,
size = [200,270],
pos = [900,150],
title = "The Form",
fn open = (if iskindof form dotnetobject do form.Showmodeless()),
fn close = (if iskindof form dotnetobject do form.Close()),
fn onShown s a =
(
print (s.WindowState.toString())
),
fn onMove s a =
(
print (s.Location.toString())
),
on create do
(
form = dotNetObject "MaxCustomControls.MaxForm"
form.size = dotNetObject "System.Drawing.Size" size.x size.y
form.Location = dotNetObject "System.Drawing.Point" pos.x pos.y
form.StartPosition = form.StartPosition.Manual
form.text = title
dotnet.addEventHandler form "Shown" onShown
dotnet.addEventHandler form "Move" onMove
)
)
w = formHolder()
w.open()
I鈥檓 not looking for properties/functions of the sender. But I want to access properties or functions in the struct in which the handler is defined.
In your example, try to print pos or size in onShown, you鈥檒l get an exception.
slight modification:
struct formHolder
(
form,
size = [200,270],
pos = [900,150],
title = "The Form",
fn open = (if iskindof form dotnetobject do form.Showmodeless()),
fn close = (if iskindof form dotnetobject do form.Close()),
fn onShown s a =
(
format "%
" (s.WindowState.toString())
),
fn onMove s a =
(
format "default:% %
" s.tag.value.pos (s.Location.toString())
),
on create do
(
form = dotNetObject "MaxCustomControls.MaxForm"
form.tag = dotnetmxsvalue this
form.size = dotNetObject "System.Drawing.Size" size.x size.y
form.Location = dotNetObject "System.Drawing.Point" pos.x pos.y
form.StartPosition = form.StartPosition.Manual
form.text = title
dotnet.addEventHandler form "Shown" onShown
dotnet.addEventHandler form "Move" onMove
)
)
w = formHolder()
w.open()
Yep, I had thought of the Tag property too, to send the instance along with the sender.
However, not all .NET classes have a Tag property, only in the System.Windows.Forms namespace. The FileSystemWatcher for example doesn鈥檛鈥?/p>
Yes alright, that is a solution. But to be honest, I don鈥檛 find it very pretty鈥?br>
You鈥檇 need a dll file just for that. So if there鈥檚 a better and more maintainable way, I鈥檇 be very interested.
as usually:
fn createFileSystemWatcher =
(
source = ""
source += "using System;
"
source += "using System.IO;
"
source += "namespace MXS
"
source += "{
"
source += " public class FileWatcher: FileSystemWatcher { public Object Tag; }
"
source += "}
"
csharpProvider = dotnetobject "Microsoft.CSharp.CSharpCodeProvider"
compilerParams = dotnetobject "System.CodeDom.Compiler.CompilerParameters"
-- compilerParams.CompilerOptions = "-unsafe"
compilerParams.ReferencedAssemblies.Add("System.dll");
compilerParams.GenerateInMemory = on
compilerResults = csharpProvider.CompileAssemblyFromSource compilerParams #(source)
compilerResults.CompiledAssembly.CreateInstance "MXS.FileWatcher"
)
global FileWatcherObject = createFileSystemWatcher()
Hm that鈥檚 interesting. Still not extremely portable and imo still a hack, but much better already.
Any idea why this behavior is occurring in the first place by the way?
why is it not portable and a hack? it鈥檚 the nature of .net . it鈥檚 the assembly as any other.
It鈥檚 having to create a new class just to fix a problem that is totally unrelated to it. The problem isn鈥檛 with the FileSystemWatcher class, not even .NET, but with the maxscript wrapper for as far as I can see.
If this is the only way around it, then so be it, but you鈥檒l have to agree with me that it isn鈥檛 pretty
Thanks for your help.
unfortunately I can鈥檛 wait when max developers fix all bugs. Developing for Max has always been a hack for me. That is the nature of MAX
I filed this bug several months ago. If I am not wrong, it鈥檚 the same problem.
So what I did was this:
(
local MPEventHandler
struct MyPanel
(
fn EventHandler sender e = (),
fn AddEventHandlers pState =
DotNet.AddEventHandler MyPanelForm "Activated" MPEventHandler
)
local MP = MyPanel()
fn MPEventHandler sender e = MP.EventHandler sender e
)
Let me know if this is the same problem. (:
Light
Lately, I鈥檝e taken to adding a instance to the global namespace with whenever I create a singleton-like struct. I make sure to use the 鈥?:鈥?prefix in the struct definition so that I always know I am referring to a global.
Lipstick on a pig.
struct formHolderDef
(
form,
size = [200,270],
pos = [900,150],
title = "The Form",
fn open = (if iskindof form dotnetobject do form.Showmodeless()),
fn close = (if iskindof form dotnetobject do form.Close()),
fn onShown s a =
(
print (s.WindowState.toString())
),
fn onMove s a =
(
print (s.Location.toString())
print ::formHolder.size
print ::formHolder.pos
),
fn init =
(
form = dotNetObject "MaxCustomControls.MaxForm"
form.size = dotNetObject "System.Drawing.Size" size.x size.y
form.Location = dotNetObject "System.Drawing.Point" pos.x pos.y
form.StartPosition = form.StartPosition.Manual
form.text = title
dotnet.addEventHandler form "Shown" onShown
dotnet.addEventHandler form "Move" onMove
),
initialized = init()
)
::formHolder = formHolderDef()
::formHolder.open()
In fact, it never should. All it should know about is what happens inside itself
It should not look at its own properties or functions through a reference from outside.