如何使用getch()ncurses获取Ctrl,Shift或Alt?

如何使用getch() ncurses获取CtrlShiftAlt
使用ncurses,使用getch()获取CtrlShiftAlt是不行的? 我想念那个男人的东西吗?

令人惊讶的是,有时正确的答案会被降级,而“权威性”放弃的答案会得到提升……有了一点创造力,key_name实际上掌握了解决这个问题的正确关键,有一点需要注意 – SHIFT / ALT / CTRL是同时按下其他键:

  • 首先,对于诸如可打印的“普通键”,您可以轻松检测到移位,因为它是大写的。

  • 对于特殊键,例如KEY_LEFT,您将看到选择SHIFT时生成的代码实际上是KEY_SLEFT。 同上KEY_RIGHT。 不幸的是,KEY_UP / KEY_DOWN没有这样的运气,SHIFT似乎并不担心。 所以你可以通过getch()返回的char来区分 – KEY_S ..意味着按下了shift。

  • 对于ALT(至少没有被X或Aqua Windowmanager困住),keyname会将密钥转换为M ……某事。

  • 对于CTRL,您将在实际键名称前面加上“^”。 例如^ R代表密钥18

因此,您现在可以通过一个简单的代码段找出switch(getch)语句的关键代码等:

 ch = getch(); endwin(); printf("KEY NAME : %s - %d\n", keyname(ch),ch); 

就是这样。 在明确地说“不能”之前先想想。 也许有一种不太明显的方式。

(粗略地复制我在Curses中如何获得Shift + X / Alt + X键的答案? )

长话短说 – 你不能。 修饰键只是 – 修饰符。 它们本身并不存在,它们会修改您可能按下的其他(打印)键。

也就是说,如果你感觉特别勇敢,你可以尝试我的libtermkey ,它至少可以正确解析Ctrlarrow之类的东西。

最后,如果你感觉更勇敢,你可以运行我写的终端pangoterm ,它有通用的方法来编码任意修改的Unicode键,所以它可以区分CtrlmEnterCtrlShifta来自Ctrla ,等等…

但是,除了这些,答案仍然是“你不能”。

至少对于控制修改器,存在简单的解决方案。 Curses源自vi源代码,您可以在其中找到以下内容(请参阅https://github.com/nt-roff/ex-1.1/blob/master/ex.h第77行和https://github.com /nt-roff/ex-1.1/blob/master/ex_vops.c第445行):

 #ifndef CTRL #define CTRL(c) ((c) & 037) #endif switch(getch()) { case CTRL('r'): /* key ctrl-r (ie ^R) pressed */ 

依赖于使用的包含CTRL可能已经或可能尚未在您的代码中定义。

同意(部分)与@leonerd,ncurses 只会给你那些键,因为它们被用作其他键的修饰符 (忽略一些人与Alt键混淆的ASCII 转义字符)。 可以告诉某些特定设备提供此信息(例如,如console_ioctl(4)中所述的 Linux控制台),但这不是ncurses将为您解决的问题。

请参阅ncurses常见问题解答如何使用shift或control-modifiers? 一个长期的答案。

但是简短:ncurses没有告诉你是否使用了一个给定的修饰符(除了有着名的转移用途的特殊情况),而是它的终端描述提供了信息

  • 将实际function键乘以shift和control-modifiers的组合,或者通过
  • 使用基于xterm的PC风格function键的名称(shift为2,alt为3,control为5等)来提供信息。

有两种方法,因为第一种使用不超过60个function键的数组(对于移位和控制组合来说足够好),而另一种只使用用户定义的名称)。

所有这些修改后的密钥都有多个字节; 在ncurses中使用keypad() (当然)的应用程序将获得一个数字。 在后一种情况下,密钥代码在运行时确定。

这主要适用于特殊键 (function ,编辑键和光标键)。 对于常规键,可以假设keyname给出了一些特殊行为,但是读取它没有的描述:

  • 它报告ASCII控制字符(您可以使用iscntrl宏执行),和
  • 对meta进行假设(只对xterm ,你可能会使用的终端有用),以及
  • 没有为shift调整器提供帮助。

终端……都具有内部可用的修改器信息,但终端通常无法将此信息传递给应用程序。 xterm可以使用modifyOtherKeys资源执行此操作,

  modifyOtherKeys (class ModifyOtherKeys) Like modifyCursorKeys, tells xterm to construct an escape sequence for other keys (such as "2") when modified by Control-, Alt- or Meta-modifiers. This feature does not apply to function keys and well-defined keys such as ESC or the control keys. The default is "0": 0 disables this feature. 1 enables this feature for keys except for those with well- known behavior, eg, Tab, Backarrow and some special control character cases, eg, Control-Space to make a NUL. 2 enables this feature for keys including the exceptions listed. 

对应于控制序列,见于XTerm控制序列 :

 CSI > Ps; Ps m Set or reset resource-values used by xterm to decide whether to construct escape sequences holding information about the modifiers pressed with a given key. The first parameter iden- tifies the resource to set/reset. The second parameter is the value to assign to the resource. If the second parameter is omitted, the resource is reset to its initial value. Ps = 0 -> modifyKeyboard. Ps = 1 -> modifyCursorKeys. Ps = 2 -> modifyFunctionKeys. Ps = 4 -> modifyOtherKeys. 

但是(作为特定于xterm的特性),没有理由在ncurses中使用它:它会不必要地使getch复杂化。

你不能,任何主要的终端仿真器都没有扩展来实现它。

如果您正在假设X11环境,您可以使用X11函数来检索它,但这完全是另一个问题。

您可以调用key_name( c )getch()生成的键转换为显示ctrl-modifier状态的内容。

例如,如果按ctrl-r,此代码显示“^ R”:

 while( true ) { char c = getch(); if ( ERR == c ) break; const char *name = key_name( c ); move( 2, 2 ); clear(); printw( "You entered: %s ", name ); refresh(); }