Tôi cần một hàm có ký tự, trả về CGKeyCode
được liên kết với vị trí của ký tự đó trên bố cục bàn phím hiện tại. Ví dụ: với "b", nó phải trả về kVK_ANSI_B
nếu sử dụng QWERTY của Hoa Kỳ hoặc kVK_ANSI_N
nếu sử dụng Dvorak.Làm thế nào để chuyển đổi ký tự ASCII sang CGKeyCode?
API Win32 có chức năng VkKeyScan()
cho mục đích này; X11 có chức năng XStringToKeySym()
. Có chức năng như vậy trong CG API không?
Tôi cần điều này để chuyển thông số đến CGEventCreateKeyboardEvent()
. Tôi đã thử sử dụng CGEventKeyboardSetUnicodeString()
thay vào đó, nhưng dường như does not support cờ bổ trợ (mà tôi cần).
Tôi đã tìm kiếm rộng rãi cho điều này nhưng không thể tìm thấy câu trả lời hợp lý. Hiện nay tôi đang sử dụng đoạn mã sau (found online), mà làm việc, nhưng không phải là chính xác tao nhã (và khá khó khăn để giải mã thế nào để đơn giản hóa) và tôi không muốn sử dụng nó trong mã sản xuất:
#include <stdint.h>
#include <stdio.h>
#include <ApplicationServices/ApplicationServices.h>
CGKeyCode keyCodeForCharWithLayout(const char c,
const UCKeyboardLayout *uchrHeader);
CGKeyCode keyCodeForChar(const char c)
{
CFDataRef currentLayoutData;
TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource();
if (currentKeyboard == NULL) {
fputs("Could not find keyboard layout\n", stderr);
return UINT16_MAX;
}
currentLayoutData = TISGetInputSourceProperty(currentKeyboard,
kTISPropertyUnicodeKeyLayoutData);
CFRelease(currentKeyboard);
if (currentLayoutData == NULL) {
fputs("Could not find layout data\n", stderr);
return UINT16_MAX;
}
return keyCodeForCharWithLayout(c,
(const UCKeyboardLayout *)CFDataGetBytePtr(currentLayoutData));
}
/* Beware! Messy, incomprehensible code ahead!
* TODO: XXX: FIXME! Please! */
CGKeyCode keyCodeForCharWithLayout(const char c,
const UCKeyboardLayout *uchrHeader)
{
uint8_t *uchrData = (uint8_t *)uchrHeader;
UCKeyboardTypeHeader *uchrKeyboardList = uchrHeader->keyboardTypeList;
/* Loop through the keyboard type list. */
ItemCount i, j;
for (i = 0; i < uchrHeader->keyboardTypeCount; ++i) {
/* Get a pointer to the keyToCharTable structure. */
UCKeyToCharTableIndex *uchrKeyIX = (UCKeyToCharTableIndex *)
(uchrData + (uchrKeyboardList[i].keyToCharTableIndexOffset));
/* Not sure what this is for but it appears to be a safeguard... */
UCKeyStateRecordsIndex *stateRecordsIndex;
if (uchrKeyboardList[i].keyStateRecordsIndexOffset != 0) {
stateRecordsIndex = (UCKeyStateRecordsIndex *)
(uchrData + (uchrKeyboardList[i].keyStateRecordsIndexOffset));
if ((stateRecordsIndex->keyStateRecordsIndexFormat) !=
kUCKeyStateRecordsIndexFormat) {
stateRecordsIndex = NULL;
}
} else {
stateRecordsIndex = NULL;
}
/* Make sure structure is a table that can be searched. */
if ((uchrKeyIX->keyToCharTableIndexFormat) != kUCKeyToCharTableIndexFormat) {
continue;
}
/* Check the table of each keyboard for character */
for (j = 0; j < uchrKeyIX->keyToCharTableCount; ++j) {
UCKeyOutput *keyToCharData =
(UCKeyOutput *)(uchrData + (uchrKeyIX->keyToCharTableOffsets[j]));
/* Check THIS table of the keyboard for the character. */
UInt16 k;
for (k = 0; k < uchrKeyIX->keyToCharTableSize; ++k) {
/* Here's the strange safeguard again... */
if ((keyToCharData[k] & kUCKeyOutputTestForIndexMask) ==
kUCKeyOutputStateIndexMask) {
long keyIndex = (keyToCharData[k] & kUCKeyOutputGetIndexMask);
if (stateRecordsIndex != NULL &&
keyIndex <= (stateRecordsIndex->keyStateRecordCount)) {
UCKeyStateRecord *stateRecord = (UCKeyStateRecord *)
(uchrData +
(stateRecordsIndex->keyStateRecordOffsets[keyIndex]));
if ((stateRecord->stateZeroCharData) == c) {
return (CGKeyCode)k;
}
} else if (keyToCharData[k] == c) {
return (CGKeyCode)k;
}
} else if (((keyToCharData[k] & kUCKeyOutputTestForIndexMask)
!= kUCKeyOutputSequenceIndexMask) &&
keyToCharData[k] != 0xFFFE &&
keyToCharData[k] != 0xFFFF &&
keyToCharData[k] == c) {
return (CGKeyCode)k;
}
}
}
}
return UINT16_MAX;
}
Có a.) (tốt hơn là) một chức năng tiêu chuẩn tôi nhìn, hoặc b.) (gần như chắc chắn) một cách tao nhã hơn viết của riêng tôi?
http://www.manytricks.com/keycodes/ – Sneakyness
@Sneakyness: Tôi không muốn mã hóa các hằng số chính. Chúng là một.) Được tạo bởi đầu vào của người dùng và b) có thể là kết quả của nhiều bố trí bàn phím. – Michael
@Michael - Bạn có nhận được phiên bản làm việc của keylogger không. Tôi đang tìm kiếm một. Tôi đã thử vài gói git. Nhưng không hoạt động như mong đợi/không nắm bắt tất cả các nét chính. Hay bạn có bất cứ đề nghị cho điều này? bất kỳ gói nguồn mở nào?Nó sẽ rất hữu ích – Dany