下面使用getwin和putwin完成对窗口内容的保存,而不是对整个屏幕,同时修正程序的几个小错误:
1、下面的操作提示在多次操作后会出现混乱。
2、退出后,endwin结束窗口,并且退出curses模式。
dp@dp:~/cursestest % cat a.c
#include
#include
#include
//code by [email protected]
//date:2014/1/17
int isExist(char *filename)
{
return (access(filename, 0) == 0);
}
int main(int argc, char *argv[])
{
MEVENT event;
setlocale(LC_ALL,"");
initscr();
clear();
noecho();
cbreak();
if(has_colors() == FALSE)
{
endwin();
printf("你的终端不支持色彩!\n");
return (1);
}
start_color(); /*启动color 机制*/
mvprintw(3,COLS/2-10,"简单编辑器-仅限于单个屏幕的编辑");
mvprintw(4,COLS/2-15,"【F9读保存内容,F10存盘,F11退出,F12删除整行】");
refresh();
init_pair(1, COLOR_GREEN, COLOR_BLACK);
WINDOW *win1;
int width=COLS-14;
int height=LINES-14;
int x,y;
win1=newwin(height,width,7,7);//新窗口(行,列,begin_y,begin_x)
keypad(wi
n1,TRUE);
wattron(win1,COLOR_PAIR(1));
box(win1,ACS_VLINE,ACS_HLINE);
wrefresh(win1);
getyx(win1,y,x);
++y;++x;
mmask_t oldmousemask;
int ans=0;
FILE *fp2=NULL;
FILE *fp1=NULL;
mousemask(ALL_MOUSE_EVENTS, &oldmousemask);
while(1){
int c=mvwgetch(win1,y,x);
switch(c)
{ case KEY_MOUSE:
if(getmouse(&event) == OK)
{ /* When the user clicks left mouse button */
if(event.bstate & BUTTON1_PRESSED)
{
y=event.y-7;x=event.x-7;
wmove(win1,y,x);
}
}
break;
case KEY_BACKSPACE:
--x;
if (x<1){
--y;x=width-2;
}
if (y<1){
y=height-2;
}
mvwprintw(win1,y,x," ");
break;
case KEY_RIGHT:
++x;
if (x>=width-1) {
++y;
x=1;
}
break;
case KEY_LEFT: --x;
if (x<1){
--y;
x=width-2;
}
break;
case KEY_UP:
--y;
if (y<1){
y=height-2;
}
break;
case KEY_DOWN:
++y;
if (y>=height-1){
y=1;
}
break;
case 10:
++y;
if (y>=height-1){
y=1;
}
break;
case KEY_F(11):
//退出
mvprintw(LINES-3,2," ");
mvprintw(LINES-3,2,"退出编辑器吗? ");
mvprintw(LINES-2,2," ");
mvprintw(LINES-1,2," \n");
refresh();
ans=getch();
if (ans=='Y' ||ans=='y')
{
mvprintw(LINES-2,2,"是\n");
refresh();
wattroff(win1,COLOR_PAIR(1));
mousemask(oldmousemask,NULL);
delwin(win1);
endwin();
return 0;
}else
mvprintw(LINES-2,2,"否\n");
refresh();
break;
case KEY_F(10):
//存盘
mvprintw(LINES-3,2," ");
mvprintw(LINES-3,2,"保存当前内容吗? ");
mvprintw(LINES-2,2," ");
mvprintw(LINES-1,2," \n");
refresh();
ans=getch();
if (ans=='Y' ||ans=='y')
{
mvprintw(LINES-3,2," ");
fp1 = fopen("myet.dat","wb");
if (fp1!=NULL){
int jg= putwin(win1,fp1);
fclose(fp1);
if (jg==OK) mvprintw(LINES-1,2,"保存成功!\n");
}
mvprintw(LINES-3,2,"保存当前内容吗? ");
mvprintw(LINES-2,2,"是\n");
refresh();
}else
mvprintw(LINES-2,2,"否\n");
refresh();
break;
case KEY_F(9):
//读取存盘
mvprintw(LINES-3,2," ");
mvprintw(LINES-3,2,"读取保存内容吗? ");
mvprintw(LINES-2,2," ");
mvprintw(LINES-1,2," \n");
refresh();
ans=getch();
if (ans=='Y' ||ans=='y')
{
if (isExist("myet.dat")) {
fp2 = fopen("myet.dat","rb");
if (fp2!=NULL){
WINDOW *newwin=getwin(fp2);
if (newwin!=NULL) {
delwin(win1);
win1=newwin;
wrefresh(win1);
mvprintw(LINES-1,2,"读取成功!\n");
}
fclose(fp2);
}
}
mvprintw(LINES-3,2,"读取保存内容吗? ");
mvprintw(LINES-2,2,"是\n");
refresh();
}else
mvprintw(LINES-2,2,"否\n");
refresh();
break;
case KEY_F(12):
//删除某行
wdeleteln(win1);
winsertln(win1);
box(win1,ACS_VLINE,ACS_HLINE);
break;
case KEY_DC:
//删除某字符
mvwprintw(win1,y,x," ");
break;
default:
mvwprintw(win1,y,x,"%c",c);
++x;
if (x>=width-1){
++y;
x=1;
}
if (y>=height-1){
y=1;
}
wrefresh(win1);
}
}
}
执行
dp@dp:~/cursestest % gcc -lncursesw a.c -o mytest
dp@dp:~/cursestest % ./mytest
面板库(Panel Library)能方便得管理面板:
使用newwin()函数创建一个窗口,它将添加到面板里。
创建面板(利用所创建的窗口)并将面板依据用户指定的可见顺序压进栈。调用
new_panel()函数即可创建该面板。
数就能让面板显示出来。
动等操作时,可以使用panel_hidden()和panel_window()这两个辅助函数。你也可以
使用用户指针来存储面板的数据,set_panel_userptr() 和panel_userptr()函数分别用
来设置和取得一个面板的用户指针。
下面是一个例子
dp@dp:~/cursestest % cat x.c
#include
int main()
{
WINDOW *my_wins[3];
PANEL *my_panels[3];
int lines = 10, cols = 40, y = 2, x = 4, i;
initscr();
cbreak();
noecho();
/* 为每个面板创建窗口*/
my_wins[0] = newwin(lines, cols, y, x);
my_wins[1] = newwin(lines, cols, y + 1, x + 5);
my_wins[2] = newwin(lines, cols, y + 2, x + 10);
/* 为窗口添加创建边框以便你能看到面板的效果*/
for(i = 0; i < 3; +++i)
box(my_wins[i], 0, 0);
/* 按自底向上的顺序,为每一个面板关联一个窗口*/
my_panels[0] = new_panel(my_wins[0]);
/* 把面板0 压进栈, 叠放顺序: stdscr0
*/
my_panels[1] = new_panel(my_wins[1]);
/* 把面板1 压进栈, 叠放顺序: stdscr01
*/
my_panels[2] = new_panel(my_wins[2]);
/* 把面板2 压进栈, 叠放顺序: stdscr012*/
/* 更新栈的顺序。把面板2 置于栈顶*/
update_panels();
/* 在屏幕上显示*/
doupdate();
getch();
endwin();
}
dp@dp:~/cursestest % gcc -lncursesw -lpanel x.c -o mytest
dp@dp:~/cursestest % ./mytest
屏幕上显示了三个窗口,每个窗口都是一个面板,每个面板关联一个窗口。如下图所示:
然后看看隐藏和显示面板
dp@dp:~/cursestest % cat x.c
#include
int main()
{
WINDOW *my_wins[3];
PANEL *my_panels[3];
int lines = 10, cols = 40, y = 2, x = 4, i;
int ch;
initscr();
cbreak();
noecho();
/* 为每个面板创建窗口*/
my_wins[0] = newwin(lines, cols, y, x);
my_wins[1] = newwin(lines, cols, y + 1, x + 5);
my_wins[2] = newwin(lines, cols, y + 2, x + 10);
/* 为窗口添加创建边框以便你能看到面板的效果*/
for(i = 0; i < 3; +++i)
box(my_wins[i], 0, 0);
/* 按自底向上的顺序,为每一个面板关联一个窗口*/
my_panels[0] = new_panel(my_wins[0]);
/* 把面板0 压进栈, 叠放顺序: stdscr0
*/
my_panels[1] = new_panel(my_wins[1]);
/* 把面板1 压进栈, 叠放顺序: stdscr01
*/
my_panels[2] = new_panel(my_wins[2]);
/* 把面板2 压进栈, 叠放顺序: stdscr012*/
/* 更新栈的顺序。把面板2 置于栈顶*/
update_panels();
/* 在屏幕上显示*/
doupdate();
//q退出,按1-3键显示和隐藏对应的面板
int isshow[3]={1,1,1};
while((ch = getch()) !='q')
{ switch(ch)
{
case '1':
if ((++isshow[0])%2) show_panel(my_panels[0]);
else hide_panel (my_panels[0]);
break;
case '2':
if ((++isshow[1])%2) show_panel(my_panels[1]);
else hide_panel (my_panels[1]);
break;
case '3':
if ((++isshow[2])%2) show_panel(my_panels[2]);
else hide_panel (my_panels[2]);
break;
}
update_panels();
doupdate();
}
getch();
endwin();
}
执行后
dp@dp:~/cursestest % gcc -lncursesw -lpanel x.c -o mytest
dp@dp:~/cursestest % ./mytest
比如把2号面板隐藏,效果如下
调用mousemask( )这个函数来激活你想要接收的鼠标事件。
mousemask( mmask_t newmask, / 你想要监听的鼠标事件掩码/
mmask_t oldmask ) / 旧版本使用的鼠标事件掩码*/
主要事件如下:(一般来说,左键为1 号,右键为2 号)
BUTTON1_PRESSED 鼠标1 号键按下
BUTTON1_RELEASED 鼠标1 号键释放
BUTTON1_CLICKED 鼠标1 号键单击
BUTTON1_DOUBLE_CLICKED 鼠标1 号键双击
BUTTON1_TRIPLE_CLICKED 鼠标1 号键三击
BUTTON2_PRESSED 鼠标2 号键按下
BUTTON2_RELEASED 鼠标2 号键释放
BUTTON2_CLICKED 鼠标2 号键单击
BUTTON2_DOUBLE_CLICKED 鼠标2 号键双击
BUTTON2_TRIPLE_CLICKED 鼠标2 号键三击
BUTTON3_PRESSED 鼠标3 号键按下
BUTTON3_RELEASED 鼠标3 号键释放
BUTTON3_CLICKED 鼠标3 号键单击
BUTTON3_DOUBLE_CLICKED 鼠标3 号键双击
BUTTON3_TRIPLE_CLICKED 鼠标3 号键三击
BUTTON4_PRESSED 鼠标4 号键按下
BUTTON4_RELEASED 鼠标4 号键释放
BUTTON4_CLICKED 鼠标4 号键单击
BUTTON4_DOUBLE_CLICKED 鼠标4 号键双击
BUTTON4_TRIPLE_CLICKED 鼠标4 号键三击
BUTTON_SHIFT 在鼠标事件发生时,伴随Shift 键按下
BUTTON_CTRL 在鼠标事件发生时,伴随Ctrl 键按下
BUTTON_ALT 在鼠标事件发生时,伴随Alt 键按下
ALL_MOUSE_EVENTS 报告所有的鼠标事件
REPORT_MOUSE_POSITION 报告鼠标移动位置
getmouse()函数将这个事件返回一个相应的指针。这个指针结构是这样的:
typedef struct
{
short id; / ID 用来辨别不同的设备/
int x, y, z; / 事件发生的坐标/
mmask_t bstate; / 鼠标按键状态/
}
Bstate 是我们关注的最主要变量,它返回了当前鼠标按键的状态。下面的这段代码可以捕捉鼠标左键按下:
if(event.bstate & BUTTON1_PRESSED)
我们在上面的编辑器中加上鼠标左键定位。
dp@dp:~/cursestest % cat a.c
#include
#include
#include
int main(int argc, char *argv[])
{
MEVENT event;
setlocale(LC_ALL,"");
initscr();
clear();
noecho();
cbreak();
if(has_colors() == FALSE)
{
endwin();
printf("你的终端不支持色彩!\n");
return (1);
}
start_color(); /启动color 机制/
mvprintw(5,COLS/2-10,"简单编辑器-仅限于单个屏幕的编辑");
refresh();
init_pair(1, COLOR_GREEN, COLOR_BLACK);
WINDOW *win1;
int width=COLS-14;
int height=LINES-14;
int x,y;
win1=newwin(height,width,7,7);//新窗口(行,列,begin_y,begin_x)
keypad(win1,TRUE);
wattron(win1,COLOR_PAIR(1));
box(win1,ACS_VLINE,ACS_HLINE);
wrefresh(win1);
getyx(win1,y,x);
++y;++x;
mmask_t oldmousemask;
mousemask(ALL_MOUSE_EVENTS, &oldmousemask);
while(1){
int c=mvwgetch(win1,y,x);
switch(c)
{ case KEY_MOUSE:
if(getmouse(&event) == OK)
{ / When the user clicks left mouse button /
if(event.bstate & BUTTON1_PRESSED)
{
y=event.y-7;x=event.x-7;
wmove(win1,y,x);
}
}
break;
case KEY_RIGHT:
++x;
if (x>=width-1) {
++y;
x=1;
}
break;
case KEY_LEFT: --x;
if (x<1){
--y;
x=width-2;
}
break;
case KEY_UP:
--y;
if (y<1){
y=height-2;
}
break;
case KEY_DOWN:
++y;
if (y>=height-1){
y=1;
}
break;
case 10:
++y;
if (y>=height-1){
y=1;
}
break;
case KEY_F(1):
//退出
mvprintw(LINES-3,2,"退出编辑器吗?");
mvprintw(LINES-2,2," ");
refresh();
int ans=getch();
if (ans=='Y' ||ans=='y')
{
mvprintw(LINES-2,2,"是\n");
refresh();
return 0;
}else
mvprintw(LINES-2,2,"否\n");
refresh();
break;
case KEY_F(12):
//删除某行
wdeleteln(win1);
winsertln(win1);
box(win1,ACS_VLINE,ACS_HLINE);
case KEY_DC:
//删除某字符
mvwprintw(win1,y,x," ");
break;
default:
mvwprintw(win1,y,x,"%c",c);
++x;
if (x>=width-1){
++y;
x=1;
}
if (y>=height-1){
y=1;
}
wrefresh(win1);
}
}
wattroff(win1,COLOR_PAIR(1));
endwin();
mousemask(oldmousemask,NULL);
return 0;
}
执行
dp@dp:~/cursestest % gcc -lncursesw a.c -o mytest
dp@dp:~/cursestest % ./mytest
scr_dump() 函数可以把当前屏幕的内容存入指定文件,即以文件名作为函数的参数,而通过 scr_restore()函数调用屏幕数据文件来恢复屏幕。它们的函数调用方式为:
scr_dump(const char *file)
scr_restore(const char *file)
getwin()函数用来将窗口内容存储到一个指定的文件中。 putwin() 函数则调用相应的文件来恢复窗口。
它们的函数调用方式为:
getwin(FILE * filep)
putwin(WINDOW win, FILE filep)
我们先利用scr_dump()与scr_restore()函数,实现将编辑器的内容存盘与读取,但是它会把整个屏幕保存下来。
设定F9读取,F10存盘,同时修改退出为F11,并加入对退格键的支持。
dp@dp:~/cursestest % cat a.c
#include
#include
#include
int isExist(char *filename)
{
return (access(filename, 0) == 0);
}
int main(int argc, char *argv[])
{
MEVENT event;
setlocale(LC_ALL,"");
initscr();
clear();
noecho();
cbreak();
if(has_colors() == FALSE)
{
endwin();
printf("你的终端不支持色彩!\n");
return (1);
}
start_color(); /启动color 机制/
mvprintw(3,COLS/2-10,"简单编辑器-仅限于单个屏幕的编辑");
mvprintw(4,COLS/2-15,"【F9读保存内容,F10存盘,F11退出,F12删除整行】");
refresh();
init_pair(1, COLOR_GREEN, COLOR_BLACK);
WINDOW *win1;
int width=COLS-14;
int height=LINES-14;
int x,y;
win1=newwin(height,width,7,7);//新窗口(行,列,begin_y,begin_x)
keypad(win1,TRUE);
wattron(win1,COLOR_PAIR(1));
box(win1,ACS_VLINE,ACS_HLINE);
wrefresh(win1);
getyx(win1,y,x);
++y;++x;
mmask_t oldmousemask;
int ans=0;
mousemask(ALL_MOUSE_EVENTS, &oldmousemask);
while(1){
int c=mvwgetch(win1,y,x);
switch(c)
{ case KEY_MOUSE:
if(getmouse(&event) == OK)
{ / When the user clicks left mouse button /
if(event.bstate & BUTTON1_PRESSED)
{
y=event.y-7;x=event.x-7;
wmove(win1,y,x);
}
}
break;
case KEY_BACKSPACE:
--x;
if (x<1){
--y;x=width-2;
}
if (y<1){
y=height-2;
}
mvwprintw(win1,y,x," ");
break;
case KEY_RIGHT:
++x;
if (x>=width-1) {
++y;
x=1;
}
break;
case KEY_LEFT: --x;
if (x<1){
--y;
x=width-2;
}
break;
case KEY_UP:
--y;
if (y<1){
y=height-2;
}
break;
case KEY_DOWN:
++y;
if (y>=height-1){
y=1;
}
break;
case 10:
++y;
if (y>=height-1){
y=1;
}
break;
case KEY_F(11):
//退出
mvprintw(LINES-3,2," ");
mvprintw(LINES-3,2,"退出编辑器吗? ");
mvprintw(LINES-2,2," ");
refresh();
ans=getch();
if (ans=='Y' ||ans=='y')
{
mvprintw(LINES-2,2,"是\n");
refresh();
return 0;
}else
mvprintw(LINES-2,2,"否\n");
refresh();
break;
case KEY_F(10):
//存盘
mvprintw(LINES-3,2," ");
mvprintw(LINES-3,2,"保存当前内容吗? ");
mvprintw(LINES-2,2," ");
refresh();
ans=getch();
if (ans=='Y' ||ans=='y')
{
mvprintw(LINES-3,2," ");
scr_dump("myedit.dat");
mvprintw(LINES-3,2,"保存当前内容吗? ");
mvprintw(LINES-2,2,"是\n");
refresh();
}else
mvprintw(LINES-2,2,"否\n");
refresh();
break;
case KEY_F(9):
//读取存盘
mvprintw(LINES-3,2," ");
mvprintw(LINES-3,2,"读取保存内容吗? ");
mvprintw(LINES-2,2," ");
refresh();
ans=getch();
if (ans=='Y' ||ans=='y')
{
if (isExist("myedit.dat")) scr_restore("myedit.dat");
mvprintw(LINES-3,2,"读取保存内容吗? ");
mvprintw(LINES-2,2,"是\n");
refresh();
}else
mvprintw(LINES-2,2,"否\n");
refresh();
break;
case KEY_F(12):
//删除某行
wdeleteln(win1);
winsertln(win1);
box(win1,ACS_VLINE,ACS_HLINE);
break;
case KEY_DC:
//删除某字符
mvwprintw(win1,y,x," ");
break;
default:
mvwprintw(win1,y,x,"%c",c);
++x;
if (x>=width-1){
++y;
x=1;
}
if (y>=height-1){
y=1;
}
wrefresh(win1);
}
}
wattroff(win1,COLOR_PAIR(1));
endwin();
mousemask(oldmousemask,NULL);
return 0;
}
执行
dp@dp:~/cursestest % gcc -lncursesw a.c -o mytest
dp@dp:~/cursestest % ./mytest