Nsdatepicker in Nsstatusbar Nssmenuitem Not Receiving Input

NSDatePicker in NSStatusBar NSSMenuItem not receiving input

Your NSDatePicker needs to return "acceptsFirstMouse" as true, which is readonly, so you'll to do that in a subclass.

Works in a test project running the code you supplied.

refresh NSMenuItem on click/open of NSStatusItem

Keep a reference to the created NSMenuItem in your app delegate and update its state (assuming you use the item only in a single menu).

class AppDelegate: NSApplicationDelegate {

var fooMenuItem: NSMenuItem?

}

func createStatusBarItem() {
...
let enableDisableMenuItem = NSMenuItem(title: "Enabled", action: #selector(toggleAdvancedMouseHandlingObjc), keyEquivalent: "e")
self.fooMenuItem = enableDisableMenuItem
...
}

@objc func toggleAdvancedMouseHandlingObjc() {
if sHandler.isAdvancedMouseHandlingEnabled() {
sHandler.disableAdvancedMouseHandling()
} else {
sHandler.enableAdvancedMouseHandling()
}

self.fooMenuItem.state = sHandler.isAdvancedMouseHandlingEnabled() ? NSControl.StateValue.on : NSControl.StateValue.off
}

Listen for Actions on a NSStatusItem With a Menu

This solution came from a previous SO question:Highlighting NSStatusItem with attributed string
and may do what you want. Unfortunately, popUpStatusItemMenu is now deprecated.

#import <Cocoa/Cocoa.h>

@interface AppDelegate : NSObject <NSApplicationDelegate> {
NSStatusItem* statusItem;
NSMenu* statusMenu;
NSMenuItem* menuItem;
}
-(void)statusItemHandler:(id)sender;
-(void)menuHandler:(id)sender;
@end

@implementation AppDelegate

-(void)menuHandler:(id)sender {
NSLog(@"Menu item = %@",sender);
}

-(void)statusItemHandler:(id)sender {
NSLog(@"StatusItem hit.");
statusMenu = [[NSMenu alloc] init];
menuItem = [statusMenu addItemWithTitle: @"Item 1" action:@selector(menuHandler:) keyEquivalent:@""];
menuItem = [statusMenu addItemWithTitle: @"Item 2" action:@selector(menuHandler:) keyEquivalent:@""];
[statusMenu addItem:[NSMenuItem separatorItem]];
menuItem = [statusMenu addItemWithTitle:@"Quit" action:@selector(terminate:) keyEquivalent:@""];
[statusItem popUpStatusItemMenu:statusMenu];
}

-(void)applicationDidFinishLaunching:(NSNotification *)notification {
statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength];
statusItem.button.title = @"\U0001F410";
statusItem.button.action = @selector(statusItemHandler:);
}

@end

int main(){
NSApplication *application = [NSApplication sharedApplication];
[application setActivationPolicy:NSApplicationActivationPolicyRegular];
AppDelegate *appDelegate = [[AppDelegate alloc] init];
[application setDelegate:appDelegate];
[application activateIgnoringOtherApps:YES];
[application run];
return 0;
}

NSStatusItem shows only up if it is defined outside of my method

Because if you only declare the object inside the method and don't keep a reference to it elsewhere it will be scoped to the method. When the method finishes execution your object will be released and go away.
If you want it to live as long as the app runs, you would want to assign it to a property of the app delegate or another object that is going to live as long as the app.

CGEventTap + NSStatusItem problems

The third argument of the function should be 1, was still 0 in the actual code. If its 1 then its a Listen CGEventTap and thus cannot modify or filter the event.

This also fixes an issue the event tap could have together with the game Minecraft. So if your CGEventTap only needs to listen and not filter make sure that that argument is set to 0x1 or 1

Menu in system status bar is disabled

Menu validation does not find any implementor of specified action in responder chain so disable it. You have to specify target for each menu item:

    let item = menu.addItem(
withTitle: "Order a burrito",
action: #selector(StatusBarFactory.x(_:)),
keyEquivalent: "A")
item.target = _instance_of_StatusBarFactory_here // like StatusBarFactory.shared

Force NSStatusItem to Redraw

As provided by Willeke in the comments, the solution is to use the needsDisplay property. The working function is:

-(void)buttonPressed {
[[[statusItem button] image] setTemplate: false];
[[statusItem button] setNeedsDisplay: true];
}


Related Topics



Leave a reply



Submit