我知道其他人也问了类似的问题,但我还没有看到明确的答案,我仍然被困住了.我正在尝试编写一个
Swift函数,它接受硬件生成的键盘扫描代码,例如来自NSEvent,并返回密钥的alpha-caps-locked名称,用于特定的键排列(Dvorak,Qwerty等). )当前在OS中有效(可能与生成代码时生效的安排不同).
我的理解是,这样做的唯一方法就是调用一些非常古老的Carbon功能,避开Swift的极端类型安全性,这是我感觉不舒服的事情.这是The Show So Far:
import Cocoa import Carbon func keyName (scanCode: UInt16) -> String? { let maxNameLength = 4,modifierKeys: UInt32 = 0x00000004 // Caps Lock (Carbon Era) let deadKeys = UnsafeMutablePointer<UInt32>(bitPattern: 0x00000000),nameBuffer = UnsafeMutablePointer<UniChar>.alloc(maxNameLength),nameLength = UnsafeMutablePointer<Int>.alloc(1),keyboardType = UInt32(LMGetKbdType()) let source = TISGetInputSourceProperty ( TIScopyCurrentKeyboardLayoutInputSource() .takeRetainedValue(),kTISPropertyUnicodeKeyLayoutData ) let dataRef = unsafeBitCast(source,CFDataRef.self) let dataBuffer = CFDataGetBytePtr(dataRef) let keyboardLayout = unsafeBitCast(dataBuffer,UnsafePointer <UCKeyboardLayout>.self) let osstatus = UCKeyTranslate (keyboardLayout,scanCode,UInt16(kUCKeyActionDown),modifierKeys,keyboardType,UInt32(kUCKeyTranslateNoDeadKeysMask),deadKeys,maxNameLength,nameLength,nameBuffer) switch osstatus { case 0: return Nsstring (characters: nameBuffer,length: nameLength[0]) as String default: NSLog (“Code: 0x%04X Status: %+i",osstatus); return nil } }
它不会崩溃,在这一点上我几乎认为游戏成就本身,但它也不起作用. UCKeyTranslate总是返回-50的状态,我理解这意味着有一个参数错误.我怀疑“keyboardLayout”,因为它是最复杂的设置.谁能看到参数问题?或者是否有更新的框架来处理这类事情?
正如您已经发现的那样,您必须传递UInt32的地址
变量作为deadKeyState参数.分配内存是一个
解决这个问题的方法,但你不能忘记释放内存
最终,否则该程序将泄漏内存.
变量作为deadKeyState参数.分配内存是一个
解决这个问题的方法,但你不能忘记释放内存
最终,否则该程序将泄漏内存.
另一种可能的解决方案是将变量的地址传递给
和&的一个inout-argument:
var deadKeys : UInt32 = 0 // ... let osstatus = UCKeyTranslate(...,&deadKeys,...)
这有点短,更简单,你不需要释放
记忆.同样可以应用于nameBuffer和nameLength.
使用Unmanaged类型可以避免unsafeBitCast(),
比较Swift: CFArray : get values as UTF Strings类似的问题和
更详细的解释.
您还可以利用两者之间的免费桥接
CFData和NSData.
然后你的函数看起来像这样(Swift 2):
import Carbon func keyName(scanCode: UInt16) -> String? { let maxNameLength = 4 var nameBuffer = [UniChar](count : maxNameLength,repeatedValue: 0) var nameLength = 0 let modifierKeys = UInt32(alphaLock >> 8) & 0xFF // Caps Lock var deadKeys : UInt32 = 0 let keyboardType = UInt32(LMGetKbdType()) let source = TIScopyCurrentKeyboardLayoutInputSource().takeRetainedValue() let ptr = TISGetInputSourceProperty(source,kTISPropertyUnicodeKeyLayoutData) let layoutData = Unmanaged<CFData>.fromOpaque(copaquePointer(ptr)).takeUnretainedValue() as NSData let keyboardLayout = UnsafePointer<UCKeyboardLayout>(layoutData.bytes) let osstatus = UCKeyTranslate(keyboardLayout,&nameLength,&nameBuffer) guard osstatus == noErr else { NSLog("Code: 0x%04X Status: %+i",osstatus); return nil } return String(utf16CodeUnits: nameBuffer,count: nameLength) }
Swift 3更新:
import Carbon func keyName(scanCode: UInt16) -> String? { let maxNameLength = 4 var nameBuffer = [UniChar](repeating: 0,count : maxNameLength) var nameLength = 0 let modifierKeys = UInt32(alphaLock >> 8) & 0xFF // Caps Lock var deadKeys: UInt32 = 0 let keyboardType = UInt32(LMGetKbdType()) let source = TIScopyCurrentKeyboardLayoutInputSource().takeRetainedValue() guard let ptr = TISGetInputSourceProperty(source,kTISPropertyUnicodeKeyLayoutData) else { NSLog("Could not get keyboard layout data") return nil } let layoutData = Unmanaged<CFData>.fromOpaque(ptr).takeUnretainedValue() as Data let osstatus = layoutData.withUnsafeBytes { UCKeyTranslate($0,&nameBuffer) } guard osstatus == noErr else { NSLog("Code: 0x%04X Status: %+i",count: nameLength) }
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。