免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1014 | 回复: 0
打印 上一主题 下一主题

Ncurses介绍 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-03-09 15:32 |只看该作者 |倒序浏览
这段时间一直在做linux下的工作,需要学习ncurses,因此便查询了和ncurses相关的网站及一些书籍,收获颇丰,记录了一些,一并发上来吧。
最后的成果是做出了一个手持端的拨号界面,实现键盘与屏幕的同步响应,算是完成了第一步吧。呵呵
Ncurses是一个能提供功能键定义(快捷键),屏幕绘制以及基于文本终端的图形互动功能的动态库。
什么是Ncurses?
您希望您的程序有一个彩色的界面吗?Ncurses是一个能提供基于文本终端窗口功能的动态库. Ncurses可以:

  • 只要您喜欢,您可以使用整个屏幕
  • 创建和管理一个窗口
  • 使用8种不同的彩色
  • 为您的程序提供鼠标支持
  • 使用键盘上的功能键

哪里可以下载?
Ncurses是基于GNU/Linux发展的,请访问
http://www.gnu.org/software/ncurses/
以获得最新的更新版本或
基础知识
为了能够使用ncurses库,您必须在您的源程序中将curses.h包括(include)进来,而且在编译的需要与它连接起来. 在gcc中您可以使用参数-lcurses进行编译.
在使用ncurses的时候,您有必要了解它的基础数据结构.它有一个WINDOW结构,从名字就很容易知道,它是用来描述 您创建的窗体的,所有ncurse库中的函数都带有一个WINDOW指针参数.
在ncurses中使用最多的组件是窗体.即使您没有创建自己的窗体,当前屏幕会认为是您自己的窗体. 如同标准输入输出系统提供给屏幕的文件描述符stdout一样(假设没有管道转向),ncurses提供一个 WINDOW指针stdscr做相同工作.除了stdscr外,ncurses还定义了一个WINDOW指针curscr. 和stdscr描述当前屏幕一样,curscr描述当前在库中定义的屏幕,您可以带着"他们有什么区别?"这个问题继续阅读.
为了在您的程序中使用ncurses的函数和变量,您必须首先调用initscr函数(初始化工作),它会给一些变量比如 stdscr,curscr等分配内存,并且让ncurses库处于准备使用状态,换句话说,所有ncurses函数必须跟在initscr后面. 同样的约定,您在结束使用ncurses后,应该使用endwin来释放所有ncurses使用的内存.在使用endwin后,您将不能在使用 任何ncurses的函数,除非您再一次调用initscr函数.
在initscr和endwin之间,请不要使用标准输入输出库的函数输出结果到屏幕上,否则,您会看到屏幕会被您的输出 弄的乱七八糟,这可不是您期望的结果.当ncurses处在激活状态时,请使用它自己的函数来把结果输出到屏幕.在调用initscr之前或者 endwin之后,您就可以随便使用了.
  
刷新屏幕:refresh
WINDOW结构不会经常保持同一高度宽度以及在窗体中的位置,但是会保持在窗体中的内容.当您向窗体写入数据时, 会改变窗体中的内容,但并不意味着在屏幕中会立即显示出来,要更新屏幕内容,必须调用refresh或者wrefres函数.
这里介绍了stdscr和curscr两者之间的区别.curscr保存着当前屏幕的内容,在调用ncurse的输出函数后,stdscr和curscr可能会有不同的内容, 如果您想在最近一次屏幕内容改变后让stdscr和curscr保持一致,您必须使用refresh函数.换句话说, refresh是唯一一个处理curscr的函数.千万不要弄混淆了curscr和stdscr,应该在refresh函数中更新curscr中的内容
refresh有一个能尽可能快的更新屏幕的机制,当调用refresh时,它只更新窗体中内容改变的行,这节省了CPU的处理时间 ,防止程序往屏幕上写相同的信息(译者注:在屏幕的同一位置不用重新显示同样的内容.)这种机制就是为什么同时使用ncurses的函数 和标准的输入输出函数会造成屏幕内容错位的原因.当调用ncurses的输出函数时,它会设置一个标志,能让refresh 知道是哪一行改变了.但是您调用标准输入输出函数时,就不会产生这种结果.
refresh和wrefresh其实做了同样的事情.wrefresh需要一个WINDOW的指针参数,它仅仅刷新该窗体的内容. refresh()等同于wrefresh(stdscr).我在后面会提到,和wrefresh一样,ncursers的许多函数都有许多这种为stdscr定义的宏函数.
  
定义一个新的窗体
下面我们来谈谈能定义新窗体的subwin和newwin函数.他们都需要一个来定义新窗体的高度,宽度以及 左上角位置的参数,并且返回一个WINDOW指针来指向该窗体.您可以使用它来作为wrefresh的参数或者一些其他我将要 谈到的函数.
您可能会问:"如果他们做同样的事情,为什么要有两个函数?",您是对的,他们之间有一些细微的差别.subwin创建一个 窗体的子窗体,它将继承了父窗体的所有属性.但如果在子窗体中改变了这些属性的值,它将不会影响父窗体.
除此之外,父窗体和子窗体之间还有一些联系.父窗体和子窗体中的内容将彼此共享,彼此影响.换句话说, 在父窗口和子窗体重叠的区域的字符会被任意一个窗体改变.如果父窗体写入了数据到这块区域,子窗体中这块区域同样 改变了,反之也是如此.
和subwin不同的是,newwin创建一个独有的窗体.这样的窗体,在没有他们的子窗体之前,是不会和其他窗体共享 任何文本数据的.使用subwin的好处是可以使用较少的内存就可以方便的共享字符数据了.但是如果您担心窗体数据会互相影响 那么就应该使用newwin.
您可以创建任意多层的子窗体,每一个子窗体又可以有它自己的子窗体,但是一定要记住,窗体的字符内容是被两个以上 的窗体共享的.
当您调用完您定义的窗体后,您可以使用delwin函数来删除该窗体.我建议您使用man pages来得到这些函数的详细参数.
  
向窗体写数据和从窗体读数据
我们谈到了stdscr,curscr,以及刷新屏幕和定义一个新窗体,但是我们怎样向一个窗体写入数据?我们怎样从一个窗体中读入数据?
实现以上目的函数如同标准输入输出库中的一些函数一样,我们使用printw来替换printf输出内容,scanw替换scanf接受输入, addch替换putc或者putchar,getch替换getc或者getchar.他们用法一样,仅仅名字不同,类似的,addstr可以用来向窗体 写入一个字符串,getstr用来从窗体中读入一个字符串.所有这些函数都是以一个"w"字母开头,后面再跟上函数的?字, 如果需要操作另外一个窗体内容,第一个参数必须是该窗体的WINDOWS结构指针,举个例子,printw(...)和wprintw(stdscr,...) 是相同的,就如同refresh()和wrefresh(stdscr)一样.
如果要写这些函数的详细说明,这篇文章将会变的很长.要得到他们的?述,原型以及返回值或者其他信息,man pages是一个不错的选择. 我建议您对照man pages检查您使用的?一个函数.他们提供了详细和非常有用的信息.在这篇文章的最后一节,我提供了 一个示例程序,可以当作是一个ncurses函数的使用指南.
  
物理指针和逻辑指针
在讲完写入数据和从窗体读出数据后,我们需要解释一下物理指针和逻辑指针 物理指针是一个常用指针,它只有一个,从另一个方面讲,逻辑指针属于ncurses窗体, 每一个窗体都只有一个物理指针,但是他们可以有多个逻辑指针.
当窗体准备写入和读出的时候,逻辑指针会指向窗体中将要进行操作的区域.因此, 通过移动逻辑指针,您可以任何时候向窗体中的任意位置写入数据.这个是区别与标准输入输出库的优势之处.
移动逻辑指针的函数是move或者另外一个您非常容易猜出来的函数wmove.move是wmove的一个宏函数,专门用来处理 stdscr的.
另外一个需要确认的是物理指针和逻辑指针的协作关系,物理指针的位置将会在一段写入程序后无效,但是我们通过可以 通过WINDOW结构的_leave标志定位它.如果设置了_leave标志,在写操作结束后,逻辑指针将会移动到物理指针指向窗体中最后写入的区域. 如果没有设置_leave位,在写操作结束后,物理指针将返回到逻辑指针指向窗体的第一个字符写入位置._leave标志是由leaveok函数控制的.
移动物理指针的函数是mvcur,不象其他的函数,mvcur在不用等待refresh动作就会立即生效.如果您想隐藏物理指针, 您可以使用curs_set函数,使用man pages来获得详细信息.
同样存在一些宏函数简化了上述的移动和写入等函数.您可以在addch,addstr,printw,getch,getstr,scanw等函数 的man pages页得到更多的解释.
  
清除窗体
当我们向窗体写完内容后,我们怎么样清除窗体,行和字符?
在ncurses中,清除意味着用空白字符填充整块区域,整行或者整个窗体的内容. 下面我介绍的函数将会使用空白字符填充必要的区域,达到我们清屏的目的.
首先我们谈到能清楚字符和行的函数,delch和wdelch能删除掉窗体逻辑指针指向的字符,下一个字符和一直到行末的字符都会左移 一个位置.deleteln和wdeleteln能删除掉逻辑指针指向的行,并且上移下一行.
clrteol和wclrtoeol能清除掉从逻辑指针指向位置右边字符开始到行末的所有字符.clrtbot和wclrtobot 首先清除掉从逻辑指针所在位置右边字符开始到行末的所有字符,接着删除下面所有行.
除了这些,还有一些函数能清除整个屏幕和窗体.有两种方法可以清除掉整个屏幕.第一个是先用空白字符填充 屏幕所有区域,然后再调用refresh函数.另外一种方法是用固定的终端控制字符清除.第一种方法比较慢,因为它需要重写 当前屏幕.第二种能迅速清除整个屏幕内容.
erase和werase用空白字符替换窗体的文本字符,在下一次调用refresh后屏幕内容将会被清除掉.但是如果窗体 需要清掉整个屏幕, 这将一个比较苯的办法.您可以使用上面讲的第一种方法来完成.当窗体需要被清除的是一个屏幕那么宽, 您可以使用下面讲的函数来非常好的完成您的任务.
在涉及到其他函数之前,我们先来讨论一下_clear标志位.如果设置了该标志,那么它会存在WINDOW结构中. 当调用它时,它会用refresh来发送控制代码到终端,refresh检查窗体的宽度是否是屏幕的宽度(使用_FULLWIN标志位). 如果是的话,它将用内置的终端方法刷新屏幕,它将写入除了空白字符外的文本字符到屏幕,这是一种非常快速清屏的方法. 为什么仅仅当窗体的宽度和屏幕宽度相等时才用内置的终端方法清屏呢?那是因为控制终端代码不仅仅只清除窗体自身 ,它还可以清除当前屏幕._clear标志位由clearok函数控制.
函数clear和wclear被用来清除和屏幕宽度一样的窗体内容.实际上,这些函数等同与使用werase和clearok. 首先,它用空白字符填充窗体的文本字符.接着,设置_clear标志位,如果窗体宽度和屏幕宽度一样,就使用内置的终端方法 清屏,如果不一样就用空白字符填充窗体所有区域再用refresh刷新.
总而言之,如果您知道窗体的宽度和屏幕宽度一样,就使用clear或者wclear,这个速度将非常快.如果窗体宽度 不是和屏幕宽度一样,那么使用wclear和werase将没有任何分别.
  
使用颜色
您在屏幕上看到的颜色其实都是颜色对,因为每一个区域都有一个背景色和一个前景色.使用ncurses显示彩色 意味着您定义自己的颜色对并且将这些颜色对写入到窗体.
如同使用ncurses函数必须先调用initscr一样,start_color需要首先调用以初始化色素. 您用来定义自己的颜色对的函数是init_pair,当您使用它定义了一个颜色对后,它将会和您在函数中的设置的第一个参数联系起来. 在程序中,无论您什么时候需要用该颜色对,您只需用COLOR_PAIR调用该参数就可以了.
除了定义颜色对,您还必须使用函数来保证写入的使用是用不同的颜色对,attron和wattron可以满足您的要求. 使用这些函数将会用您选择的颜色对写入数据到相应的屏幕上,直到调用了attroff或者wattroff函数.
bkgd和wbkgd函数可以改变相应的整个窗体的颜色对,调用时,它将会改变窗体所有区域的前景色和背景色.也就 是说,在下一个刷新动作前,窗体上所有的区域将会使用新的颜色对重写.
使用刚才提到的那些函数man pages来得到详细的关于颜色资料和信息.
  
窗体的边框
您可以给您的程序里面的窗体一个很好看的边框,在库中有一个box宏函数可以替您做到这一点,和其他函数所 不同的是,没有wbox函数.box需要一个WINDOW指针来作为参数.
您可以在box的man pages页轻松获得详细的帮助,这里有一些需要注意的是,给一个窗体设置边框其实只是 在窗体的相应边框区域写入了一些字符.如果您在边框区域一下写如了某些数据,边框将会被中断. 解决的办法就是在您在原始窗体里面再建一个子窗体,将原始窗体放入到边框里面然后使用里面的子窗体作为需要的输入数据窗体.
  
功能键
为了能够使用功能键,必须在我们需要接受输入的窗体中设置_use_keypad标志位,keypad是一个能设置 _use_keypad值的函数,当您设置了_use_keypad后,您就可以使用键盘的功能键(快捷键),如同普通输入一样.
在这里,如果您想使用getch来作个简单接受数据输入的例子,您需要注意的是要将数据赋给整形变量(int)而不是 字符型(char).这是因为整形变量能容纳的功能键比字符型更多.您不需要知道这些功能键的值,您只需要使用库中定义的 宏名就可以了,在getch的man page中有这些数值的列表.
ncurses主页地址:
http://www.gnu.org/software/ncurses/


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/7913/showart_82993.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP