soe*_*ard 5 macos cocoa objective-c core-services swift
给定一个没有修饰符的键的键代码,我想产生按shift +键的结果.示例:对于标准美国键盘,<shift> + <period>给出>.
相关的功能是UCKeytranslate,但我需要一些帮助来获得正确的细节.下面的代码片段是一个完整的程序,可以在XCode中运行.该程序的目的是给出<period>来产生字符>.
该计划的结果是:
Keyboard: <TSMInputSource 0x10051a930> KB Layout: U.S. (id=0)
Layout: 0x0000000102802000
Status: -50
UnicodeString: 97
String: a
Done
Program ended with exit code: 0
Run Code Online (Sandbox Code Playgroud)
获得布局的部分似乎正在工作,但状态代码显示出现了问题.但是什么?
import Foundation
import Cocoa
import Carbon
import AppKit
// The current text input source (read keyboard) has a layout in which
// we can lookup how key-codes are resolved.
// Get the a reference keyboard using the current layout.
var unmanagedKeyboard = TISCopyCurrentKeyboardLayoutInputSource()
var keyboard = unmanagedKeyboard.takeUnretainedValue() as TISInputSource
print("Keyboard: ") ; println(keyboard)
// Get the layout
var ptrLayout = TISGetInputSourceProperty(keyboard, kTISPropertyUnicodeKeyLayoutData)
var layout = UnsafeMutablePointer<UCKeyboardLayout>(ptrLayout)
print("Layout: "); println(layout)
// Let's see what the result of pressing <shift> and <period> (hopefully the result is > )
var keycode = UInt16(kVK_ANSI_Period) // Keycode for <period>
var keyaction = UInt16(kUCKeyActionDisplay) // The user is requesting information for key display
var modifierKeyState = UInt32(1 << 17) // Shift
var keyboardType = UInt32(LMGetKbdType())
var keyTranslateOptions = UInt32(1 << kUCKeyTranslateNoDeadKeysBit)
var deadKeyState = UnsafeMutablePointer<UInt32>(bitPattern: 0) // Is 0 the correct value?
var maxStringLength = UniCharCount(4) // uint32
var actualStringLength = UnsafeMutablePointer<UniCharCount>.alloc(1) //
actualStringLength[0]=16
var unicodeString = UnsafeMutablePointer<UniChar>.alloc(255)
unicodeString[0] = 97 // a (this value is meant to be overwritten by UCKeyTranslate)
var str = NSString(characters: unicodeString, length: 1)
var result = UCKeyTranslate(layout, keycode, keyaction, modifierKeyState, keyboardType, keyTranslateOptions,
deadKeyState, maxStringLength, actualStringLength, unicodeString)
// Print the results
print("Status: "); println(result)
var unichar = unicodeString[0];
print("UnicodeString: "); println(String(unichar))
print("String: "); println(str)
println("Done")
Run Code Online (Sandbox Code Playgroud)
编辑
我根据Ken Thomases的建议改写了片段.一些技巧来自:Graphite a Swift程序使用密钥代码也被使用.
import Foundation
import Cocoa
import Carbon
import AppKit
// The current text input source (read keyboard) has a layout in which
// we can lookup how key-codes are resolved.
// Get the a reference keyboard using the current layout.
let keyboard = TISCopyCurrentKeyboardInputSource().takeRetainedValue()
let rawLayoutData = TISGetInputSourceProperty(keyboard, kTISPropertyUnicodeKeyLayoutData)
print("Keyboard: ") ; println(keyboard)
// Get the layout
var layoutData = unsafeBitCast(rawLayoutData, CFDataRef.self)
var layout: UnsafePointer<UCKeyboardLayout> = unsafeBitCast(CFDataGetBytePtr(layoutData), UnsafePointer<UCKeyboardLayout>.self)
print("Layout: "); println(layout)
print("KbdType "); println(LMGetKbdType()) // Sanity check (prints 44)
var keycode = UInt16(kVK_ANSI_Period) // Keycode for a
var keyaction = UInt16(kUCKeyActionDisplay)
var modifierKeyState = UInt32(1 << 1) // Shift
var keyboardType = UInt32(LMGetKbdType())
var keyTranslateOptions = OptionBits(kUCKeyTranslateNoDeadKeysBit)
var deadKeyState = UInt32(0) // Is 0 the correct value?
var maxStringLength = UniCharCount(4) // uint32
var chars: [UniChar] = [0,0,0,0]
var actualStringLength = UniCharCount(1)
var result = UCKeyTranslate(layout, keycode, keyaction, modifierKeyState, keyboardType, keyTranslateOptions,
&deadKeyState, maxStringLength, &actualStringLength, &chars)
// Print the results
print("Status: "); println(result)
print("Out:"); println(UnicodeScalar(chars[0]))
println("Done")
Run Code Online (Sandbox Code Playgroud)
对于kTISPropertyUnicodeKeyLayoutData,TISGetInputSourceProperty()返回一个CFDataRef.您需要获取其字节指针并将其视为指针UCKeyboardLayout.我不认为你正在用这条线做什么:
var layout = UnsafeMutablePointer<UCKeyboardLayout>(ptrLayout)
Run Code Online (Sandbox Code Playgroud)
我真的不知道Swift,但它可能会起作用:
var layout = UnsafePointer<UCKeyboardLayout>(CFDataGetBytePtr(ptrLayout))
Run Code Online (Sandbox Code Playgroud)
或者可能:
var layout = CFDataGetBytePtr(ptrLayout) as UnsafePointer<UCKeyboardLayout>
Run Code Online (Sandbox Code Playgroud)
而且,kUCKeyActionDisplay大多没用.它的目的是返回密钥的标签,但它甚至不能可靠地执行.你可能想用kUCKeyActionDown.
对于修饰符,您希望使用shiftKey右移8位的碳时代位掩码(如文档中所示UCKeyTranslate()).shiftKey是1 << 9,这样shiftKey >> 8的1 << 1.
对于选项,您应该能够kUCKeyTranslateNoDeadKeysMask简单地使用.它相当于1 << kUCKeyTranslateNoDeadKeysBit.
是,0是deadKeyState初始击键的正确值,或者是您不想应用任何先前死锁状态的值.
我不确定你为什么评论这maxStringLength条线uint32.该类型与最大字符串长度完全无关.应该写入提供的缓冲区maxStringLength的最大UTF-16代码单元数(API错误地称之为"字符")UCKeyTranslate().它基本上是缓冲区大小,以UniChars(非字节)为单位.在你的情况下它应该是255.或者,因为你可能不希望从一次击键得到255个"字符",你可以减小缓冲区的大小并设置maxStringLength为匹配它是什么.
你的处理str很奇怪.您unicodeString在调用之前从缓冲区构造它UCKeyTranslate().您是否希望更改字符串对象的值,因为UCKeyTranslate()更改了内容unicodeString?它不是.如果确实如此,那将是一个非常糟糕的错误NSString.在成功填充NSString该缓冲区后, 您应该从缓冲区构造UCKeyTranslate().当然,你应该actualStringLength在构造时传递长度参数NSString.
| 归档时间: |
|
| 查看次数: |
1732 次 |
| 最近记录: |