2009-10-21 30 views
10

Tôi đang sử dụng một số mã Carbon trong dự án Cocoa của mình để xử lý các sự kiện quan trọng trên toàn cầu (các phím tắt) từ các ứng dụng khác. Hiện tại tôi đã thiết lập trình xử lý sự kiện kEventHotKeyReleased và tôi có thể nhận được các phím nóng khi ứng dụng của tôi không hoạt động. Điều đó kích hoạt một số hoạt động trong ứng dụng của tôi.Làm thế nào để theo dõi trạng thái khóa bổ trợ toàn cục (trong bất kỳ ứng dụng nào)?

Tôi có vấn đề với hành vi của kEventHotKeyReleased là:

Nói ví dụ tôi bấm tổ hợp phím Cmd-Shift-P. Ngay sau khi tôi thả phím "P", sự kiện phím nóng được kích hoạt. Tôi cần có khả năng kích hoạt sự kiện (hoặc kích hoạt sự kiện theo cách thủ công) khi tất cả của các phím không được nén (tức là: các phím Cmd và Shift cũng được giải phóng).

Thật dễ dàng để theo dõi các phím nóng nhưng tôi không thấy gì để theo dõi các lần nhấn phím cá nhân. Nếu tôi có thể theo dõi các phím bổ trợ, tôi sẽ làm việc.

Bất kỳ gợi ý nào về cách thực hiện việc này?

Cảm ơn trước!


UPDATE:

Tôi đã cố gắng sử dụng kEventRawKeyUpkEventRawKeyModifiersChanged nhưng trong khi làm việc kEventHotKeyReleased hai không mặc dù tôi thiết lập chúng theo cách chính xác giống như 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 

Phương pháp globalHotKeyHandler được gọi là cho kEventHotKeyReleased, nhưng không phải cho kEventRawKeyUp đối với một số lý do tôi dường như không thể nắm bắt. Đây là những gì phương pháp globalHotKeyHandler của tôi trông giống như:

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

Có một cuộc gọi bổ sung mà cần phải được thực hiện hay cái gì khác tôi quên?

N.B: Thoạt nhìn, có vẻ như Truy cập cho thiết bị trợ giúp bị tắt nhưng không phải là. Vì vậy, tôi khá không biết gì.


UPDATE 2:

tôi điều tra một chút trên CGEventTap Leibowitzn đề nghị và tôi đã đưa ra với thiết lập này:

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

... và gọi lại:

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

Như bạn có thể thấy tôi đang sử dụng kCGEventKeyUp làm mặt nạ cho nhấn sự kiện nhưng bằng cách nào đó tôi nhận được sự kiện di chuột xuống ??! ??


UPDATE 3:

Ok quên rằng, tôi bỏ qua các dòng trong doc mà nói để sử dụng CGEventMaskBit (kCGEventKeyUp) cho tham số này, vì vậy cuộc gọi chính xác là:

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

Tôi vẫn gặp sự cố: các phím bổ trợ không kích hoạt kCGEventKeyUp ...


CẬP NHẬT 4:

Ok quên lần nữa ... Tôi sẽ trả lời câu hỏi của riêng tôi 5 phút sau khi yêu cầu họ ngay hôm nay huh!

Để chặn phím sửa đổi, sử dụng kCGEventFlagsChanged:

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

Vì vậy, trong bản chất tôi có chìa khóa và sửa đổi khóa làm việc phát hiện nhà nước, nhưng Tôi vẫn muốn biết lý do tại sao kEventRawKeyUp không hoạt động ...


NB: Cũng lưu ý rằng tôi đang phát triển trên Tiger với mục tiêu hỗ trợ cho các phiên bản mới hơn và cũ hơn của HĐH Càng nhiều càng tốt. CGEventTap là 10.4+ chỉ vì vậy tôi sẽ sử dụng điều này cho đến bây giờ nhưng một giải pháp tương thích ngược sẽ được chào đón.

Trả lời

3

Một tùy chọn là sử dụng EventTaps. Điều này cho phép bạn theo dõi tất cả các sự kiện bàn phím. Xem: http://developer.apple.com/mac/library/documentation/Carbon/Reference/QuartzEventServicesRef/Reference/reference.html#//apple_ref/c/func/CGEventTapCreate

Rất tiếc, các sự kiện nhấn sẽ ngừng hoạt động nếu ứng dụng yêu cầu đầu vào an toàn. Ví dụ Quicken.

+0

Tôi nghĩ có cách chỉ giám sát các phím bổ trợ. Kiểm tra mã nguồn vào Hộp Tìm kiếm Nhanh của Google. Nó có một số mã để phát hiện khi người dùng chạm vào phím lệnh hai lần. Xem: http://www.google.com/codesearch/p?hl=vi&sa=N&cd=2&ct=rc#qWBe9JkJhME/trunk/QuickSearchBox/QSB/QSBApplicationDelegate.m&q=modifiersChangedWhileInactive%20package:http://qsb-mac \ .googlecode \.com – Leibowitzn

+0

Ahh, họ chỉ đăng ký sự kiện carbon sau: {kEventClassKeyboard, kEventRawKeyModifiersChanged} – Leibowitzn

+0

Tôi đã nhận thấy kEventRawKeyModifiersChanged và kEventRawKeyUp nhưng tôi dường như không thể làm cho chúng hoạt động trong cuộc sống của tôi. Xem cập nhật trong câu hỏi của tôi. (Cảm ơn sự giúp đỡ của bạn btw!) – Form

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

Đây không phải là toàn cầu. Thao tác này chỉ cài đặt trình xử lý khi ứng dụng của riêng bạn đang hoạt động và (tôi tin) sau bộ lọc sự kiện riêng của Trình quản lý sự kiện Carbon.

Bạn cần sử dụng InstallEventHandler, có mục tiêu sự kiện làm tham số đầu tiên (InstallApplicationEventHandler là macro vượt qua mục tiêu sự kiện ứng dụng).

Đối với các sự kiện xảy ra trong khi ứng dụng của bạn không hoạt động, mục tiêu bạn muốn là GetEventMonitorTarget(). Đối với các sự kiện xảy ra khi ứng dụng của bạn đang hoạt động, mục tiêu bạn muốn là GetEventDispatcherTarget(). Để bắt các sự kiện bất kể ứng dụng nào đang hoạt động, hãy cài đặt trình xử lý của bạn trên cả hai mục tiêu.

Hiện tại, tôi chỉ sử dụng CGEventTaps, như Leibowitzn đã đề xuất.

+0

Thật lạ vì InstallApplicationEventHandler cài đặt khóa nóng của tôi ở khắp mọi nơi, không chỉ trong khi ứng dụng của tôi đang hoạt động. Tôi có thể kích hoạt các phím nóng từ bất kỳ ứng dụng nào. Ngoài ra khi tôi thử sử dụng InstallEventHandler với GetEventMonitorTarget() nó dường như không hoạt động, nhưng tôi phải làm điều gì sai. Lợi ích gì khi sử dụng CGEventTap thay vì những gì tôi đang sử dụng ngay bây giờ? – Form

+0

Dễ dàng hơn rất nhiều. –

+0

Ngoài ra, nếu bạn chỉ muốn đăng ký một phím nóng, hãy sử dụng chức năng [RegisterEventHotKey] (http://developer.apple.com/legacy/mac/library/documentation/Carbon/Reference/Carbon_Event_Manager_Ref/Reference/reference.html # // apple_ref/c/func/RegisterEventHotKey), tồn tại cho mục đích đó. –

Các vấn đề liên quan