3

I have created a custom NSView that i would like to place over the top of the content of a window to block any interaction while all the content is loading. The problem i was having is that i could click through the NSView to the controls below though that has now been fixed. The new problem is that even though i cannot click on the controls, when i move the mouse over text controls, the mouse switches to the I Beam icon.

How do i make the NSView completely block all interaction with everything below it?

The NSView i created is below:

[Register("StupidView")]
public class StupidView : NSView
{


    public StupidView()
    {
        // Init
        Initialize();
    }

    public StupidView(IntPtr handle) : base (handle)
    {
        // Init
        Initialize();
    }

    [Export("initWithFrame:")]
    public StupidView(CGRect frameRect) : base(frameRect) {
        // Init
        Initialize();
    }

    private void Initialize()
    {
        this.AcceptsTouchEvents = true;
        this.WantsLayer = true;
        this.LayerContentsRedrawPolicy = NSViewLayerContentsRedrawPolicy.OnSetNeedsDisplay;
    }

    public override void DrawRect(CGRect dirtyRect)
    {
        var ctx = NSGraphicsContext.CurrentContext.GraphicsPort;
        ctx.SetFillColor(new CGColor(128, 128, 128, 0.7f));
        ctx.FillRect(dirtyRect);
    }

    public override void MouseDown(NSEvent theEvent)
    {
        if (Hidden)
        {
            base.MouseDown(theEvent);
        }
    }

    public override void MouseDragged(NSEvent theEvent)
    {

        if (Hidden)
        {
            base.MouseDragged(theEvent);
        }
    }

    public override bool AcceptsFirstResponder()
    {
        return !this.Hidden;
    }

    public override bool AcceptsFirstMouse(NSEvent theEvent)
    {
        return !this.Hidden;
    }

    public override NSView HitTest(CGPoint aPoint)
    {
        return Hidden ? null : this;
    }
}
bizzehdee
  • 20,289
  • 11
  • 46
  • 76

1 Answers1

2

I had the same problem a few weeks ago, and here is how I could manage this :

First, to prevent user interactions on the superview placed below, I added a transparent button which was there only to catch the mouse click and, if you don't have to do anything, do nothing :

 private void Initialize()
 {
    this.AcceptsTouchEvents = true;
    this.WantsLayer = true;
    this.LayerContentsRedrawPolicy = NSViewLayerContentsRedrawPolicy.OnSetNeedsDisplay;

    //Add button to prevent user interactions 

    NSButton buttonToPreventUserInteraction = new NSButton();
    buttonToPreventUserInteraction.Bordered = false;
    buttonToPreventUserInteraction.Transparent = true;
    buttonToPreventUserInteraction.TranslatesAutoresizingMaskIntoConstraints = false;
    AddSubview(buttonToPreventUserInteraction);

    //If you want to add some constraints on the button, for it to resize and keep the same size of your subview

    var dicoViews = new NSMutableDictionary();
    dicoViews.Add((NSString)"buttonToPreventUserInteraction", buttonToPreventUserInteraction);
    NSLayoutConstraint[] buttonToPreventUserInteractionHorizontalConstraints = NSLayoutConstraint.FromVisualFormat("H:|[buttonToPreventUserInteraction]|", NSLayoutFormatOptions.DirectionLeadingToTrailing, null, dicoViews);
    NSLayoutConstraint[] buttonToPreventUserInteractionVerticalConstraints = NSLayoutConstraint.FromVisualFormat("V:|[buttonToPreventUserInteraction]|", NSLayoutFormatOptions.DirectionLeadingToTrailing, null, dicoViews);
    AddConstraints(buttonToPreventUserInteractionHorizontalConstraints);
    AddConstraints(buttonToPreventUserInteractionVerticalConstraints);

 }

For your other problem, which is the mouse cursor changing from the content in your superview placed below, you can add a NSTrackingArea on your subview, and implement the override method "MouseMoved" to change the cursor. You can do something like this :

First Add the NSTrackingArea on your subview (you can put this code in your "Initialize" method)

NSTrackingAreaOptions opts = ((NSTrackingAreaOptions.MouseMoved | NSTrackingAreaOptions.ActiveInKeyWindow | NSTrackingAreaOptions.InVisibleRect));
var trackingArea = new NSTrackingArea(new CGRect(0, 0, FittingSize.Width, FittingSize.Height), opts, Self, null);

AddTrackingArea(trackingArea);

And then implement the override method :

public override void MouseMoved(NSEvent theEvent)
{
    //You can choose the type of cursor you want to use here
    NSCursor.ArrowCursor.Set();
}

This made it for me, hope it will for you too

Hikaiix
  • 70
  • 9