2012-06-26 19 views
6

दबाकर एप्लिकेशन के मुख्य मेनू में मेनू आइटम को छुपाएं/दिखाएं मैं एप्लिकेशन के मुख्य मेनू में मेनू आइटम जोड़ना चाहता हूं जिसका उपयोग बहुत दुर्लभ होगा। मैं इसे डिफ़ॉल्ट रूप से छिपाना चाहता हूं और केवल तभी दिखाता हूं जब उपयोगकर्ता विकल्प कुंजी दबाए रखें। मैं यह कैसे करु?विकल्प कुंजी

ऐसा लगता है कि मैं flagsChanged: संभाल चाहिए, लेकिन यह NSResponder की विधि है और NSMenuNSResponder से विरासत नहीं करता है? मैंने इसे मुख्य विंडो नियंत्रक के अंदर करने की कोशिश की, और जब मैं मेनू पर क्लिक करने से पहले विकल्प कुंजी दबाता हूं तो यह काम करता है। निम्नलिखित उपयोग केस काम नहीं करते हैं: मेनू आइटम पर क्लिक करें (कोई आइटम नहीं है), विकल्प कुंजी दबाएं - मेरा आइटम दिखाना चाहिए, विकल्प कुंजी जारी करें - आइटम गायब होना चाहिए।

मैं भी NSEvent के addLocalMonitorForEventsMatchingMask:handler: और NSFlagsChangedMask के लिए addGlobalMonitorForEventsMatchingMask:handler: की कोशिश की है, लेकिन विकल्प कुंजी दबाया जब जबकि मुख्य मेनू खुला न स्थानीय है या वैश्विक संचालकों निकाल दिया नहीं कर रहे हैं।

मैं यह कैसे कर सकता हूं?

उत्तर

5

आवेदन के लिए निम्नलिखित जोड़ें DidFinishLaunching। जबकि नियंत्रण ट्रैक किए जा रहे है, तो यह एक प्रदर्शन हिट की बहुत अधिक नहीं है

// Dynamically update QCServer menu when option key is pressed 
NSMenu *submenu = [[[NSApp mainMenu] itemWithTitle:@"QCServer"] submenu];  
NSTimer *t = [NSTimer timerWithTimeInterval:0.1 target:self selector:@selector(updateMenu:) userInfo:submenu repeats:YES]; 
[[NSRunLoop currentRunLoop] addTimer:t forMode:NSEventTrackingRunLoopMode]; 

तो

- (void)updateMenu:(NSTimer *)t { 

    static NSMenuItem *menuItem = nil; 
    static BOOL isShowing = YES; 

    // Get global modifier key flag, [[NSApp currentEvent] modifierFlags] doesn't update while menus are down 
    CGEventRef event = CGEventCreate (NULL); 
    CGEventFlags flags = CGEventGetFlags (event); 
    BOOL optionKeyIsPressed = (flags & kCGEventFlagMaskAlternate) == kCGEventFlagMaskAlternate; 
    CFRelease(event); 

    NSMenu *menu = [t userInfo]; 

    if (!menuItem) { 
     // View Batch Jobs... 
     menuItem = [menu itemAtIndex:6]; 
     [menuItem retain]; 
    } 

    if (!isShowing && optionKeyIsPressed) { 
     [menu insertItem:menuItem atIndex:6]; 
     [menuItem setEnabled:YES]; 
     isShowing = YES; 
    } else if (isShowing && !optionKeyIsPressed) { 
     [menu removeItem:menuItem]; 
     isShowing = NO; 
    } 

    NSLog(@"optionKeyIsPressed %d", optionKeyIsPressed); 
} 

टाइमर केवल आग जोड़ें।

+0

मेरे पास अभी कोशिश करने का समय था और यह काम करता है। आपका बहुत बहुत धन्यवाद! –

9

मेनू बनाने के दौरान वैकल्पिक आइटम शामिल है और इसे छुपा के रूप में चिह्नित करें। फिर मेनू के प्रतिनिधि के रूप में अपना क्लास इंस्टेंस सेट करें और वैकल्पिक लूप ऑब्जेक्टर जोड़ें जबकि मेनू वैकल्पिक आइटम के छिपे हुए राज्य को नियंत्रित करने के लिए खुला है।

@implementation AppController { 
    CFRunLoopObserverRef _menuObserver; 
} 

- (void)updateMenu { 
    BOOL hideOptionalMenuItems = ([NSEvent modifierFlags] & NSAlternateKeyMask) != NSAlternateKeyMask; 
    [self.optionalMenuItem setHidden:hideOptionalMenuItems]; 
} 

- (void)menuWillOpen:(NSMenu *)menu { 
    [self updateMenu]; 

    if (_menuObserver == NULL) { 
     _menuObserver = CFRunLoopObserverCreateWithHandler(NULL, kCFRunLoopBeforeWaiting, true, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) { 
      [self updateMenu]; 
     }); 

     CFRunLoopAddObserver(CFRunLoopGetCurrent(), _menuObserver, kCFRunLoopCommonModes); 
    } 
} 

- (void)menuDidClose:(NSMenu *)menu { 
    if (_menuObserver != NULL) { 
     CFRunLoopObserverInvalidate(_menuObserver); 
     CFRelease(_menuObserver); 
     _menuObserver = NULL; 
    } 
} 
+0

यह एक बेहतर समाधान प्रतीत होता है, मैं इसे थोड़ी देर बाद कोशिश करूंगा। धन्यवाद। –

+0

यह एक चैंप की तरह काम किया। – dbainbridge

+1

यहां पर सावधान। मैंने अभी यह कोशिश की और ध्यान दिया कि जब आप मेनू में होते हैं और अन्य मेनू खोलने के लिए मेनू बार में अपने माउस को ले जाते हैं, तो मेनू नेड्स अपडेट: हमेशा कॉल नहीं किया जाता है (यदि मेनू पहले खुलता था), जिससे दुर्घटना हो जाती है। 'मेनूWillOpen: 'के बजाय' menuWillOpen: 'का उपयोग करें: – Mark

1

NSMenuDelegate विधि menuNeedsUpdate: के बाद से प्रदर्शन से पहले कहा जाता है, यह इसे ओवरराइड, देखें कि क्या [NSEvent modifierFlags] वैकल्पिक बिट सेट है, और का उपयोग करें कि दिखाने/अपने गुप्त मेनू आइटम को छिपाने के लिए संभव है।

यहाँ एक उदाहरण है, Reveal Functionality with Key Modifiers से नकल है, जो वास्तव में इस विषय को शामिल किया गया:

#pragma NSMenu delegate methods 

- (void) menuNeedsUpdate: (NSMenu *)menu 
{ 
    NSLog(@"menuNeedsUpdate: %@", menu); 

    NSUInteger flags = ([NSEvent modifierFlags] & NSDeviceIndependentModifierFlagsMask); 

    // We negate the value below because, if flags == NSAlternateKeyMask is TRUE, that 
    // means the user has the Option key held, and wants to see the secret menu, so we 
    // need shoudHideSecretMenu to be FALSE, so we just negate the value. 
    BOOL shoudHideSecretMenu = !(flags == NSAlternateKeyMask); 

    NSLog(@"Flags: 0x%lx (0x%x), shoudHideSecretMenu = %d", flags, NSAlternateKeyMask, shoudHideSecretMenu); 

    [secretMenuItem setHidden:shoudHideSecretMenu]; 
} 
+0

मैंने कोशिश नहीं की, लेकिन ऐसा लगता है कि यह विधि केवल मेनू मेनू आइटम को दिखाएगी यदि सीएमडी कुंजी मेनू खोलने से पहले दबाया गया हो। लेकिन मैं मेनू मेनू अभी भी खुला होने पर cmd कुंजी दबाकर/जारी करके इस मेनू आइटम को दिखाना/छिपाना चाहता हूं। –

10

सबसे अच्छा तरीका है आप प्राप्त कर सकते हैं यह दो मेनू आइटम का उपयोग करना है, पहली मेनू आइटम ऊंचाई 0 से कस्टम दृश्य का उपयोग करता है , और अक्षम है, फिर इसके नीचे एक "वैकल्पिक" आइटम है। (आपको इस आइटम का keyEquivalentModifierMaskNSAlternateKeyMask पर सेट करना होगा) इस व्यवस्था के साथ, जब आप विकल्प कुंजी दबाते हैं, तो एनएसएमएनयू स्वचालित रूप से शून्य-ऊंचाई मेनू आइटम को वैकल्पिक आइटम के साथ प्रतिस्थापित कर देगा जो मेनू आइटम को जादुई रूप से प्रकट करने का प्रभाव रखेगा।

टाइमर, अपडेट या ध्वज परिवर्तन अधिसूचनाओं की कोई आवश्यकता नहीं है।

यह कार्यक्षमता प्रलेखन यहाँ में वर्णित है: Managing Alternates

+0

"ऊंचाई 0 के कस्टम दृश्य का उपयोग करता है, और अक्षम है" - एक उदाहरण अच्छा होगा। – frakman1

+0

कोई कस्टम दृश्य उपयोग करने की आवश्यकता नहीं है। यह सिर्फ काम करता है (मैकोज़ 11.6 पर परीक्षण किया गया)। –

+0

यह काम कर सकता है, लेकिन एक्सेसिबिलिटी पर वास्तव में बुरा है, और अन्य सभी तंत्र जो उपयोगकर्ता को मेनू आइटम उपलब्ध कराते हैं। आप ओएस से अपने एनएसएमएनयूइटम की स्थिति को छिपाना नहीं चाहते हैं (दूसरे शब्दों में - वास्तव में इसे छुपाएं)। –

0

कुछ जटिल जवाब यहाँ है लेकिन यह वास्तव में बहुत सरल है:

2 menuitems बनाएँ। सबसे पहले डिफ़ॉल्ट कुंजीपटल और शीर्षक जो आप चाहते हैं डिफ़ॉल्ट है। दूसरी बात यह है कि जब संशोधक कुंजी डाउन हो जाती है तो दिखाया जाएगा - फिर से अलग कुंजी एक्वाइवलेंट और शीर्षक के साथ। दूसरे मेन्यूइटम पर, 'वैकल्पिक' सक्षम करें और बाकी सब कुछ स्वचालित रूप से हो जाएगा।

आवश्यक संशोधक 2 कुंजीइक्वाइवलेंट मानों की तुलना करके पता लगाया गया है।