6.LinuxGUI编程-NCurses(一)新

合集下载

NCURSES库及其简单使用方法

NCURSES库及其简单使用方法

NCURSES库及其简单使用方法1、介绍在那个广泛使用电传打字机的年代,电传打字机作为中央电脑的输出终端,通过电缆和中央电脑连接。

用户要向终端程序发送一系列特定的控制命令,才可以控制终端屏幕的输出。

比如要在改变光标在屏幕上的位置,清除屏幕某一区域的内容,卷动屏幕,切换显示模式,给文字添加下划线,改变字符的外观、颜色、亮度等等。

这些控制都是通过一种叫做转义序列(escape sequence)的字符串实现的。

被叫做转义序列是因为这些连续字节都是以一个"0x1B"字符,即转义字符(按下ESC键所输入的字符)作为字符串的开头。

即使在现在,我们也可以通过向终端仿真程序输入转义序列得到与当年电传打字终端同样的输出效果。

如果你想在终端(或者终端仿真程序)屏幕输出一段背景是彩色的文字,可以将以下这段转义序列输入到你的命令行提示符:echo "^[[0;31;40mIn Color"在这里 "^[" 就是所谓的转义字符。

(注意:在这里 "^[" 是一个字符。

不是依次键入"^"和"["字符。

要打印出这个字符,你必须先按下Ctrl+V,然后按下ESC 键。

)执行以上的命令后。

你应该可以看见"In Color"的背景变为红色了。

从此以后显示的文本信息都是以这样的方式输出的。

如果想终止这种方式并回到原来的显示方式可以使用以下的命令:echo "^[[0;37;40m"现在知道这些字符(转移序列)的作用了吗?(译者注:更改分号之间的参数,看看会有什么结果。

)也许会和自己想像的不一样?可能是因为终端环境不同,终端环境取决于终端或操作系统的不同。

(译者注:你不可能让一个黑白终端显示出彩色字符吧?)为了避免这种不兼容情况,能够在不同的终端上输出统一的结果。

UNIX的设计者发明了一种叫做 termcap的机制。

ncurses解读 -回复

ncurses解读 -回复

ncurses解读-回复什么是ncurses?ncurses是一个用于在终端上创建图形用户界面(GUI)的库。

它提供了一套函数和工具,可以让开发者创建基于文本的用户界面,以及处理键盘和鼠标输入。

ncurses最初是Unix系统下的一个文本模式终端驱动程序,但后来发展成为一个功能强大的库,适用于各种操作系统。

为什么选择使用ncurses?1. 跨平台:ncurses可在不同操作系统和终端类型上工作,包括Unix、Linux、macOS等系统,以及VT100、xterm、Microsoft Windows终端等不同类型的终端。

2. 简化开发:ncurses提供了一套抽象的界面,使开发者无需了解底层终端控制序列就能创建功能丰富的用户界面。

这包括在屏幕上显示文本、颜色和图形,处理键盘和鼠标输入等。

3. 功能丰富:ncurses提供了丰富的功能,例如文本框、按钮、菜单、滚动窗口、对话框等,使开发者能够创建功能强大的终端应用程序。

4. 自定义性强:ncurses允许开发者自定义界面的外观和行为。

可以设置颜色、字体、光标形状等,以及定义快捷键和动作,从而为用户提供个性化的操作体验。

如何使用ncurses创建用户界面?使用ncurses创建用户界面可以分为以下步骤:1. 初始化:在创建用户界面之前,我们需要初始化ncurses库。

这可以通过调用`initscr()`函数来完成。

它会初始化屏幕并返回一个指向`WINDOW`结构的指针,代表整个屏幕。

2. 设置界面选项:接下来,我们可以通过调用`start_color()`函数启用颜色选项。

这将使我们能够使用不同的颜色来装饰界面元素。

还可以通过调用`curs_set()`函数来设置光标的可见性,以及调用`keypad()`函数来启用终端上的特殊键盘输入。

3. 创建窗口:使用`WINDOW`结构提供的函数,可以在屏幕上创建不同大小和位置的窗口。

可以使用`newwin()`函数创建一个新窗口,并使用`wprintw()`函数在窗口中打印文本。

7.LinuxGUI编程-NCurses(二)

7.LinuxGUI编程-NCurses(二)

keypad示例2-2
While (key != ERR && key != „q‟){ move(7,5); clrtoeol(); if( (key >= „A‟ && key <=„Z‟) || (key>=„a‟ && key<=„z‟)){ printw(“key was %c”,(char)key); } else { switch(key){ case KEY_END: printw(“%s”,”END_KEY”);break; case KEY_LEFT:printw(“%s”,”LEFT KEY”);break; case KEY_F(1): printw(“%s”,”F1 Key”);break; } } refresh(); key = getch(); } endwin(); }
函数名 getpartyx(WINDOW*,int,int) 描述 用于取得子窗口相对主窗口的起始坐标
getbegyx(WINDOW*,int,int)
获得指定窗口的起始坐标
getmaxyx(WINDOW*,int,int) 获得指定窗口的结束坐标
屏幕转储
开发游戏的时候,通常存储和恢复屏幕是十分必要的。 scr_dump()函数可以把当前屏幕的内容存入指定文件,即以 文件名作为函数的参数(函数原型:scr_dump(const char *file))。
颜色组合的索引
前景色
背景色
用下面的语句可以把绿色背景红色前景定义 为第一号颜色组合 init_pair(1,COLOR_RED,COLOR_GREEN)
curses定义的基本颜色
名称
COLOR_BLACK COLOR_RED COLOR_GREEN COLOR_YELLOW 黑色 红色 绿色 黄色

ncurses 手册

ncurses 手册

NCurses 是一个用于编写文本用户界面(TUI)的库。

它提供了一组函数和宏,用于在终端上创建窗口、按钮、菜单和其他常见的GUI 元素。

NCurses 手册是一个详细的文档,包含了NCurses 库的所有函数、数据类型、宏和选项的说明。

它提供了每个函数的使用方法、参数说明、返回值以及相关的示例代码。

要查看NCurses 手册,您可以在终端中使用以下命令:这将打开NCurses 手册的在线版本。

您可以使用箭头键和Page Up/Page Down 键来浏览手册,使用Q 键退出手册。

如果您无法访问在线手册,您还可以下载NCurses 手册的PDF 或其他格式的文档。

您可以在NCurses 的官方网站或其他文档下载网站上找到这些文档。

ncurse库的使用

ncurse库的使用

用curses库有个特点,就是要初始化一个窗口用函数initscr();后面要用函数endwin来说明窗口结束!我们现在知道了:在程序中调用initscr()函数,会让屏幕初始化并进入CURSES模式。

还有一些其它的函数可以根据我们自己的方案初始化CURSES。

不同的初始化函数可以让屏幕进入不同的显示模式。

比如:终端模式(terminal mode)、彩色模式(color mode)、鼠标模式(mouse mode)等等……通常情况下,用户输入的字符将被终端程序送入终端的缓冲区。

但当用户输入换行符时,终端程序将会中断,同时输出当前的缓冲区内容并启用新行的输出缓冲。

但是大多数程序需要当用户输入单个字符时,却希望这些字符能够立即显示在屏幕上。

这两个函数就是用来禁用行缓冲(line buffering)。

这两个函数所初始化的的模式同样可以用来给程序传送控制字符,比如:挂起(CTRL-Z)、中断或退出(CTRL-C)。

区别在于,在raw()函数模式下,这些字符将传送给程序去处理而不作为终端程序处理的信号。

在cbreak()模式下,这些控制字符将被认为是终端驱动程序中的控制字符,因而将这些字符传送给终端程序。

我比较喜欢使用raw(),那样可以进行更多的控制操作。

这两个函数控制用户输入的键盘回显。

就是在运行程序的时候是否将输入的字符出现在屏幕上。

比如你的程序在运行时你需要使用控制字符,但是你不想让控制字符出现在屏幕上,就可以使用这两个函数。

也就是说当用户调用getch()函数向程序输入数据时,你不想让他输入的字符出现在屏幕上。

noecho()函数就可以不让控制字符(比如CTRL-C)出现在屏幕上。

大多数的交互式程序要进入控制模式的时候,一般都使用echo()、noecho()函数初始化、关闭键盘回显。

这样给了程序员更大的灵活性。

这个函数允许使用功能键:F1、F2、方向键等等……几乎所有的交互式程序都使用这个函数。

零点起飞学Linux C之Linux GUI编程

零点起飞学Linux C之Linux GUI编程





gtk_window_new函数的返回值为指向GtkWidget结构的指针,即指 向新创建的窗口。后面对窗口的各种操作都通过该指针来实现。 gtk_widget_show函数用来显示窗口中的构件,它的一般形式为: void gtk_widget_show(GtkWidget *widget); 创建了新的构件,或者改变了构件属性时,必须调用该函数将其设 为可见。 gtk_main使程序进入事件循环,它的一般形式为: void gtk_main(void); 将窗口和所有的组件都显示到屏幕上之后,GTK+应用程序必须调 用该函数,使程序进入等待状态,等候事件的发生,例如单击界面 上的按钮、按下键盘上的某个键以及超时等。事件发生后,系统会 调用对应的回调函数来对事件进行处理。回调函数执行完成后,再 次返回到gtk_main函数,等待新的事件发生。 在程序的编译连接过程中,我们使用了pkg-config工具,用来生成编 译连接时必需的头文件和库文件列表。

GtkWindow构件是GTK+中最大的容器构件,但它只能容纳一个子构件。 GtkWindow构件的创建方法为: GtkWidget* gtk_window_new(GtkWindowType type); 对于应用程序的窗口,参数type一般设为GTK_WINDOW_TOPLEVEL。 该构件的部分函数前面已经介绍过了,例如gtk_container_set_border_width 函数、gtk_container_add函数等,接下来再给出两个常用函数。 (1)gtk_window_set_title函数用来设置或更改窗口的标题,它的一般形式 为: void gtk_window_set_title(GtkWindow *window, const gchar *title); 参数window为要设置或更改标题的窗口指针,参数title为一个字符串,即窗 口的标题。 (2)gtk_window_set_default_size函数用来设置窗口的默认大小,它的一般 形式为: void gtk_window_set_default_size(GtkWindow *window, gint width, gint height); 参数window为要设置的窗口指针,参数其中width和height为设置的宽度和 高度。

Linux(centos?6)安装R语言及R脚本运行

Linux(centos?6)安装R语言及R脚本运行

Linux(centos 6)安装R语言及R脚本运行1. 安装转载:/qibaoyuan/article/details/6827352R语言是主要用于统计分析、绘图的语言和操作环境。

官方网站:/Windows下面有直接的安装包,直接下载安装很方便,但是对于刚出的CentOS6.0上不能直接通过yum 安装R,需要自己编译。

下载页面:/mirrors/CRAN/在编译R之前,需要通过yum安装以下几个程序:#yum install gcc-gfortran #否则报”configure: error: No F77 compiler found”错误#yum install gcc gcc-c++ #否则报”configure: error: C++ preprocessor “/lib/cpp” fails sanity check”错误#yum install readline-devel #否则报”–with-readline=yes (default) and headers/libs are not available”错误#yum install libXt-devel #否则报”configure: error: –with-x=yes (default) and X11 headers/libs are not available”错误然后下载源代码,编译#cd#wget /mirrors/CRAN/src/base/R-2/R-2.13.1.tar.gz#tar zxvf R-2.13.1.tar.gz#cd R-2.13.1#./configure#make#make install即可完成编译安装。

自定义安装目录: ./configure --prefix=/data1/R2.使用:[jiawei4@secondnamenode183 task5]$ /data1/R-3.0.0/bin/RR version 3.0.0 (2013-04-03) -- "Masked Marvel"Copyright (C) 2013 The R Foundation for Statistical ComputingPlatform: x86_64-unknown-linux-gnu (64-bit)R is free software and comes with ABSOLUTELY NO WARRANTY.You are welcome to redistribute it under certain conditions.Type 'license()' or 'licence()' for distribution details.Natural language support but running in an English localeR is a collaborative project with many contributors.Type 'contributors()' for more information and'citation()' on how to cite R or R packages in publications.Type 'demo()' for some demos, 'help()' for on-line help, or 'help.start()' for an HTML browser interface to help.Type 'q()' to quit R.>3. 脚本运行:#cp /data1/R-3.0.0/bin/Rscript /bin/ #vi test.r#!/bin/Rscriptx<-10x# Rscript test.r[1] 10。

chapter10 Linux下的GUI编程

chapter10 Linux下的GUI编程

精通Linux C编程 精通Linux C编程
三、GTK+/GNOME编程 GTK+/GNOME编程
2、GTK+编程 GTK+编程
任何GTK程序都需要几个基本的函数和组成都分。首先你需要至少 包含头文件gtk.h。根据所使用的构件和函数,可能会需要其他的 GTK头文件。然后必须为想要使用的构件定义指针。随后需要利用 gtk_initt函数初始化GTK库。做完这些以后,就可以利用GTK函数定 义构件,并将它们的地址赋给开始定义的指针。然后,可以利用GTK 函数为构件指定动作和属性,如显示它们。例如,一个关闭方框 (Close box)的事件delete_event绑定到窗口和函数 gtk_main_quit。因此,如果一个用户点击了窗口中的关闭方框 (Close box),程序结束。最后,利用gtk_main函数运行构件。
个能够简化应用程序设计的跳板。 --OpenLook。OpenLook是Sun公司产品的一个免费的工具包,它强调了一种另类的观 感。它是在一个为Xview的函数库上面建立起来的,这个库与Xt很相似。 --Motif。Motif是OSF组织的一个标准,设计目的是为UNIX桌面提供统一的观感。 Motif分为两个主要部分:一组用来定义Xt函数中使用的各种常数的头文件和一个用 来简化对话框和菜单等元素的创建工作的易于使用的函数库。Motif还定义了一种程 序设计风格,不管程序员是否使用Motif工具包,都可以参照它来设计自己的程序。 --Qt。Qt是一个由Trolltech公司出品的函数库,它构成了KDE桌面环境的基础,在大 多数Linux发行版本里都能找到它。Qt编程依赖于大量的C++类集,通常其中每个类 都有一大批成员函数来处理类对象。 --GTK+。GTK+就是GIMP工具包,它是GNOME系统的基石。下面我们将详细介绍如何对 这个高级环境进行程序设计。

Linux操作系统应用编程课件(完整版)

Linux操作系统应用编程课件(完整版)

2.Linux操作系统的发行版
Linux操作系统发行版实际就是Linux内核加上外围实用程序 组成的一个大软件包。相对于Linux操作系统的内核版本,发行版 的版本号随发布者的不同而不同,与Linux操作系统内核的版本号 是相对独立的。因此把SUSE、RedHat、Ubuntu、Slackware等直 接称为Linux是不确切的,它们是Linux操作系统的发行版。更确 切地说,应该将它们称为“以Linux为核心的操作系统软件包”。
Shell是Linux操作系统的一种用户界面,它作为操作系统 的“外壳”,为用户提供使用操作系统的接口。Shell主要有以 下两大功能特点。
(1)Shell是一个命令解释器,它拥有自己内建的Shell命令集。 (2)Shell的另一个重要特性是它自身就是一种解释型的程序设 计语言。
当用户成功登录Linux系统后,系统将执行一个Shell程序。 正是Shell进程提供了命令提示符。作为默认值,Shell对普通用 户用“$”作提示符,对超级用户(root)用“#”作提示符。
1.4.4 联机手册
联机手册命令man可向用户提供系统中各种命令、系统调用、 库函数和重要系统文件的详细说明,包括名字、使用语法、功能 描述、应用实例和相关参考文件等。其格式如下:
$ man [拥有哪个级别的帮助。 -k:查看和命令相关的所有帮助。
查看who命令的详细说明示例如下。 $ man who
Linux操作系统 应用编程
本章主要介绍Linux文件系统,包括文件系统的结构、文 件的定义与分类、目录与文件操作命令、文件的权限管理等, 让读者对Linux文件系统有一定的认识和理解,为后文的学习 打下基础。
2.1.1 组织结构
Linux操作系统中所有文件存储在文件系统中,文件被组织 到一棵“目录树”中,其文件系统层次结构(树状目录结构)如 图2.1所示。树根在该层次结构的顶部,树根的下方衍生出子目 录分支。

嵌入式Linux下GUI的编程

嵌入式Linux下GUI的编程

嵌入式Linux下GUI的编程1嵌入式linux (2)1.1、什么是嵌入式Linux (2)1.2 Linux成为优秀嵌入式OS的必然性 (2)1.3、嵌入式Linux的特点 (2)2常见的硬件平台架构 (3)3 面向嵌入式Linux系统的图形用户库 (3)3.1 MicoroWindows/NanoX (3)3.2 OpenGUI (4)3.3 Qt/Embedded (4)3.4 MiniGUI (6)3.5 Tiny-X与FL TK (7)4 fltk编程 (7)1嵌入式linux1.1、什么是嵌入式Linux嵌入式Linux(Embedded Linux)是指对Linux经过小型化裁剪后,能够固化在容量只有几十万字节或几十亿字节的存储器芯片或单片机中,应用于特定嵌入式场合的专用Linux操作系统[7]。

1.2 Linux成为优秀嵌入式OS的必然性Linux成为优秀的嵌入式操作系统,有其自身的必然性,这种必然性的根源在于自由软件的开发模式和开放性。

自由软件的由一个标准组织控制,全世界范围软件人员并行开发的方式造就了Linux可剪裁的内核结构,而可剪裁性恰恰是将Linux与嵌入式系统紧密联系在一起的纽带,另一方面嵌入式系统对成本的严格限制也使得具备开放特征的Linux超越其它诸如Vxwork、pSOS、Neculeus和Windowss CE等强劲竞争对手成为市场占有率第一的嵌入式操作系统。

1.3、嵌入式Linux的特点嵌入式Linux操作系统产品在2000年开始涌现,短短一年之后,嵌入式Linux操作系统达到了整个嵌入式操作系统市场的1/4。

人们惊呼,没想到Linux行业的赢利竟然是从嵌入式Linux系统开始的!Linux在嵌入式系统领域能取得成功有以下几点原因:1性能稳定,功能强大,占用资源较少。

Linux是按照POSIX标准编写的,许多源代码借鉴了UNIX,。

2模块的动态加载,独特的内核结构和工作方式使Linux非常适合于工作在嵌入式系统中。

ncurses参考资料

ncurses参考资料

NCURSES 函数简要参考BenBear目录说明简介初始化与结束基本输入、输出函数预览函数命名、参数习惯getch()窗口 WINDOW颜色Panel、Menus 和 Forms其它参考资料说明在这里写下对 NCURSES 库使用的经验,希望对你有用。

由于条件的不足,我只是在 WMware Workstation 4.0.5 里安装的 Debian Linux 3.0 r2 下使用过 NCURSES,所以这里所说的片面性在所难免,还请细查。

如有问题,你可以给我发邮件:cxj1024@。

简介NCURSES 是 Linux 下进行终端界面开发的库,其功能相当强大。

它以WINDOW(窗口)为基本要素,在此基础上支持 Panel、Memus 及 Forms 等更加强大的元素。

更多的信息请参考资料。

初始化与结束当然了,为了使用 NCURSES 库,你应该 #include <curses.h>,在编译时,应该加上 -lncurses。

在使用 NCURSES 库前,必须先行初始化;用完后必须结束,否则终端可能会不正常。

初始化是一系列的动作,内容有关功能键、输入回显、换行符、颜色等。

一般地,第一个函数调用必须是 initscr()。

这个函数初始化终端,然后清屏。

它的参数为空,返回值一般也不用管。

它会初始化一个叫 stdscr 的变量,stdscr 有点像 stdin 或 stdout 的地位,它是 NCURSES 默认的窗口。

紧接着 initscr() 的应该是其它初始化,下面一一介绍。

即时按键。

raw() 和 cbreak() 两个函数都是用来关闭行缓冲以使按键可以马上被程序处理的。

只是 cbreak() 可以在按 Ctrl-C 的时候退出程序,我一般用这个。

两个函数都无参数。

使用功能键。

keypad() 可以用来打开一个窗口的功能键,从来使程序可以识别 F1、F2、Up、Down 等这样的按键。

linux gui编程例子

linux gui编程例子

linux gui编程例子以下是一个简单的Linux GUI编程例子,使用GTK+库和C语言。

```c#include <gtk/gtk.h>// 按钮点击事件回调函数void button_clicked(GtkWidget *widget, gpointer data) {g_print("Hello World!\n");}int main(int argc, char *argv[]) {GtkWidget *window;GtkWidget *button;// 初始化GTK+gtk_init(&argc, &argv);// 创建窗口window = gtk_window_new(GTK_WINDOW_TOPLEVEL);gtk_window_set_title(GTK_WINDOW(window), "Hello GTK+");gtk_container_set_border_width(GTK_CONTAINER(window), 10);// 创建按钮button = gtk_button_new_with_label("Click Me");// 将按钮添加到窗口中gtk_container_add(GTK_CONTAINER(window), button);// 连接按钮的点击事件回调函数g_signal_connect(button, "clicked", G_CALLBACK(button_clicked),NULL);// 显示所有控件gtk_widget_show_all(window);// 进入GTK+主循环gtk_main();return 0;}```将上述代码保存为`main.c`文件,并使用以下命令进行编译:```gcc -o main main.c `pkg-config --cflags --libs gtk+-3.0````然后运行生成的可执行文件:```./main```这个例子创建了一个包含一个按钮的窗口。

ncurses 函数

ncurses 函数

ncurses 函数ncurses函数是一种用于控制终端屏幕显示的库函数,在Linux系统中被广泛应用于开发命令行界面程序。

本文将介绍ncurses函数的基本使用方法和一些常见的应用场景。

一、ncurses函数的基本概念和使用方法1. 初始化屏幕在使用ncurses函数前,需要先调用initscr()函数来初始化屏幕。

这个函数会清空屏幕并分配一些内存用于存储屏幕缓冲区。

在程序结束时,需要调用endwin()函数来释放这些内存。

2. 控制光标位置使用move(row, col)函数可以将光标移动到指定的行和列,其中行和列的编号从0开始。

可以使用getmaxyx(stdscr, maxrow, maxcol)函数获取屏幕的行数和列数。

3. 输出文本使用printw(format, ...)函数可以在当前光标位置输出文本。

其中format参数用于指定输出的格式,可以包含占位符和格式化字符串。

可以使用mvprintw(row, col, format, ...)函数在指定位置输出文本。

4. 获取用户输入使用getch()函数可以从终端读取用户输入的一个字符。

可以使用keypad(stdscr, TRUE)函数打开功能键模式,使得可以读取特殊按键(如方向键、回车键等)的输入。

5. 清空屏幕使用clear()函数可以清空屏幕上的所有内容。

使用refresh()函数可以将屏幕缓冲区中的内容刷新到实际屏幕上。

二、ncurses函数的常见应用场景1. 文本编辑器通过使用ncurses函数,可以在终端中实现一个简单的文本编辑器。

可以使用move()函数控制光标位置,使用printw()函数输出文本,使用getch()函数读取用户输入,以及使用clear()和refresh()函数来清空和刷新屏幕。

2. 游戏开发ncurses函数可以用于开发终端中的文字游戏。

可以使用move()函数和printw()函数来输出游戏地图和角色信息,使用getch()函数来读取用户的操作输入,以及使用clear()和refresh()函数来更新屏幕内容。

C语言编程之 UNIX常用库函数

C语言编程之  UNIX常用库函数

UNIX(Linux)系统编程常用库函数说明(阅览 4167 次)作者:169 时间:2000-02-25.19:07:14※ 来源: 绿色兵团UNIX系统为程序员提供了许多子程序,这些子程序可存取各种安全属性.有些是信息子程序,返回文件属性,实际的和有效的UID,GID等信息.有些子程序可改变文件属性.UID,GID等有些处理口令文件和小组文件,还有些完成加密和解密.本文主要讨论有关系统子程序,标准C库子程序的安全,如何写安全的C程序并从root的角度介绍程序设计(仅能被root调用的子程序).1.系统子程序(1)I/O子程序*creat():建立一个新文件或重写一个暂存文件.需要两个参数:文件名和存取许可值(8进制方式).如:creat("/usr/pat/read_write",0666) /* 建立存取许可方式为0666的文件 */调用此子程序的进程必须要有建立的文件的所在目录的写和执行许可,置给creat()的许可方式变量将被umask()设置的文件建立屏蔽值所修改,新文件的所有者和小组由有效的UID 和GID决定.返回值为新建文件的文件描述符.*fstat():见后面的stat().*open():在C程序内部打开文件.需要两个参数:文件路径名和打开方式(I,O,I&O).如果调用此子程序的进程没有对于要打开的文件的正确存取许可(包括文件路径上所有目录分量的搜索许可),将会引起执行失败.如果此子程序被调用去打开不存在的文件,除非设置了O_CREAT标志,调用将不成功.此时,新文件的存取许可作为第三个参数(可被用户的umask修改).当文件被进程打开后再改变该文件或该文件所在目录的存取许可,不影响对该文件的I/O操作.*read():从已由open()打开并用作输入的文件中读信息.它并不关心该文件的存取许可.一旦文件作为输入打开,即可从该文件中读取信息.*write():输出信息到已由open()打开并用作输出的文件中.同read()一样它也不关心该文件的存取许可.(2)进程控制*exec()族:包括execl(),execv(),execle(),execve(),execlp()和execvp()可将一可执行模快拷贝到调用进程占有的存贮空间.正被调用进程执行的程序将不复存在,新程序取代其位置.这是UNIX系统中一个程序被执行的唯一方式:用将执行的程序复盖原有的程序.安全注意事项:. 实际的和有效的UID和GID传递给由exec()调入的不具有SUID和SGID许可的程序.. 如果由exec()调入的程序有SUID和SGID许可,则有效的UID和GID将设置给该程序的所有者或小组.. 文件建立屏蔽值将传递给新程序.. 除设了对exec()关闭标志的文件外,所有打开的文件都传递给新程序.用fcntl()子程序可设置对exec()的关闭标志.*fork():用来建立新进程.其建立的子进程是与调用fork()的进程(父进程)完全相同的拷贝(除了进程号外)安全注意事项:. 子进程将继承父进程的实际和有效的UID和GID.. 子进程继承文件方式建立屏蔽值.. 所有打开的文件传给子进程.*signal():允许进程处理可能发生的意外事件和中断,需要两个参数:信号编号和信号发生时要调用的子程序.信号编号定义在signal.h中.信号发生时要调用的子程序可由用户编写,也可用系统给的值,如:SIG_IGN 则信号将被忽略,SIG_DFL则信号将按系统的缺省方式处理.如许多与安全有关的程序禁止终端发中断信息(BREAK和DELETE),以免自己被用户终端终止运行.有些信号使UNIX系统的产生进程的核心转储(进程接收到信号时所占内存的内容,有时含有重要信息),此系统子程序可用于禁止核心转储.(3)文件属性*access():检测指定文件的存取能力是否符合指定的存取类型.需要两个参数:文件名和要检测的存取类型(整数).存取类型定义如下:0: 检查文件是否存在1: 检查是否可执行(搜索)2: 检查是否可写3: 检查是否可写和执行4: 检查是否可读5: 检查是否可读和执行6: 检查是否可读可写可执行这些数字的意义和chmod命令中规定许可方式的数字意义相同.此子程序使用实际的UID和GID检测文件的存取能力(一般有效的UID和GID 用于检查文件存取能力).返回值: 0:许可 -1:不许可.*chmod():将指定文件或目录的存取许可方式改成新的许可方式.需要两个参数:文件名和新的存取许可方式.*chown():同时改变指定文件的所有者和小组的UID和GID.(与chown命令不同).由于此子程序同时改变文件的所有者和小组,故必须取消所操作文件的SUID 和SGID许可,以防止用户建立SUID和SGID程序,然后运行chown()去获得别人的权限.*stat():返回文件的状态(属性).需要两个参数:文件路径名和一个结构指针,指向状态信息的存放的位置.结构定义如下:st_mode: 文件类型和存取许可方式st_ino: I节点号st_dev: 文件所在设备的IDst_rdev: 特别文件的IDst_nlink: 文件链接数st_uid: 文件所有者的UIDst_gid: 文件小组的GIDst_size: 按字节计数的文件大小st_atime: 最后存取时间(读)st_mtime: 最后修改时间(写)和最后状态的改变st_ctime: 最后的状态修改时间返回值: 0:成功 1:失败*umask():将调用进程及其子进程的文件建立屏蔽值设置为指定的存取许可.需要一个参数: 新的文件建立屏值.(4)UID和GID的处理*getuid():返回进程的实际UID.*getgid():返回进程的实际GID.以上两个子程序可用于确定是谁在运行进程.*geteuid():返回进程的有效UID.*getegid():返回进程的有效GID.以上两个子程序可在一个程序不得不确定它是否在运行某用户而不是运行它的用户的SUID 程序时很有用,可调用它们来检查确认本程序的确是以该用户的SUID许可在运行.*setuid():用于改变有效的UID.对于一般用户,此子程序仅对要在有效和实际的UID之间变换的SUID程序才有用(从原有效UID变换为实际UID),以保护进程不受到安全危害.实际上该进程不再是SUID方式运行. *setgid():用于改变有效的GID.2.标准C库(1)标准I/O*fopen():打开一个文件供读或写,安全方面的考虑同open()一样.*fread(),getc(),fgetc(),gets(),scanf()和fscanf():从已由fopen()打开供读的文件中读取信息.它们并不关心文件的存取许可.这一点同read().*fwrite(),put(),fputc(),puts,fputs(),printf(),fprintf():写信息到已由fopen()打开供写的文件中.它们也不关心文件的存取许可.同write().*getpass():从终端上读至多8个字符长的口令,不回显用户输入的字符.需要一个参数: 提示信息.该子程序将提示信息显示在终端上,禁止字符回显功能,从/dev/tty读取口令,然后再恢复字符回显功能,返回刚敲入的口令的指针.*popen():将在(5)运行shell中介绍.(2)/etc/passwd处理有一组子程序可对/etc/passwd文件进行方便的存取,可对文件读取到入口项或写新的入口项或更新等等.*getpwuid():从/etc/passwd文件中获取指定的UID的入口项.*getpwnam():对于指定的登录名,在/etc/passwd文件检索入口项.以上两个子程序返回一指向passwd结构的指针,该结构定义在/usr/include/pwd.h中,定义如下:struct passwd {char * pw_name; /* 登录名 */char * pw_passwd; /* 加密后的口令 */uid_t pw_uid; /* UID */gid_t pw_gid; /* GID */char * pw_age; /* 代理信息 */char * pw_comment; /* 注释 */char * pw_gecos;char * pw_dir; /* 主目录 */char * pw_shell; /* 使用的shell */};*getpwent(),setpwent(),endpwent():对口令文件作后续处理.首次调用getpwent(),打开/etc/passwd并返回指向文件中第一个入口项的指针,保持调用之间文件的打开状态.再调用getpwent()可顺序地返回口令文件中的各入口项.调用setpwent()把口令文件的指针重新置为文件的开始处.使用完口令文件后调用endpwent()关闭口令文件.*putpwent():修改或增加/etc/passwd文件中的入口项.此子程序将入口项写到一个指定的文件中,一般是一个临时文件,直接写口令文件是很危险的.最好在执行前做文件封锁,使两个程序不能同时写一个文件.算法如下:. 建立一个独立的临时文件,即/etc/passnnn,nnn是PID号.. 建立新产生的临时文件和标准临时文件/etc/ptmp的链,若建链失败,则为有人正在使用/etc/ptmp,等待直到/etc/ptmp可用为止或退出.. 将/etc/passwd拷贝到/etc/ptmp,可对此文件做任何修改.. 将/etc/passwd移到备份文件/etc/opasswd.. 建立/etc/ptmp和/etc/passwd的链.. 断开/etc/passnnn与/etc/ptmp的链.注意:临时文件应建立在/etc目录,才能保证文件处于同一文件系统中,建链才能成功,且临时文件不会不安全.此外,若新文件已存在,即便建链的是root用户,也将失败,从而保证了一旦临时文件成功地建链后没有人能再插进来干扰.当然,使用临时文件的程序应确保清除所有临时文件,正确地捕捉信号.(3)/etc/group的处理有一组类似于前面的子程序处理/etc/group的信息,使用时必须用include语句将/usr/include/grp.h文件加入到自己的程序中.该文件定义了group结构,将由getgrnam(),getgrgid(),getgrent()返回group结构指针.*getgrnam():在/etc/group文件中搜索指定的小组名,然后返回指向小组入口项的指针. *getgrgid():类似于前一子程序,不同的是搜索指定的GID.*getgrent():返回group文件中的下一个入口项.*setgrent():将group文件的文件指针恢复到文件的起点.*endgrent():用于完成工作后,关闭group文件.*getuid():返回调用进程的实际UID.*getpruid():以getuid()返回的实际UID为参数,确定与实际UID相应的登录名,或指定一UID为参数.*getlogin():返回在终端上登录的用户的指针.系统依次检查STDIN,STDOUT,STDERR是否与终端相联,与终端相联的标准输入用于确定终端名,终端名用于查找列于/etc/utmp文件中的用户,该文件由login维护,由who程序用来确认用户.*cuserid():首先调用getlogin(),若getlogin()返回NULL指针,再调用getpwuid(getuid()).*以下为命令:*logname:列出登录进终端的用户名.*who am I:显示出运行这条命令的用户的登录名.*id:显示实际的UID和GID(若有效的UID和GID和实际的不同时也显示有效的UID和GID)和相应的登录名.(4)加密子程序1977年1月,NBS宣布一个用于美国联邦政府ADP系统的网络的标准加密法:数据加密标准即DES用于非机密应用方面.DES一次处理64BITS的块,56位的加密键.*setkey(),encrypt():提供用户对DES的存取.此两子程序都取64BITS长的字符数组,数组中的每个元素代表一个位,为0 或1.setkey()设置将按DES处理的加密键,忽略每第8位构成一个56位的加密键.encrypt()然后加密或解密给定的64BITS长的一块,加密或解密取决于该子程序的第二个变元,0:加密 1:解密. *crypt():是UNIX系统中的口令加密程序,也被/usr/lib/makekey命令调用.Crypt()子程序与crypt命令无关,它与/usr/lib/makekey一样取8个字符长的关键词,2个salt字符.关键词送给setkey(),salt字符用于混合encrypt()中的DES算法,最终调用encrypt()重复25次加密一个相同的字符串. 返回加密后的字符串指针.(5)运行shell*system():运行/bin/sh执行其参数指定的命令,当指定命令完成时返回.*popen():类似于system(),不同的是命令运行时,其标准输入或输出联到由 popen()返回的文件指针.二者都调用fork(),exec(),popen()还调用pipe(),完成各自的工作,因而fork()和exec()的安全方面的考虑开始起作用.3.写安全的C程序一般有两方面的安全问题,在写程序时必须考虑:(1)确保自己建立的任何临时文件不含有机密数据,如果有机密数据,设置临时文件仅对自己可读/写.确保建立临时文件的目录仅对自己可写.(2)确保自己要运行的任何命令(通过system(),popen(),execlp(), execvp()运行的命令)的确是自己要运行的命令,而不是其它什么命令,尤其是自己的程序为SUID或SGID许可时要小心.第一方面比较简单,在程序开始前调用umask(077).若要使文件对其他人可读,可再调chmod(),也可用下述语名建立一个"不可见"的临时文件.Creat("/tmp/xxx",0);file=open("/tmp/xxx",O_RDWR);unlink("/tmp/xxx");文件/tmp/xxx建立后,打开,然后断开链,但是分配给该文件的存储器并未删除,直到最终指向该文件的文件通道被关闭时才被删除.打开该文件的进程和它的任何子进程都可存取这个临时文件,而其它进程不能存取该文件,因为它在/tmp中的目录项已被unlink()删除.第二方面比较复杂而微妙,由于system(),popen(),execlp(),execvp()执行时,若不给出执行命令的全路径,就能"骗"用户的程序去执行不同的命令.因为系统子程序是根据PATH变量确定哪种顺序搜索哪些目录,以寻找指定的命令,这称为SUID陷井.最安全的办法是在调用system()前将有效UID改变成实际UID,另一种比较好的方法是以全路径名命令作为参数.execl(),execv(), execle(),execve()都要求全路径名作为参数.有关SUID陷井的另一方式是在程序中设置PATH,由于system()和popen()都启动shell,故可使用shell句法.如:system("PATH=/bin:/usr/bin cd");这样允许用户运行系统命令而不必知道要执行的命令在哪个目录中,但这种方法不能用于execlp(),execvp()中,因为它们不能启动shell执行调用序列传递的命令字符串.关于shell解释传递给system()和popen()的命令行的方式,有两个其它的问题:*shell使用IFS shell变量中的字符,将命令行分解成单词(通常这个shell变量中是空格,tab,换行),如IFS中是/,字符串/bin/ed被解释成单词bin,接下来是单词ed,从而引起命令行的曲解.再强调一次:在通过自己的程序运行另一个程序前,应将有效UID改为实际的UID,等另一个程序退出后,再将有效UID改回原来的有效UID.SUID/SGID程序指导准则(1)不要写SUID/SGID程序,大多数时候无此必要.(2)设置SGID许可,不要设置SUID许可.应独自建立一个新的小组.(3)不要用exec()执行任何程序.记住exec()也被system()和popen()调用.. 若要调用exec()(或system(),popen()),应事先用setgid(getgid())将有效GID置加实际GID.. 若不能用setgid(),则调用system()或popen()时,应设置IFS: popen("IFS=\t\n;export IFS;/bin/ls","r");. 使用要执行的命令的全路径名.. 若不能使用全路径名,则应在命令前先设置PATH:popen("IFS=\t\n;export IFS;PATH=/bin:/usr/bin;/bin/ls","r");. 不要将用户规定的参数传给system()或popen();若无法避免则应检查变元字符串中是否有特殊的shell字符.. 若用户有个大程序,调用exec()执行许多其它程序,这种情况下不要将大程序设置为SGID 许可.可以写一个(或多个)更小,更简单的SGID程序执行必须具有SGID许可的任务,然后由大程序执行这些小SGID程序.(4)若用户必须使用SUID而不是SGID,以相同的顺序记住(2),(3)项内容,并相应调整.不要设置root的SUID许可.选一个其它户头.(5)若用户想给予其他人执行自己的shell程序的许可,但又不想让他们能读该程序,可将程序设置为仅执行许可,并只能通过自己的shell程序来运行.编译,安装SUID/SGID程序时应按下面的方法(1)确保所有的SUID(SGID)程序是对于小组和其他用户都是不可写的,存取权限的限制低于4755(2755)将带来麻烦.只能更严格.4111(2111)将使其他人无法寻找程序中的安全漏洞.(2)警惕外来的编码和make/install方法. 某些make/install方法不加选择地建立SUID/SGID程序.. 检查违背上述指导原则的SUID/SGID许可的编码.. 检查makefile文件中可能建立SUID/SGID文件的命令.4.root程序的设计有若干个子程序可以从有效UID为0的进程中调用.许多前面提到的子程序,当从root进程中调用时,将完成和原来不同的处理.主要是忽略了许可权限的检查.由root用户运行的程序当然是root进程(SUID除外),因有效UID用于确定文件的存取权限,所以从具有root的程序中,调用fork()产生的进程,也是root进程.(1)setuid():从root进程调用setuid()时,其处理有所不同,setuid()将把有效的和实际的UID都置为指定的值.这个值可以是任何整型数.而对非root 进程则仅能以实际UID或本进程原来有效的UID为变量值调用setuid().(2)setgid():在系统进程中调用setgid()时,与setuid()类似,将实际和有效的GID都改变成其参数指定的值.* 调用以上两个子程序时,应当注意下面几点:. 调用一次setuid()(setgid())将同时设置有效和实际UID(GID),独立分别设置有效或实际UID(GID)固然很好,但无法做到这点.. Setuid()(setgid())可将有效和实际UID(GID)设置成任何整型数,其数值不必一定与/etc/passwd(/etc/group)中用户(小组)相关联.. 一旦程序以一个用户的UID了setuid(),该程序就不再做为root运行,也不可能再获root 特权.(3)chown():当root进程运行chown()时,chown()将不删除文件的SUID和/或SGID许可,但当非root进程运行chown()时,chown()将取消文件的SUID和/或SGID许可.(4)chroot():改变进程对根目录的概念,调用chroot()后,进程就不能把当前工作目录改变到新的根目录以上的任一目录,所有以/开始的路径搜索,都从新的根目录开始.(5)mknod():用于建立一个文件,类似于creat(),差别是mknod()不返回所打开文件的文件描述符,并且能建立任何类型的文件(普通文件,特殊文件,目录文件).若从非root进程调用mknod()将执行失败,只有建立FIFO特别文件(有名管道文件)时例外,其它任何情况下,必须从root进程调用mknod().由于creat()仅能建立普通文件,mknod()是建立目录文件的唯一途径,因而仅有root能建立目录,这就是为什么mkdir命令具有SUID许可并属root所有. 一般不从程序中调用mknod().通常用/etc/mknod命令建立特别设备文件而这些文件一般不能在使用着时建立和删除,mkdir命令用于建立目录.当用 mknod()建立特别文件时,应当注意确从所建的特别文件不允许存取内存, 磁盘,终端和其它设备.(6)unlink():用于删除文件.参数是要删除文件的路径名指针.当指定了目录时,必须从root进程调用unlink(),这是必须从root进程调用unlink()的唯一情况,这就是为什么rmdir命令具有root的SGID许可的原因.(7)mount(),umount():由root进程调用,分别用于安装和拆卸文件系统.这两个子程序也被mount和umount命令调用,其参数基本和命令的参数相同.调用mount(),需要给出一个特别文件和一个目录的指针,特别文件上的文件系统就将安装在该目录下,调用时还要给出一个标识选项,指定被安装的文件系统要被读/写(0)还是仅读(1).umount()的参数是要一个要拆卸的特别文件的指针.。

8.LinuxGUI编程-NCurses(一)

8.LinuxGUI编程-NCurses(一)

scanw例子
#include <ncurses.h> #include <string.h> int main() { char mesg[]="Enter a string: "; /* 将要被打印的字符串信息*/ char str[80]; int row,col; /* 存储行号和列号的变量,用于指定光标位置*/ initscr(); /* 进入curses 模式*/ getmaxyx(stdscr,row,col); /* 取得stdscr 的行数和列数*/ mvprintw(row/2,(col-strlen(mesg))/2,"%s",mesg); /* 在屏幕的正中打 印字符串mesg */ scanw(“%s”,str); /* 将指针str 指向读取的字符串*/ mvprintw(2,0, "You Entered: %s", str); getch(); endwin(); return 0; }
refresh() 函数
在使用printw 函数打印“Hello World!!!”时, 实际上这个消息打印到了一个叫作“stdscr”的虚 拟窗口上,没有被直接输出到屏幕上。 printw()函数的作用是不断将一些显示标记和相关 的数据结构写在虚拟显示器上,并将这些数据写入 stdscr 的缓冲区内。 为了显示这些缓冲区中的数据我们必须使用 refresh()函数告诉curses系统将缓冲区的内容 输出到屏幕上。
getstr()
• •
功能说明:获取用户输入的字符串 原型:
int getstr (char *string);
获取到的字符串
getstr对它返回的字符串长度没有限制,所以在使用这个函数 时必须多加小心

Linux中终端图形编程库curses库使用教程

Linux中终端图形编程库curses库使用教程

1.1什么是cursescurses实际上是一个函数开发包,专门用来进行UNIX下终端环境下的屏幕界面处理以及I/O处理。

通过这些函数库,C和C++程序就可以控制终端的视频显示以及输入输出。

使用curses包中的函数,用户可以非常方便的创建和操作窗口,使用菜单以及表单,而且最为重要的一点是使用curses包编写的程序将独立于各种具体的终端,这样的一个直接的好处就是程序具有良好的移植性.这一点在网络上显得尤其重要,因为你面对的可能是上百种终端,如果为每一个终端都专门重新编写一套新的程序,那么复杂程度出乎想象,而且几乎不可能。

为了能够达到这样的目的,curses包使用了终端描述数据库(Terminal Description Databases)terminfo(TERMinal INFOrmation database)或者termcap(TERMinal CAPabilitie database),这两个数据库里存放了不同终端的操作控制码和转义序列以及其余相关信息,这样当使用每一个终端的时候,curses将首先在终端描述数据库中查找是否存在该类型的终端描述信息,如果找到则进行适当的处理.如果数据库中没有这种终端信息,则程序无法在该终端上运行,除非用户自己增加新的终端描述。

具体的如何在终端描述数据库中增加自定义终端在第八章“terminfo数据库"中有详细的介绍。

1。

1。

1 curses发展历史curses是怎么来的?curses的名称起源于“cursor optimization”,即光标优化的意思。

它最早是由巴克利大学的Bill Joy和Ken Arnold发展而来,主要是处理游戏rogue的屏幕界面。

rogue是一个古老的基于文本的的冒险类游戏。

在当时,仅仅控制游戏屏幕的外观显示就需要编写大量的代码,因为它们使用的是古老的termios甚至是tty接口。

巨大的工作量迫使Bill Joy和Ken Arnold将rogue游戏中的所有的屏幕处理和光标移动的函数汇集到一个函数库中。

ncurses解读 -回复

ncurses解读 -回复

ncurses解读-回复【ncurses解读】以中括号内的内容为主题,写一篇1500-2000字文章,一步一步回答。

第一步:理解ncurses是什么ncurses是一个开源的、跨平台的终端窗口管理库,用于在命令行界面上创建交互式的图形化程序。

它提供了用于构建文本用户界面(TUI)的API,并支持多种操作系统,如Linux、Unix和Windows。

第二步:ncurses的历史和发展ncurses最早是在20世纪80年代初由Eric S. Raymond开发的兼容性终端控制库的一部分。

随着时间的推移,并由于开源社区的积极贡献,ncurses逐渐发展成了一个功能丰富且稳定的库,并迅速成为Unix-like 操作系统上开发终端应用程序的首选方案。

第三步:ncurses的特点和优势1. 跨平台性:ncurses支持多种操作系统,包括Linux、Unix和Windows 等。

2. 可移植性:ncurses采用了抽象层面的API,使得开发者可以编写与特定终端无关的代码,从而实现对各种终端的兼容性。

3. 支持多线程:ncurses库可以在多线程环境下安全使用,这使得同时处理多个终端窗口成为可能。

4. 功能丰富:ncurses提供了大量的API函数,可以进行文本、图形和输入输出的处理,包括文本样式设置、光标控制、窗口划分、用户输入响应等。

5. 支持全面:ncurses可以对终端进行高度定制,包括窗口布局、颜色配置和键盘映射等。

6. 开源社区支持:ncurses拥有一个活跃的开源社区,提供了持续的更新和维护,以解决各种问题和改进。

第四步:ncurses常用函数介绍1. initscr():初始化标准窗口并进入curses模式。

2. endwin():退出curses模式并还原终端设置。

3. printw():在当前光标位置打印字符串。

4. mvprintw():在指定坐标位置打印字符串。

5. refresh():刷新窗口以显示最新更改。

Ncurses简介

Ncurses简介

Ncurses是一个能提供功能键定义(快捷键),屏幕绘制以及基于文本终端的图形互动功能的动态库什么是Ncurses您希望您的程序有一个彩色的界面吗Ncurses是一个能提供基于文本终端窗口功能的动态库. Ncurses可以:•只要您喜欢,您可以使用整个屏幕•创建和管理一个窗口•使用8种不同的彩色•为您的程序提供鼠标支持•使用键盘上的功能键Ncurses可以在任何遵循ANSI/POSIX标准的UNIX系统上运行,除此之外,它还可以从系统数据库中检测终端的属性, 并且自动进行调整,提供一个不受终端约束的接口.因此,Ncurses可以在不同的系统平台和不同的终端上工作的非常好.mc工具集就是一个用ncurses写的很好的例子,而且在终端上系统核心配置的界面同样是用ncurses编写的. 下面就是它们的截图:哪里可以下载Ncurses是基于GNU/Linux发展的,请访问以获得最新的更新版本或者其他详细信息以及相关链接 . 基础知识为了能够使用ncurses库,您必须在您的源程序中将包括(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之后,您就可以随便使用了.刷新屏幕:refreshWINDOW结构不会经常保持同一高度宽度以及在窗体中的位置,但是会保持在窗体中的内容.当您向窗体写入数据时, 会改变窗体中的内容,但并不意味着在屏幕中会立即显示出来,要更新屏幕内容,必须调用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的一个宏函数,专门用来处理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定义菜单,菜单中的一个选择项都会被证明选种. 这个程序比较有意思的一面就是使用了ncurses的窗体来达到菜单效果.您可以看下面的屏幕截图.程序开始和普通一样,包括进去了一个头文件.接着我们定义了回车键和escape键的ASCII码值.#include <>#include <>#define ENTER 10#define ESCAPE 27当程序的时候,下面的函数会被调用.它首先调用initscr初始化指针接着调用start_color来显示彩色. 整个程序中所使用的颜色对会在后面定义.调用curs_set(0)会屏蔽掉物理指针.noecho()将终止键盘上的输入会在屏幕上显示出来. 您可以使用noecho函数控制键盘输入进来的字符,只允许需要的字符显示.echo()将会屏蔽掉这种效果. 接着的函数keypad设置了可以在stdscr中接受键盘的功能键(快捷键),我们需要在后面的程序中定义F1,F2以及移动的光标键.void init_curses(){initscr();start_color();init_pair(1,COLOR_WHITE,COLOR_BLUE);init_pair(2,COLOR_BLUE,COLOR_WHITE);init_pair(3,COLOR_RED,COLOR_WHITE);curs_set(0);noecho();keypad(stdscr,TRUE);}下面定义的这个函数定义了一个显示在屏幕最顶部的菜单栏, 您可以看下面的main段程序,它看上去好象只是屏幕最顶部的一行,其实实际上是stdscr窗体的一个子窗体,该子窗体只有一行.下面的程序将指向该子窗体的指针作为它的参数,首先改变它的背景色,接着定义菜单的字,我们使用waddstr定义菜单的字.需要注意的是wattron调用了另外一个不同的颜色对(序号3)以取代缺省的颜色对(序号2).记住2号颜色对在最开始就由wbkgd设置成缺省的颜色对了.wattroff函数可以让我们切换到缺省的颜色对状态.void draw_menubar(WINDOW *menubar){wbkgd(menubar,COLOR_PAIR(2));waddstr(menubar,"Menu1");wattron(menubar,COLOR_PAIR(3));waddstr(menubar,"(F1)");wattroff(menubar,COLOR_PAIR(3));wmove(menubar,0,20);waddstr(menubar,"Menu2");wattron(menubar,COLOR_PAIR(3));waddstr(menubar,"(F2)");wattroff(menubar,COLOR_PAIR(3));}下一个函数显示了当按下F1或者F2键显示的菜单,定义了一个在蓝色背景上菜单栏颜色一样的白色背景窗体,我们不希望这个新窗口会被显示在背景色上的字覆盖掉.它们应该停留在那里直到关闭了菜单.这就是为什么菜单窗体不能定义为stdscr的子窗体,下面会提到,窗体items[0]是用newwin函数定义的, 其他8个窗体则都是定义成items[0]窗体的子窗体.这里的items[0]被用来绘制一个围绕在菜单旁边的边框,其他的窗体则用来显示菜单中选中的单元.同样的,他们不会覆盖掉菜单上的边框.为了区别选中和没选中的状态,有必要让选中的单元背景色和其他的不一样.这就是这个函数中倒数第三句的作用了,菜单中的第一个单元背景色和其他的不一样, 这是因为菜单弹出来后,第一个单元是选中状态.WINDOW **draw_menu(int start_col){int i;WINDOW **items;items=(WINDOW **)malloc(9*sizeof(WINDOW *));items[0]=newwin(10,19,1,start_col);wbkgd(items[0],COLOR_PAIR(2));box(items[0],ACS_VLINE,ACS_HLINE);items[1]=subwin(items[0],1,17,2,start_col+1);items[2]=subwin(items[0],1,17,3,start_col+1);items[3]=subwin(items[0],1,17,4,start_col+1);items[4]=subwin(items[0],1,17,5,start_col+1);items[5]=subwin(items[0],1,17,6,start_col+1);items[6]=subwin(items[0],1,17,7,start_col+1);items[7]=subwin(items[0],1,17,8,start_col+1);items[8]=subwin(items[0],1,17,9,start_col+1);for (i=1;i<9;i++)wprintw(items[i],"Item%d",i);wbkgd(items[1],COLOR_PAIR(1));wrefresh(items[0]);return items;}下面这个函数简单的删除了上面函数定义的菜单窗体.它首先用delwin函数删除窗体, 接着释放items指针的内存单元.void delete_menu(WINDOW **items,int count){int i;for (i=0;i<count;i++)delwin(items[i]);free(items);}scroll_menu函数允许我们在菜单选择项上上下移动,它通过getch读取键盘上的键值,如果按下了键盘上的上移或者下移方向键, 菜单选择项的上一个项或者下一个项被选中.回忆一下刚才所讲的,选中项的背景色将会和没选中的不一样.如果是向左或者向右的方向键,当前菜单将会关闭,另一个菜单打开.如果按下了回车键,则返回选中的单元值.如果按下了ESC键,菜单将会被关闭,并且没有任何选择项,下面的函数忽略了其他的输入键.getch能从键盘上读取键值,这是因为我们在程序开始使用了keypad(stdscr,TRUE) 并且将返回值赋给一个int型变量而不是char型变量,这是因为int型变量能表示比char型更大的值.int scroll_menu(WINDOW **items,int count,int menu_start_col){int key;int selected=0;while (1) {key=getch();if (key==KEY_DOWN || key==KEY_UP) {wbkgd(items[selected+1],COLOR_PAIR(2));wnoutrefresh(items[selected+1]);if (key==KEY_DOWN) {selected=(selected+1) % count;} else {selected=(selected+count-1) % count;}wbkgd(items[selected+1],COLOR_PAIR(1));wnoutrefresh(items[selected+1]);doupdate();} else if (key==KEY_LEFT || key==KEY_RIGHT) {delete_menu(items,count+1);touchwin(stdscr);refresh();items=draw_menu(20-menu_start_col);return scroll_menu(items,8,20-menu_start_col);} else if (key==ESCAPE) {return -1;} else if (key==ENTER) {return selected;}}}最后就是我们的main部分了.它使用了上面所有我们所讲述和编写的函数来使程序合适的工作. 它同样通过getch读取键值来判断F1或者F2是否按下了,并且用draw_menu来在相应的菜单窗体上绘制菜单. 接着调用scroll_menu函数让用户选择某一个菜单,当scroll_menu返回后,它删除菜单窗体并且显示所选择的单元内容在信息栏里.我必须提到的是函数touchwin.如果在菜单关闭后没有调用touchwin而立即刷新,那么最后打开的菜单将一直停留在屏幕上.这是因为在调用refresh时,menu函数根本就没有完全改变stdscr的内容.它没有重新写入数据到stdscr上, 因为它以为窗体内容没有改变.touchwin函数设置了所有WINDOW结构中的标志位,它通知refresh刷新窗体中所有的行, 值都改变了,这样在下一次刷新整个窗体时,即使窗体内容没有改变也要重新写入一次.在菜单关闭后,选择的菜单信息会一直停留在stdscr上面.菜单没有在stdscr上写数据,因为它是开了一个新的子窗口.int main(){WINDOW *menubar,*messagebar;init_curses();bkgd(COLOR_PAIR(1));menubar=subwin(stdscr,1,80,0,0);messagebar=subwin(stdscr,1,79,23,1);draw_menubar(menubar);move(2,1);printw("Press F1 or F2 to open the menus. ");printw("ESC quits.");refresh();do {int selected_item;WINDOW **menu_items;key=getch();werase(messagebar);wrefresh(messagebar);if (key==KEY_F(1)) {menu_items=draw_menu(0);selected_item=scroll_menu(menu_items,8,0);delete_menu(menu_items,9);if (selected_item<0)wprintw(messagebar,"You haven't selected any item."); elsewprintw(messagebar,"You have selected menu item %d.",selected_item+1); touchwin(stdscr);refresh();} else if (key==KEY_F(2)) {menu_items=draw_menu(20);selected_item=scroll_menu(menu_items,8,20);delete_menu(menu_items,9);if (selected_item<0)wprintw(messagebar,"You haven't selected any item."); elsewprintw(messagebar,"You have selected menu item %d.",selected_item+1); touchwin(stdscr);refresh();}} while (key!=ESCAPE);delwin(menubar);delwin(messagebar);endwin();}如果您拷贝了代码到一个文件,假设名字是,并且移走了我所有的注释,您可以用下面这个方法编译:gcc -Wall -o example -lcurses为了测试程序,您可以在参考一章里下载该程序.总结我谈到了很多关于ncurses的基础知识,应该足够用来给您的程序创建一个很好看的界面.还有许多方便的功能在这里都没有提及,您可以在我经常问到的几个函数的man pages里面找到很多有用的信息.读完了后,您将回明白我这里提到的东西和内容仅仅是一个介绍而已.参考程序:#include <>#include <>#define ENTER 10#define ESCAPE 27void init_curses(){initscr();start_color();init_pair(1,COLOR_WHITE,COLOR_BLUE);init_pair(2,COLOR_BLUE,COLOR_WHITE);init_pair(3,COLOR_RED,COLOR_WHITE);curs_set(0);noecho();keypad(stdscr,TRUE);}void draw_menubar(WINDOW *menubar){wbkgd(menubar,COLOR_PAIR(2));waddstr(menubar,"Menu1");wattron(menubar,COLOR_PAIR(3));waddstr(menubar,"(F1)");wattroff(menubar,COLOR_PAIR(3));wmove(menubar,0,20);waddstr(menubar,"Menu2");wattron(menubar,COLOR_PAIR(3));waddstr(menubar,"(F2)");wattroff(menubar,COLOR_PAIR(3));}WINDOW **draw_menu(int start_col){int i;WINDOW **items;items=(WINDOW **)malloc(9*sizeof(WINDOW *));items[0]=newwin(10,19,1,start_col);wbkgd(items[0],COLOR_PAIR(2));box(items[0],ACS_VLINE,ACS_HLINE);items[1]=subwin(items[0],1,17,2,start_col+1);items[2]=subwin(items[0],1,17,3,start_col+1);items[3]=subwin(items[0],1,17,4,start_col+1);items[4]=subwin(items[0],1,17,5,start_col+1);items[5]=subwin(items[0],1,17,6,start_col+1);items[6]=subwin(items[0],1,17,7,start_col+1);items[7]=subwin(items[0],1,17,8,start_col+1);items[8]=subwin(items[0],1,17,9,start_col+1);for (i=1;i<9;i++)wprintw(items[i],"Item%d",i);wbkgd(items[1],COLOR_PAIR(1));wrefresh(items[0]);return items;}void delete_menu(WINDOW **items,int count){int i;for (i=0;i<count;i++)delwin(items[i]);free(items);}int scroll_menu(WINDOW **items,int count,int menu_start_col){int key;int selected=0;while (1) {key=getch();if (key==KEY_DOWN || key==KEY_UP) {wbkgd(items[selected+1],COLOR_PAIR(2));wnoutrefresh(items[selected+1]);if (key==KEY_DOWN) {selected=(selected+1) % count;} else {selected=(selected+count-1) % count; }wbkgd(items[selected+1],COLOR_PAIR(1));wnoutrefresh(items[selected+1]);doupdate();} else if (key==KEY_LEFT || key==KEY_RIGHT) {delete_menu(items,count+1);touchwin(stdscr);refresh();items=draw_menu(20-menu_start_col);return scroll_menu(items,8,20-menu_start_col); } else if (key==ESCAPE) {return -1;} else if (key==ENTER) {return selected;}}}int main(){int key;WINDOW *menubar,*messagebar;init_curses();bkgd(COLOR_PAIR(1));menubar=subwin(stdscr,1,80,0,0);messagebar=subwin(stdscr,1,79,23,1);draw_menubar(menubar);move(2,1);printw("Press F1 or F2 to open the menus. ");printw("ESC quits.");refresh();do {int selected_item;WINDOW **menu_items;key=getch();werase(messagebar);wrefresh(messagebar);if (key==KEY_F(1)) {menu_items=draw_menu(0);selected_item=scroll_menu(menu_items,8,0);delete_menu(menu_items,9);if (selected_item<0)wprintw(messagebar,"You haven't selected any item."); elsewprintw(messagebar,"You have selected menu item %d.",selected_item+1);touchwin(stdscr);refresh();} else if (key==KEY_F(2)) {menu_items=draw_menu(20);selected_item=scroll_menu(menu_items,8,20);delete_menu(menu_items,9);if (selected_item<0)wprintw(messagebar,"You haven't selected any item."); elsewprintw(messagebar,"You have selected menu item %d.",selected_item+1); touchwin(stdscr);refresh();}} while (key!=ESCAPE);delwin(menubar);delwin(messagebar);endwin();return 0;}。

ncurses库的介绍与安装

ncurses库的介绍与安装

ncurses库的介绍与安装介绍(new curses)是⼀套编程库,它提供了⼀系列的函数以便使⽤者调⽤它们去⽣成基于⽂本的⽤户界⾯。

ncurses名字中的n意味着“new”,因为它是curses的⾃由软件版本。

由于AT&T“臭名昭著”的版权政策,⼈们不得不在后来⽤ncurses去代替它。

ncurses是的⼀部分,但它却是少数⼏个不使⽤GNU GPL或LGPL授权的GNU软件之⼀。

其实我们对ncurses本⾝并不陌⽣,以下⼏款⼤名⿍⿍的软件都⽤到过ncurses:vimemacslynxscreen为了制作⾃⼰构想了⼀段时间的Roguelike的游戏,同时作为对的实践,我开始接触ncurses并在此作笔记。

安装Linux以Debian为例(⼈⽣中第⼀个发⾏版)$ sudo apt-get install libncurses5-dev安装完毕后,我们写下如下代码://test.c#include <string.h>#include <ncurses.h>int main(int argc,char* argv[]){initscr();raw();noecho();curs_set(0);char* c = "Hello, World!";mvprintw(LINES/2,(COLS-strlen(c))/2,c);refresh();getch();endwin();return0;}然后使⽤gcc编译后执⾏看看效果,不要忘了加-lncurses哦。

$ gcc test.c -o test -lncurses$ ./test不出意外的话结果如下:。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

attroff(chtype attribute)
attrset(chtype attribute) standend() standout()
关闭指定的属性
mvwscanw()
将光标移动到指定位置,并获取用户输入 在指定窗口的当前坐标处,获取用户输入
在指定窗口的指定坐标处,获取用户输入
scanw例子
#include <ncurses.h> #include <string.h> int main() { char mesg[]="Enter a string: "; /* 将要被打印的字符串信息*/ char str[80]; int row,col; /* 存储行号和列号的变量,用于指定光标位置*/ initscr(); /* 进入curses 模式*/ getmaxyx(stdscr,row,col); /* 取得stdscr 的行数和列数*/ mvprintw(row/2,(col-strlen(mesg))/2,"%s",mesg); /* 在屏幕的正中打 印字符串mesg */ scanw(“%s”,str); /* 将指针str 指向读取的字符串*/ mvprintw(2,0, "You Entered: %s", str); getch(); endwin(); return 0; }
字符输出过程
• 在一个curses程序里,输出一个字符的过程 是:
– 使用curses函数刷新一个逻辑屏幕 – 请求curses用refresh刷新物理屏幕
curses模式初始化
initscr()函数将终端屏幕初始化为curses 模式 它用来清除屏幕上所有的字符,并等待下一步处理。 在调用其它的curses 函数前,要先调initscr()函数初始化 屏幕。 initscr()初始化了curses 系统并且为当前屏幕(也就是 “stdscr”)和相关的数据结构分配内存
getch()
• •
功能说明:从键盘读入一个字符 原型:
int getch (void);

注意:这个getch()是ncurses提供的函数, 没有getche()这个函数
移动光标
• •
功能说明:把逻辑光标的位置移动到指定的地点 原型:
int move (int new_y, int new_x);
第六章
Linux GUI-NCurses(一)
本章目标
• • • • 了解NCurses程序库 掌握NCurses输入输出函数 掌握NCurses窗口工作机制和窗口控制 了解控件雏形和工作原理
curses 简介
• curses 的命名是来自一个叫做“cursor optimization " (光标最优化)的双关语。 curses 构成了一个工作在底层终端代码之 上的封装,并向用户提供了一个灵活高效 的API ( Application Programming Interface 应用程序接口)。 • curses提供了移动光标,建立窗口,产生颜 色,处理鼠标操作等功能。
退出curses模式
• 通过endwin()函数退出curses 模式 • endwin()函数释放了curses 子系统和相关 数据结构占用的内存 • 必须是在完成所有的curses 操作以后才可 以调用
第一个curses程序
#include <ncurses.h> int main() { initscr(); /* 初始化,进入NCURSES 模式*/ printw(“Hello World !!”); /* 在虚拟屏幕上打Hello World!!*/ refresh(); /* 将虚拟屏幕上的内容写到显示器 上, 并刷新*/ getch(); /* 等待用户输入*/ endwin(); /* 退出NCURSES 模式*/ return 0; }
ncurses 与 curses的关系
ncurses是最早的SystemRelease4.0(SVR 4)中curses的一个克隆。这是一个可自由配 置的库,完全兼容旧版本的curses。
编译包含NCURSES 库函数的程序
• 如果要调用ncurses 库中的函数,你必须在 代码中加载ncurses.h 文件,就是要在C 或 C++程序开头添加“#include <ncurses.h>”, 然后在链接时标记lncurses参数。(注: ncurses 库已经包含“stdio.h”)
清除屏幕函数
函数名 erase(void) clear(void) 描述 在每个屏幕空白位置写上空白符 清除整个屏幕,要配合refresh()使用 清除从光标当前位置到屏幕右下角的所有内 容 从光标当前位置删除到这一行的结尾
clrtobot(void)
clrtoeol(void)
输入函数
• 输入函数也被分为三种:
普通字符输出
终端字符最亮 下划线 字符反白显示 闪动显示
A_BOLD
A_PROTECT
加亮加粗
保护模式
A_INVIS
A_DIM A_CHARTEXT A_ALTCHARSET
空白显示模式
半亮显示 字符掩盖 字符交替
字符属性操作函数
函数名 attron(chtype attribute) 开启指定的属性 描述
获取到的字符串
界面允许用户输入的 字符数
getnstr允许对读取的字符个数加以限制
字符的属性2-1
每个curses字符都可以有特定的属性,属性控制 着这个字符在屏幕上的显示方式,当然前提是显 示设备硬件能够支持要求的属性
字符的属性2-2
属性名 描述
A_NORMAL
A_STANDOUT A_UNDERLINE A_REVERSE A_BLINK
addch()
• •
功能说明:在光标的当前位置添加给定的字符 原型:
int addch (const chtype char_to_add);
要添加的字符
chtype是curses自己的字符类型,在ncurses中所使用的chtype 实际上是一个unsigned long整数 char_to_add =
ch | A_BOLD | A_UNDERLINE
addstr()
• •
功能说明:在光标的当前位置添加给定的字符串 原型:
int addstr (chtype * const string_to_add); 要添加的字符串
其他add..()函数
函数名 mvaddch(int y,int x,chtype ch) waddch(WINDOW*,chtype ch) mvwaddch(WINDOW* , int, int, chtype) mvaddstr() waddstr() 描述 用于将光标移动到指定位置输出字符 将字符输出到指定窗口的当前坐标处 将字符输出到指定窗口的指定坐标处
• 编译和连接命令: gcc <程序文件> -lncurses
curses工作原理3-1
• 窗口是由curses系统定义的一个假想的屏幕, 即逻辑屏幕。并不像Windows 平台上的窗 口那样具有边框。当curses 初始化的时候, 它会默认创建一个叫做stdscr 的窗口。这个 窗口的屏幕一般是80列,24 行(根据显示 环境的不同,可能会出现不同的大小)。
curses工作原理3-2
• 逻辑屏幕的布局是一个字符数组,数组下 标为行号和列号组成。位置(0,0)是屏 幕的左上角 • curses函数使用的坐标是y值(行号)在前, x值(列号)在后。
curses工作原理3-3
• stdscr数据结构指的是“标准屏幕”,它的 工作原理和stdio函数库中的标准输出stdout 非常相似,在curses程序里,它是缺省的输 出窗口。 • curscr数据结构指的是“当前屏幕”。 • 在程序调用refresh之前,输出数据是不会 出现在标准屏幕上的。 • refresh被调用时,curses会比较stdscr与 curscr的内容,只刷新发生改变的部分。
printw()例子
#include <ncurses.h> /* ncurses.h 已经包含了stdio.h */ #include <string.h> int main() { char mesg[]="Just a string"; /* 将要被打印的字符串*/ int row,col; /* 存储行号和列号的变量,用于指定光标位置*/ initscr(); /* 进入curses 模式*/ getmaxyx(stdscr,row,col); /* 取得stdscr(标准输出设备)的行数和列数*/ mvprintw(row/2,(cols - trlen(mesg))/2,"%s",mesg); /*在屏幕的正中打印字 符串mesg*/ mvprintw(row/2,0,"This screen has %d rows and %d columns\n“,row,col); printw("Try resizing your window(if possible)and then run this program again"); refresh(); getch(); endwin(); return 0; }
– getch ()系列:读取一个字符的一类函数。 – scanw()系列:按照格式化读取输入的一类函数。 – getstr()系列:读取字符串的一类函数。
scanw()系列函数
函数名 scanw() பைடு நூலகம்述 和标准io的scanf()类似用法,用来获取用户 的输入
mvscanw() wscanw()
相关文档
最新文档