curses 例程工作在屏幕,视窗,以及子窗口上。“屏幕”就是我们这在写的设备,它占据了这个设备上所有可用的显示面积。当然,如果终端窗口在一个 X 窗口中,那么所谓的“屏幕”就是该终端窗口中所有可用的字符位置。
然而,至少总有一个 curses 视窗 stdscr ,它和物理屏幕一样大小。你可以额外创建一些小于屏幕的窗口。视窗可以互相重叠并且可以有很多个子窗口,但是每一个子窗口必须总是包含在父窗口中。
cruses 库维护了两个数据结构,此数据接够有点类似于一个终端屏幕的地图(用这两个数据结构来映射屏幕):
stdscr 与 curscr
这两个结构中,stdscr 相对来说比较重要一点,这个结构在 curses 函数输出时被更新。stdscr 数据结构是“标准屏幕”。它和 stdout 在很多方面都非常相似。在 curses 程序里,它是个默认的输出窗口。curscr 结构与之类似,但是它保持屏幕所显示的实际上看起来就像是发生在当前时刻。写到 stdscr 的输出不会立即出现在屏幕上,知道程序调用了 refresh() -- 这时候,curses 库会比较 stdscr 和 curscr (屏幕当前的样子)中的内容;然后,curses 会使用这两个结构的不同来更新屏幕。
一些 curses 程序需要了解 cruses 所维护的 stdscr 结构,所以几个函数需要它这样的一个参数。然而,实际上的 stdscr 结构与函数库的具体实现密切相关(implementation-dependent)并且永远不能直接去访问。curses 程序也永远无须用到 curscr 结构。
因此,在 curses 程序里处理输出字符的过程如下:
[Plain Text] 纯文本查看 复制代码 使用 curses 函数去更新一个逻辑屏幕;
请求 curses 通过 refresh 来刷新物理屏幕。
这个两级跳的方法(tow-level approach)的好处,除了对程序设计方面更加容易外(in addition to 除了..之外),还有就是 curses 屏幕刷新得非常有效率。另外(in addtion),尽管这在一个控制台屏幕上看来不太重要,但如果你正在运行的程序是在一个低速网络链接上(低速串行口或调制解调器)时,这种差距看起来就很客观了。
一个 curses 程序会对逻辑屏幕输出函数做多次的调用,比如说可能会在整个屏幕上移动光标使之找到要写文本的位置以及划线与画框框。
在某个阶段(at some stage),用户需要查看全部的输出。这种情况一般发生在调用 refresh 期间,curses 将计算出物理屏幕对影逻辑屏幕的一个最佳方法。通过使用合适终端工具(性能指标)以及优化光标移动动作,curses 可以经常以更少的字符输出来更新屏幕,而不需要立即的去一次性的写一整屏的东西。
逻辑屏幕的布局是一个字符数组,数组下标由行号和列号组成,开始坐标(0,0)在屏幕的左上角。
所有的 curses 函数使用(y,x)为坐标表示,y表示行,x表示列。每一个位置不仅容纳这个屏幕位置上的字符而且还保存有他的属性。属性是否能被显示出来还依赖于物理终端的性能指标,但通常至少会有粗题和下划线这两种属性可用。
因为 curses 库需要创建和破坏同一个临时数据结构,所有 curses 程序在使用之前必须初始化库,以便用后还原。这里有两个函数可以做这件工作:initscr 和 endwin
测试代码:
#include <unistd.h>
#include <stdlib.h>
#include <curses.h>
int main()
{
initscr();
move(5, 15);
printw("%s", "hello,wrold");
refresh();
sleep(3); /*休息3秒以看到效果*/
endwin();
exit(EXIT_SUCCESS);
} |