Cocoa: How to get app to fire mouseDown on _any_ part of window?

Discussion in 'Mac Programming' started by mpemburn, Jun 16, 2009.

  1. mpemburn macrumors member

    Jan 11, 2008
    Bel Air, MD USA
    Hi All,

    In the app I'm building, I'd like to have a HUD panel pop up over my main user interface when certain conditions occur but I don't want to require the user to click an 'OK' button to dismiss it. Instead, I'd prefer to have the panel disappear when the user clicks anywhere within the app. If I put the "orderOut" code within a mouseDown event, it only fires when I click in the narrow blank areas around the controls, since most of the area is covered by a split panel and an ImageView. Is there any way to tell the other controls to pass the mouse click along to the underlying window -- or perhaps just interpret the next mouse click as a 'dismiss' command?

    BTW -- I'm also having a little trouble with closing the HUD panel with the "X" close button: The first time the panel comes up, I can close it with the "X" but the second time the "X" does nothing.


    P.S. Please don't hesitate to tell me if this is a dumb approach and not the "Mac Way". I've used interface devices like this in other contexts and rather like them but I'll accepted other suggestions.
  2. HiRez macrumors 603


    Jan 6, 2004
    Western US
    You could maybe put up an invisible (fully transparent) child window over your main window (or HUD panel) which tracks and duplicates its frame and position, and have it intercept mouse events.
  3. mpemburn thread starter macrumors member

    Jan 11, 2008
    Bel Air, MD USA
    Thanks HiRez.

    Actually, not too long after I posted, a similar thought occurred to me. I use the technique of graying out the window in some of my browser-based apps so if I can do what you suggest and make the child window semi-transparent, it'd serve nicely. Then, instead of a HUD panel, I could center my message on the window in a text control. Hmmm. Much simpler. Gonna try it!

    -- Mark
  4. jared_kipe macrumors 68030


    Dec 8, 2003
    In UIKit this is very easy, you just make a button that covers the whole screen. Make it "custom" so it has no appearance, and then drag it to the background in the hierarchal viewer. Or choose menu option "Send to Back".

    I haven't written much of anything in Cocoa, I much prefer UIKit, but hopefully there is a similar technique.
  5. mpemburn thread starter macrumors member

    Jan 11, 2008
    Bel Air, MD USA
    Okay -- I've achieved what I intended (or close enough). Here's how:

    1. Add an outlet to the controller class:
    IBOutlet NSButton * btnGrayedOut;
    2. Add a Square Button to your window and connect it to the outlet. You should also go into the Button Size tab on the Inspector and click all of the arrows in the "Autosizing" section so that it sizes in all dimensions.

    3. Add an action to the controller and connect it to the button as well:
    - (IBAction)ClickedGrayedOutButton:(id)sender;
    4. Add a "GrayOut" method to do the work of sizing and displaying the button:
    - (void)GrayOut: (NSString *) message; {
    	NSRect frame;
    	float fadeIn;
    	//*** Get the frame rectangle of the main window
    	frame = [[self window] frame];
    	//*** Expand the button to cover the entire area of the window
    	[btnGrayedOut setFrame: NSMakeRect(0, 0, frame.size.width, frame.size.height)];
    	//*** Set title text and show
    	[btnGrayedOut setTitle: message];
    	[btnGrayedOut setHidden: NO];
    	//*** Make it fade in
    	for (fadeIn=0.0; fadeIn<0.6; fadeIn+=.02) {
    		[btnGrayedOut setAlphaValue: fadeIn];
    		[btnGrayedOut display];
    - (IBAction)ClickedGrayedOutButton:(id)sender; {
    	[btnGrayedOut setHidden: YES];
    Now, when you call "GrayOut" . . .

    [self GrayOut: @"NO DOCUMENT ON SCANNER"];
    . . . the button will fade in and cover the entire window with the text you specify in the center. If the user clicks anywhere on the window, it'll dismiss the message.


    -- Mark
  6. john1620b macrumors member

    Apr 29, 2009
    Nice solution! Thanks for sharing the code, I'm sure it'll come in handy some day.
  7. kainjow Moderator emeritus


    Jun 15, 2000
    Another possible solution would be to use [NSWindow nextEventMatchingMask:untilDate:inMode:dequeue:] with NSLeftMouseDownMask to wait until the next mouse click event.

Share This Page