加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

在Swift中获取键盘代码的键名

发布时间:2020-12-14 02:26:22 所属栏目:百科 来源:网络整理
导读:我知道其他人也问了类似的问题,但我还没有看到明确的答案,我仍然被困住了.我正在尝试编写一个 Swift函数,它接受硬件生成的键盘扫描代码,例如来自NSEvent,并返回密钥的alpha-caps-locked名称,用于特定的键排列(Dvorak,Qwerty等). )当前在OS中有效(可能与生成
我知道其他人也问了类似的问题,但我还没有看到明确的答案,我仍然被困住了.我正在尝试编写一个 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参数.分配内存是一个
解决这个问题的方法,但你不能忘记释放内存
最终,否则该程序将泄漏内存.

另一种可能的解决方案是将变量的地址传递给
和&的一个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)
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读