Keyboard Input
 

基础

使用FB的内置功能,有四种获取键盘输入的方法:

    • Inkey()返回一个包含与用户按下的键对应的ASCII字符串的字符串,或者一些特殊键的2字节FB扩展键码,例如箭头键或Page Up / Down。它的工作原理与QB一样。
    • Getkey()返回与inkey()相同的信息,但以整数形式而不是字符串。inkey()getkey()属于一起:它们使用相同的代码,它们位于相同的模块中。
    • Multikey()需要FB扫描码(SC_ *),并检查此时是否按下该键。
    • Screenevent()以EVENT_KEY_PRESS事件的形式(以及其他的密钥释放或重复)返回按键。它返回Event.Scancode字段中的FB扫描码,并在EVENT.ascii字段中返回ASCII char值或0。EVENT.ascii不使用FB扩展键码;可以检查EVENT.scancode字段,以便处理扩展密钥。
“扫描码”指的是与DOS键盘扫描码匹配的SC_ * #define。这些值并不构成,它们本身对应于某些ASCII字符,例如:SC_HOME = asc(“G”)=&h47。它们也与DOS / DJGPP或Linux内核相同的值作为扩展键代码序列的一部分。除了在multikey()screenevent()中使用,扫描码在内部的各种场合使用,例如在不同种类的键码之间进行翻译,作为键盘代码的易于使用和便携式的表示。

“key”是指由inkey()返回的其他键的ASCII字符或2字节的扩展键码字符串。rtlib对于可用的2字节扩展密钥代码,以整数形式具有几个KEY_ * #define。这些内部使用,也与getkey()返回的值相匹配。

FB的2字节扩展密钥代码由&hFF字节组成,后跟一个包含与按键对应的SC_ * scancode值的字节。检查inkey()返回的SC_HOME可能如下所示:
if( inkey( ) = chr( 255 ) + "G" ) then ...
检查getkey()返回的SC_HOME:
if( getkey() = &h47FF ) then ...
if( getkey() = ((SC_HOME shl 8) or &hFF) ) then ...
inkey()getkey()multikey()使用封装函数调用...
    • 默认情况下,控制台模式版本为fb_ConsoleInkey(),fb_ConsoleGetkey(),fb_ConsoleMultikey()
    • 或gfxlib版本fb_GfxInkey(),fb_GfxGetkey(),fb_GfxMultikey()如果??图形SCREEN处于活动状态,
通过使用函数指针钩。

rtlib

对于每个平台,rtlib具有以上功能的独立控制台模式实现:

  • DOS
fb_ConsoleInkey()fb_ConsoleGetkey()使用DJGPP的getch()功能在任何时间调用时检索输入字符。getch()返回ASCII字符,也可以返回特殊键的2字节序列,因为它们匹配SC_ *扫描码,因此易于处理。
fb_ConsoleMultikey()安装一个使用端口I / O读取键盘信息的中断处理程序,并更新由multikey()检查的键状态表。
  • Win32的
fb_ConsoleInkey()fb_ConsoleGetkey()(间接)使用Win32 API函数PeekConsoleInput()ReadConsoleInput()在需要时获得排队的按键/释放事件。所有当前待处理的事件在通话过程中处理,在涉及MapVirtualKey()的非常复杂的内部翻译之后,键被放入缓冲区,fb_ConsoleInkey()fb_ConsoleGetkey()读取他们返回的密钥。

SetConsoleCtrlHandler()用于监听控制台关闭/系统关闭事件以提供SC_CLOSE控制台模式的事件(rtlib的win32端口可能是迄今为止唯一的)。

fb_ConsoleMultikey()使用FindWindow()/ GetForegroundWindow()hack来确定控制台窗口是否集中,如果是,只需使用GetAsyncKeyState().
  • Linux,* BSD
rtlib的Unix端口在后台线程中运行控制台键盘处理程序(和控制台鼠标处理程序),以便为multikey()(和getmouse())提供输入。

fb_ConsoleInkey()fb_ConsoleGetkey()通过__fb_con.keyboard_getch()钩子读取输入字节。默认情况下,__fb_con.keyboard_getch()指向一个简单的函数,它使用/dev/tty/dev/tty上的fgetc()(间接地; Unix rtlib初始化代码打开句柄,并更改I / O设置等,不仅用于键盘输入,但大多数)。

终端返回用于简单按键的ASCII字符,以及扩展键的特殊转义序列。在第一次调用时,通过各种termcap查找(通过tgetstr())来确定某些按键事件的特定于终端的转义序列,并将它们放入查找树中,以便轻松快速地转换到相应的FB扩展密钥代码。通过执行termcap查询,Unix rtlib可以支持所有不同的终端(例如,xterm vs.linux)很好,虽然还有一些钥匙不在这里和那里工作。

一次只读取一个“事件”(ASCII字符或转义序列),将结果键添加到键缓冲区,从fb_ConsoleInkey()fb_ConsoleGetkey()可以读取它。

fb_ConsoleMultikey()目前仅针对Linux端口实现,而不是在* BSD下。在控制台输入模式(在'console'/'linux'终端下使用),它dup()定义了rtlib的/dev/tty句柄,并将其切换到中等原始模式。然后,它覆盖后台线程的__fb_con.keyboard_handler()钩子到/dev/tty复制的/dev/tty句柄的read()内核密钥代码的功能。
从后台线程调用,它会立即读取固定数量的输入,每当它到达。在稍微复杂的翻译之后,更新一个关键状态表以反映按下/释放的键的状态,由fb_ConsoleMultikey()在任何时候检查,并将这些键添加到一个键缓冲区中,从而覆盖__fb_con.keyboard_getch()读取它们,由fb_ConsoleInkey()或fb_ConsoleGetkey()[why is this done?]调用。此外,如果激活密钥,则会将这些密钥发送到Linux fbdev gfxlib2驱动程序。
在X11模式(在xterm终端下使用),fb_ConsoleMultikey()将后台线程的__fb_con.keyboard_handler()设置为检查xterm是否具有输入焦点(XGetInputFocus())的功能,如果是,则使用XQueryKeymap()更新fb_ConsoleMultikey()的关键状态表。

gfxlib2

在gfxlib中,fb_GfxInkey()fb_GfxGetkey()使用一个密钥缓冲区(所有平台上的相同代码),不同/平台特定的gfx驱动程序向其发送密钥。与此类似,有一个单一的状态表fb_GfxMultikey(),它也由gfx驱动程序更新。gfx驱动程序是否实际执行后续密钥或更新密钥状态是由他们决定的。

  • DOS
DOS gfxlib2端口(对于所有DOS gfx驱动程序)设置由DOS fb_ConsoleMultikey()使用的同一键盘中断处理程序调用的钩子/回调。
  • Win32驱动
gfx窗口线程侦听WM_CHARWM_CHARWM_CLOSE,翻译密钥,然后更新密钥状态表,将其发布到fb_GfxInkey()/ fb_GfxGetkey()缓冲区,并填写并发布相应的EVENTscreenevent().
  • X11驱动
gfx窗口线程侦听KeyPress和其他XEvent,翻译键,然后发布他们等,就像Win32驱动程序。
  • Linux fbdev驱动
如上所述,fbdev驱动程序从与Linux {98??9796080}使用的相同的键盘处理程序代码获取输入。