هل هناك تقنية مكافئة في الكاكاو لـ TrackPopupUpmenu المتزامن في Windows؟

StackOverflow https://stackoverflow.com/questions/227935

  •  03-07-2019
  •  | 
  •  

سؤال

استجابةً لحدث RightMouse ، أود الاتصال بوظيفة تعرض قائمة سياق وتشغيلها وتستجيب لعنصر القائمة المحددة. في Windows يمكنني استخدام TrackPopupMenu مع علامة TPM_ReturnCMD.

ما هي أسهل طريقة لتنفيذ هذا في الكاكاو؟ يبدو NSMENU: يريد PopupContextMenu نشر حدث إلى NSVIEW المحدد. هل يجب علي إنشاء طريقة عرض وهمية وانتظر الحدث قبل العودة؟ إذا كان الأمر كذلك ، كيف يمكنني "الانتظار" أو الأحداث المتدهورة ، فأنا لا أعود إلى رئيسي؟

هل كانت مفيدة؟

المحلول 2

يبدو أن popupContextMenu متزامن بالفعل. بما أنني لم أر طريقة لاستخدام NSMenu دون أن أرسل إشعارًا إلى NSView ، فقد توصلت إلى مخطط يثبت NSView مؤقتًا. الهدف هو عرض قائمة منبثقة وإرجاع العنصر المحدد في سياق مكالمة وظيفة واحدة. فيما يلي قصاصات الرمز من الحل المقترح:

// Dummy View class used to receive Menu Events

@interface DVFBaseView : NSView
{
    NSMenuItem* nsMenuItem;
}
- (void) OnMenuSelection:(id)sender;
- (NSMenuItem*)MenuItem;
@end

@implementation DVFBaseView
- (NSMenuItem*)MenuItem
{
    return nsMenuItem;
}

- (void)OnMenuSelection:(id)sender
{
    nsMenuItem = sender;
}

@end

// Calling Code (in response to rightMouseDown event in my main NSView

void HandleRButtonDown (NSPoint pt)
{
    NSRect    graphicsRect;  // contains an origin, width, height
    graphicsRect = NSMakeRect(200, 200, 50, 100);

    //-----------------------------
    // Create Menu and Dummy View
    //-----------------------------

    nsMenu = [[[NSMenu alloc] initWithTitle:@"Contextual Menu"] autorelease];
    nsView = [[[DVFBaseView alloc] initWithFrame:graphicsRect] autorelease];

    NSMenuItem* item = [nsMenu addItemWithTitle:@"Menu Item# 1" action:@selector(OnMenuSelection:) keyEquivalent:@""];

    [item setTag:ID_FIRST];

    item = [nsMenu addItemWithTitle:@"Menu Item #2" action:@selector(OnMenuSelection:) keyEquivalent:@""];

    [item setTag:ID_SECOND];
    //---------------------------------------------------------------------------------------------
// Providing a valid windowNumber is key in getting the Menu to display in the proper location
//---------------------------------------------------------------------------------------------

    int windowNumber = [(NSWindow*)myWindow windowNumber];
    NSRect frame = [(NSWindow*)myWindow frame];
    NSPoint wp = {pt.x, frame.size.height - pt.y};  // Origin in lower left

    NSEvent* event = [NSEvent otherEventWithType:NSApplicationDefined
                     location:wp
                     modifierFlags:NSApplicationDefined 
                     timestamp: (NSTimeInterval) 0
                     windowNumber: windowNumber
                     context: [NSGraphicsContext currentContext]
                     subtype:0
                     data1: 0
                     data2: 0]; 

    [NSMenu popUpContextMenu:nsMenu withEvent:event forView:nsView];      
    NSMenuItem* MenuItem = [nsView MenuItem];

    switch ([MenuItem tag])
    {
    case ID_FIRST: HandleFirstCommand(); break;
    case ID_SECOND: HandleSecondCommand(); break;
    }
 }

نصائح أخرى

تتمثل الطريقة "المناسبة" للقيام بذلك في الكاكاو في الحصول على هدف عنصر القائمة الخاص بك وإجراء إجراء الطريقة المطلوبة. ومع ذلك ، إذا كان يجب عليك القيام بذلك ضمن مكالمتك الأولية ، فيمكنك الاستخدام [NSView nextEventMatchingMask:] لجلب أحداث جديدة باستمرار تهمك ، والتعامل معها ، وحلقة. إليك مثالًا ينتظر فقط حتى يتم إصدار زر الماوس الأيمن. ربما ترغب في استخدام وسيطة قناع أكثر تعقيدًا ، والاتصال باستمرار [NSView nextEventMatchingMask:] حتى تحصل على ما تريد.

NSEvent *localEvent = [[self window] nextEventMatchingMask: NSRightMouseUpMask];

أعتقد أنك ستجد الطريقة "المناسبة" لتسهيل أسهل بكثير.

لا يوجد ما يعادلها المباشر ، إلا في الكربون ، الذي تم إهماله.

للكشف عن النقر بزر الماوس الأيمن ، اتبع هذه التعليمات. إنهم يضمنون أنك ستكتشف بشكل صحيح النقرات اليمنى والاحتفالات اليمنى وعرض القائمة عندما يجب عليك وعدم عرضها عندما لا ينبغي عليك ذلك.

لمتابعة الأحداث ، قد تحاول [[NSRunLoop currentRunLoop] runMode:NSEventTrackingRunLoopMode untilDate:[NSDate distantFuture]]. ستحتاج إلى الاتصال بهذا بشكل متكرر حتى يختار المستخدم أحد عناصر القائمة.

استخدام nextEventMatchingMask:NSRightMouseUpMask لن تعمل في كل الحالات ، أو حتى معظمها. إذا كان المستخدم يمينًا-نقرات على جهاز التحكم الخاص بك ، سيرتفع زر الماوس الأيمن فور انخفاضه ، دون تحديد عنصر قائمة ، ومن المحتمل أن يحدث تحديد عنصر القائمة (على الرغم من أنه ليس بالضرورة) من خلال زر الماوس الأيسر. من الأفضل تشغيل حلقة التشغيل مرارًا وتكرارًا حتى يختار المستخدم شيئًا أو يرفض القائمة.

لا أعرف كيف أقول أن المستخدم رفض القائمة دون اختيار أي شيء.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top