كيفية مراقبة حالة مفتاح التعديل العالمي (في أي تطبيق)؟

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

  •  05-07-2019
  •  | 
  •  

سؤال

أنا أستخدم بعض أكواد الكربون في مشروع Cocoa الخاص بي للتعامل مع الأحداث الرئيسية العالمية (الاختصارات) من التطبيقات الأخرى.حاليا لدي الإعداد أ kEventHotKeyReleased يمكنني أنا ومعالج الأحداث الحصول على مفاتيح التشغيل السريع بنجاح عندما لا يكون التطبيق الخاص بي نشطًا.يؤدي ذلك إلى تشغيل بعض العمليات في طلبي.

المشكلة عندي مع سلوك kEventHotKeyReleased يكون:

لنفترض على سبيل المثال أنني قمت بالضغط على مجموعة المفاتيح Cmd-Shift-P.بمجرد تحرير المفتاح "P"، يتم تشغيل حدث المفتاح السريع. أحتاج إلى أن أكون قادرًا على تشغيل الحدث (أو تشغيله يدويًا) متى الجميع من المفاتيح غير مضغوطة (أي:يتم تحرير مفاتيح Cmd وShift أيضًا).

من السهل مراقبة المفاتيح الساخنة ولكني لم أر شيئًا لمراقبة ضغطات المفاتيح الفردية.إذا كان بإمكاني مراقبة حالات مفتاح التعديل، سأكون في العمل.

هل هناك أي تلميحات حول كيفية القيام بذلك؟

شكرا لك مقدما!


تحديث:

لقد حاولت استخدام kEventRawKeyUp و kEventRawKeyModifiersChanged ولكن في حين kEventHotKeyReleased لا يعمل هذين الاثنين على الرغم من أنني قمت بإعدادهما بنفس الطريقة تمامًا kEventHotKeyReleased.

EventTypeSpec eventTypes[] = {{kEventClassKeyboard, kEventHotKeyReleased}, {kEventClassKeyboard, kEventRawKeyUp}};
// Changing the order in the list does not help, nor does removing kEventHotKeyReleased
OSStatus err = InstallApplicationEventHandler(&globalHotkeyHandler, GetEventTypeCount(eventTypes), eventTypes, NULL, NULL);
// err == noErr after this line

ال globalHotKeyHandler الطريقة مطلوبة kEventHotKeyReleased, ولكن ليس من أجل kEventRawKeyUp لسبب ما لا أستطيع أن أفهم.وهنا ما بلدي globalHotKeyHandler تبدو الطريقة كما يلي:

OSStatus globalHotkeyHandler(EventHandlerCallRef nextHandler, EventRef anEvent, void *userData) {
    NSLog(@"Something happened!");
}

هل هناك مكالمة إضافية يجب إجراؤها أو شيء آخر نسيته؟

ملحوظة:للوهلة الأولى، يبدو أنه من الممكن أن يكون الوصول إلى الأجهزة المساعدة معطلاً، ولكن ليس.لذلك أنا جاهل جدا.


التحديث 2:

لقد حققت قليلا في CGEventTap اقترح Leibowitzn وتوصلت إلى هذا الإعداد:

CFMachPortRef keyUpEventTap = CGEventTapCreate(kCGHIDEventTap,kCGHeadInsertEventTap,kCGEventTapOptionListenOnly,kCGEventKeyUp,&keyUpCallback,NULL);
CFRunLoopSourceRef keyUpRunLoopSourceRef = CFMachPortCreateRunLoopSource(NULL, keyUpEventTap, 0);
CFRelease(keyUpEventTap);
CFRunLoopAddSource(CFRunLoopGetCurrent(), keyUpRunLoopSourceRef, kCFRunLoopDefaultMode);
CFRelease(keyUpRunLoopSourceRef);

...و رد النداء :

CGEventRef keyUpCallback (CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) {
    NSLog(@"KeyUp event tapped!");
    return event;
}

كما ترون أنا باستخدام kCGEventKeyUp كقناع للحدث اضغط ولكن بطريقة ما أتلقى أحداث الماوس لأسفل ??!??


التحديث 3:

حسنًا، انسَ ذلك، لقد تجاهلت السطر الموجود في المستند الذي يشير إلى استخدام CGEventMaskBit(kCGEventKeyUp) لهذه المعلمة، لذا فإن الاتصال الصحيح هو:

CGEventTapCreate(kCGHIDEventTap,kCGHeadInsertEventTap,kCGEventTapOptionListenOnly,CGEventMaskBit(kCGEventKeyUp),&keyUpCallback,NULL);

رغم ذلك مازلت أواجه مشكلة:لا تقوم مفاتيح التعديل بتشغيل kCGEventKeyUp...


التحديث 4:

طيب إنسي ذلك مرة أخرى..أنا ملزم بالإجابة على أسئلتي الخاصة بعد 5 دقائق من طرحها اليوم، هاه!

لاعتراض مفاتيح التعديل، استخدم kCGEventFlagsChanged:

CGEventTapCreate(kCGHIDEventTap,kCGHeadInsertEventTap,kCGEventTapOptionListenOnly,CGEventMaskBit(kCGEventFlagsChanged),&callbackFunction,NULL);

لذا، في جوهر الأمر، حصلت على اكتشاف حالة المفتاح والمفتاح المعدل، ولكن ما زلت مهتمًا بمعرفة ذلك لماذا kEventRawKeyUp لا يعمل...


ملحوظة:لاحظ أيضًا أنني أقوم بالتطوير على Tiger بهدف الحصول على دعم للإصدارات الجديدة والأقدم من نظام التشغيل قدر الإمكان.CGEventTap هو الإصدار 10.4+ فقط، لذا سأستخدم هذا في الوقت الحالي ولكن سيكون الحل المتوافق مع الإصدارات السابقة موضع ترحيب.

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

المحلول

أحد الخيارات هو استخدام EventTaps.يتيح لك ذلك مراقبة جميع أحداث لوحة المفاتيح.يرى:http://developer.apple.com/mac/library/documentation/Carbon/Reference/QuartzEventServicesRef/Reference/reference.html#//apple_ref/c/func/CGEventTapCreate

لسوء الحظ، ستتوقف نقرات الأحداث عن العمل إذا طلب أحد التطبيقات إدخالاً آمنًا.على سبيل المثال تسريع.

نصائح أخرى

OSStatus err = InstallApplicationEventHandler(&globalHotkeyHandler, GetEventTypeCount(eventTypes), eventTypes, NULL, NULL);

هذه ليست عالمية.يؤدي هذا إلى تثبيت المعالج فقط عندما يكون التطبيق الخاص بك نشطًا، و(على ما أعتقد) بعد مرشحات الأحداث الخاصة بـ Carbon Event Manager.

تحتاج إلى استخدام InstallEventHandler, ، والذي يأخذ هدف الحدث كمعلمة أولى (InstallApplicationEventHandler هو ماكرو يمرر هدف حدث التطبيق).

بالنسبة للأحداث التي تحدث عندما يكون تطبيقك غير نشط، فإن الهدف الذي تريده هو GetEventMonitorTarget().للأحداث التي تحدث أثناء تقديم الطلب الخاص بك يكون نشط، والهدف الذي تريده هو GetEventDispatcherTarget().لالتقاط الأحداث بغض النظر عن التطبيق النشط، قم بتثبيت المعالج الخاص بك على كلا الهدفين.

لكن في الوقت الحاضر، سأستخدم فقط CGEventTaps، كما اقترح ليبوفيتزن.

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