Search code examples
c#xamarinmononswindowmonomac

How to capture mouse events in C# MonoMac


First off all, my goal is to create pragmatically (no controllers or such things, just single class) borderless NSWindow. In this window I'd like to track mouse events, like: Mouse down, mouse move. As simple as that.

I need to do this in C# using Xamarin Studio in Monomac project. My window is super-simple

public class MyWindow : NSWindow
{
    public MyWindow()
        :base(new RectangleF (0, 0, 100, 100), 
            NSWindowStyle.Closable | NSWindowStyle.Resizable | NSWindowStyle.Titled, NSBackingStore.Buffered, 
            false)
    {
        this.StyleMask = NSWindowStyle.Borderless;
        this.MakeKeyAndOrderFront( null );
    }
}

Now, as far as I know I should add NSView to this NSWindow class with declared events. So I created NSView class:

public class MouseTracking : NSView
{
    public NSTrackingArea tracking;

    public override bool AcceptsFirstResponder ()
    {
        return true;
    }

    public override void DrawRect(RectangleF dirtyRect)
    {
        base.DrawRect(dirtyRect);
        var context = NSGraphicsContext.CurrentContext.GraphicsPort;
        var rectangle = new RectangleF (0,0, this.Frame.Width, this.Frame.Height);
        NSColor.Blue.Set ();
        context.FillRect (rectangle);
    }

    public override void UpdateTrackingAreas()
    {
        if (tracking != null)
        {
            this.RemoveTrackingArea(tracking);
            tracking.Release();
        }
        tracking = new NSTrackingArea(this.Frame,NSTrackingAreaOptions.MouseEnteredAndExited | NSTrackingAreaOptions.ActiveAlways ,this, null);
        this.AddTrackingArea(tracking);
    }

    public override void MouseMoved(NSEvent theEvent)
    {
        Console.WriteLine("MouseMoved");
    }

    public override void MouseExited(NSEvent theEvent)
    {
        Console.WriteLine("MouseExitedTest");
    }
}

My question is how to add MouseTracking nsview to MyWindow and make those mouse events available? I've tried in MyWindow constructor do:

        MouseTracking tracking = new MouseTracking ();
        this.ContentView.AddSubview (tracking);

but, that doesn't work.. I just want to do this (two lines in WinForms):

this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.panel1_MouseDown);

private void panel1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e) { }

Thanks, for help


Solution

  • You don’t need DrawRect to capture mouse events. You need contructors:

        public MouseTracking(NSCoder coder)
            :base(coder)
        {
        }
    
        public MouseTracking(RectangleF frameRect)
            :base(frameRect)
        {
        }
    

    You could also need (maybe you don’t know this yet) to override this flag:

        public override bool AcceptsFirstMouse (NSEvent theEvent)
        {
            return true;
        }
    

    and yes, you add MouseTracking to MyWindow exactly like you wrote, so:

        this.ContentView.AddSubview (tracking);