2.键盘
一般来讲,键盘输入数据后,遇见换行符号才会把输入的数据送入系统,这种处理方式被称为预处理模式。
1.键盘模式
int echo();回显
int noecho;关闭回显
int cbreak();使用立刻返回的模式
int cbreak();关闭立刻返回的模式
int noraw();关闭特殊字符,这样用信号关闭程序就会被忽略。
2.键盘输入
读取键盘的输入使用以下几个函数
int getch();
int getstr(char* str);
int getnstr(char* string, int number_of_char);
int scanw(char* format,……)
上面的函数与普通的gets,getchar(),scanf类似
实验:输入密码,与已经存在的密码对比。
程序会关闭回显,每次读取一个字符,立刻送入程序,不等待回车,然后输出一个*
输入结束后,重新输出刚刚输入的密码
#include<stdio.h>
#include<string.h>
#include<curses.h>
#include<unistd.h>
#define PW_LEN 256
#define NAME_LEN 256
int main()
{
char name[NAME_LEN];
char passwd[PW_LEN];
char real_password[] = "123456";
//输出提示字符
int i = 0;
initscr();
move(5,10);
printw("please login");
move(7,10);
printw("User name:");
getstr(name);
move(8,10);
printw("Password:");
refresh();
//输入密码
cbreak();
noecho();//关闭回显
memset(passwd,'\0',sizeof(passwd));
while(i < PW_LEN)
{
passwd[i] = getch();
if(passwd[i] == '\n') break;
move(8,20+i);
addch('*');
refresh();
i++;
}
//重新启动键盘回显,对比输入密码
echo();
nocbreak();
move(11,10);
if(strncmp(real_password, passwd, strlen(real_password)) == 0)
printw("%s","Correct");
else printw("Wrong");
printf("%s",passwd);
refresh();
sleep(10);
endwin();
return 0;
}
3.窗口
1.WINDOW结构
之前的处理,都是基于标准窗口,这个标准窗口和标注输出一样,只是一种特殊的形态,接下来要接受的是各种普遍的窗口
WINDOW* newwin(int num_of_lines, int num_of_cols, int start_y, int start_x);
int delwin(WINDOW* win);
newwin是创建一个新的窗口,delwin是删除一个创建的窗口
2.通用函数
在之前的函数前面加一个w就是对窗口的操作
加上mv就是对光标的移动
wmv是在窗口中移动光标
比如:添加一个字符的函数
int addch(const chtype char) 在窗口光标处添加一个字符
int waddch(WINDOW* winptr, const chtype char) 在winptr窗口的光标处添加一个字符
int wmv(WINDOW* win, int y, int x, const chtype char) 在win窗口,坐标(y,x)处添加一个字符
实验:
#include<stdio.h>
#include<string.h>
#include<curses.h>
#include<unistd.h>
int main()
{
initscr();
WINDOW* wptr = newwin(20,20,1,1);
if(wptr == NULL)
{
fprintf(stderr,"新屏幕创建失败\n");
return 0;
}
wprintw(wptr,"hello new curses\n");
wrefresh(wptr);
sleep(10);
delwin(wptr);
endwin();
return 0;
}
这里创建一个新的屏幕,起点在标准屏幕坐标的(1,1),长宽分别为20,20
然后在新的屏幕上输出hello new curses
和之前一样,每次更新屏幕的输出,都要刷新一次,调用对用的刷新函数即可
3.移动窗口和更新窗口
下面这些函数是用来移动窗口和重新绘制窗口的。
int mvwin(WINDOW* window_to_move, int new_y, int new_x);
int wrefresh(WINDOW* winptr);
int wclear(WINDOW* window_ptr)
int werase(WINDOW* window_ptr)
int touchwin(WINDOW* );//为窗口发送信号,通知窗口已经需要做出改变了。因为wrefresh不一定会主动刷新窗口,他会比较窗口前后的变化,做出改变。
int scrollok(WINDOW* window_ptr, bool scroll_flag);控制窗口卷屏,如果bool值取得true则表示允许卷屏
int scroll(WINDOW* window_ptr);屏幕只卷一行
实验:管理多窗口
#include<stdio.h>
#include<string.h>
#include<curses.h>
#include<unistd.h>
int main()
{
WINDOW* new_window_ptr = NULL;
WINDOW* popup_window_ptr = NULL;
int x_loop, y_loop;
char a_letter = 'a';
initscr();
/*在主窗口输出a-z*/
move(5,5);
printw("%s\n","Testing multiple window");
refresh();
for(y_loop = 0; y_loop < LINES - 1; y_loop++)
for(x_loop = 0; x_loop < COLS -1; x_loop++)
{
mvwaddch(stdscr, y_loop, x_loop, a_letter);
a_letter++;
if(a_letter > 'Z')
a_letter = 'a';
}
refresh();
sleep(2);
/*创建一个新的窗口*/
new_window_ptr = newwin(10,10,5,5);
mvwprintw(new_window_ptr,2,2,"%s","hello world");
mvwprintw(new_window_ptr,5,2,"%s","Notice how long lines wrap inside the window");
wrefresh(new_window_ptr);
sleep(2);
/*对主窗口输出内容重新设置,输出0-9*/
a_letter = '0';
for(y_loop = 0; y_loop < LINES - 1; y_loop++)
for(x_loop = 0; x_loop < COLS -1; x_loop++)
{
mvwaddch(stdscr, y_loop, x_loop, a_letter);
a_letter++;
if(a_letter > '9')
a_letter = '0';
}
refresh();
sleep(2);
char select = ' ';
while(1)
{
do{
select = getchar();
}while(select == '\n');
switch(select)
{
case '1'://刷新new窗口
/*对新创建的窗口进行输出,什么也不会发生*/
wrefresh(new_window_ptr);
sleep(2);
break;
case '2'://强制刷新new窗口
/*再刷新一次,这次发送一个信号,就会有变化*/
touchwin(new_window_ptr);
wrefresh(new_window_ptr);
sleep(2);
break;
case '3'://创建一个带边框的窗口
/*增加一个新的窗口,带边框*/
popup_window_ptr = newwin(10,20,8,8);
box(popup_window_ptr,'|','-');
mvwprintw(popup_window_ptr,5,2,"%s","pop up window");
wrefresh(popup_window_ptr);
sleep(2);
break;
case '4'://刷新子窗口
/*轮流刷新*/
touchwin(new_window_ptr);//给子窗口发送信号
wrefresh(new_window_ptr);
sleep(2);break;
case '5'://清空new_window_ptr
wclear(new_window_ptr);//清空窗口
wrefresh(new_window_ptr);
sleep(2);break;
case '6'://删除new窗口
delwin(new_window_ptr);//删除子窗口
touchwin(popup_window_ptr);//给popup窗口发送信息
wrefresh(popup_window_ptr);//刷新
sleep(2);break;
case '7'://
delwin(popup_window_ptr);//删除popup窗口
touchwin(stdscr);//给标准窗口发送信息
refresh();sleep(2);break;
default:break;
}
if(select == '0')
break;
}
endwin();
return 0;
}
依次输入123456780,对照注释观察变化。
4.keypad模式
处理功能按键。比如上下左右的键盘
int keypad(WINDOW* window_ptr, bool keypad_on);
#include<stdio.h>
#include<string.h>
#include<curses.h>
#include<unistd.h>
#define LOCAL_ESCAPE_KEY 27
int main()
{
int key;
initscr();
crmode();
keypad(stdscr,TRUE);
noecho();
mvprintw(5,5, "keypad,press q exit");
move(7, 5);
refresh();
key = getch();
while(key != ERR && key != 'q')
{
move(7,5);
clrtoeol();//关闭行模式
if((key >= 'A' && key <= 'z') || (key >= 'a' && key <= 'z'))
printw("key was %c\n",(char)key);
else{
switch(key){
case LOCAL_ESCAPE_KEY : printw("Escape key\n");break;
case KEY_END: printw("end key\n"); break;
case KEY_BEG: printw("begining key\n");break;
case KEY_RIGHT: printw("right key\n");break;
case KEY_LEFT: rpintw("left key\n");break;
case KEY_UP: printw("up key\n");break;
case KEY_DOWN:printw("down key\n"); break;
default: printw("unmatched -%d\n",key); break;
}
refresh();
key = getch();
}
}
endwin();
return 0;
}
5:彩色显示
curses对颜色的支持有些不同,必须同时定义一个字符的前景色和背景色。
(1)先检查是否支持颜色,然后对函数库初始化
bool has_colors();成功返回true
bool start_color();成功返回OK
支持的颜色种类为COLOR_PAIRS,一般是最大的64,变量COLORS表示颜色数目的最大值,一般只有8种
(2)对使用的颜色初始化,访问颜色
int init_pair(short pair_number, short foreground,short backgound);对准备使用的颜色组合进行初始化
int COLOR_PAIR(int pair_number);设置对颜色的访问
int pair_content(short pair_number,short* foreground, short *backgound);获取定义的颜色组合信息
颜色都是用COLOR_ + 颜色名字
比如红色:COLOR_RED,绿色COLOR_GREEN
颜色就和普通的属性一样,可以使用设置函数来显示attrset
#include<stdio.h>
#include<string.h>
#include<curses.h>
#include<unistd.h>
int main()
{
initscr();
if(has_colors() == false)
{
fprintf(stderr,"Don't suppose color\n");
return 0;
}
if(start_color() != OK)
{
fprintf(stderr,"start color fail\n");
return 0;
}
//设置红色和绿色
if(init_pair(1, COLOR_RED, COLOR_GREEN) < 0)
{
fprintf(stderr,"init color fail\n");
return 0;
}
//输出颜色
attrset(COLOR_PAIR(1));
printw("hello world");
refresh();
sleep(10);
endwin();
return 0;
}
(4).pad
使用WINDOW结构只能基于物理屏幕,超出屏幕范围就无效,而使用pad结构体,能够创建逻辑上的屏幕
所有的写操作的curses对于pad都是通用的,但是pad有自己的创建函数和刷新函数
创建一个pad
(1)WINDOW* newpad(int num_of_lines, int num_of_cols);
删除一个pad也是用delwin
(2)刷新pad,pad是一个逻辑屏幕,因此需要指定刷新范围
int prefresh(WINDOW* pad_ptr, int pad_row, int pad_column,
int screen_row_min, int screen_column_min,
int screen_raw_max, int screen_column_max);
起点(int pad_row, int pad_column),指定的屏幕大小为(int screen_row_min, int screen_column_min,int screen_raw_max, int screen_column_max))