📄 unix 屏幕导向程序的发展利器2.htm
字号:
<html><head><meta http-equiv="Content-Type" content="text/html; charset=gb2312"><title>UNIX 屏幕导向程序的发展利器</title></head><body bgcolor="black" text="white" link="#0066ff" vlink="#9999ff" alink="red"><div align=center> </div><div align=right>Copyleft by <a href="mailto:rezaie@softhome.net">Wilbur Lang</a>. If you have any <br>question, please read <a href="javascript:if(confirm('http://personal.xfol.com/~rezaie/api/licensing.html \n\nThis file was not retrieved by Teleport Pro, because the server reports that this file cannot be found. \n\nDo you want to open it from the server?'))window.location='http://personal.xfol.com/%7Erezaie/api/licensing.html'" tppabs="http://personal.xfol.com/%7Erezaie/api/licensing.html">licenses</a>.</div><!-- ================================================================== --><!-- --><!-- Main Body --><!-- --> <p align="center"><font color="#9879c6"><big><big>UNIX 屏幕导向程序的发展利器 - curses (之二)</big></big></font></p> <p align="right">作者:林建宏</p><pre> 在上期为您介绍完了 curses.h 函式库的一些基本函式呼叫後在, 在本期里 , 我们将继续为您介绍 curses 有关多视窗处理的函式. 有了这些函式, 我们 可以在程式里同时处理多个不同的视窗. 如 joe 编辑器内我们可将萤幕切割 成好几个小萤幕, 并且可以在这些不同的萤幕间做切换并编辑不同的档案, 这 就是多视处理的应用. 另外, 有关 POP-UP 视窗的制作, 以及视窗的卷动, 在 本文里, 我们将以简单的例子, 告诉您这些功能是如何做到的. 关於一些较基 本函式的用法, 我们将不再特别介绍. 如果您尚未熟悉 curses 基本函式使用 方法, 请参阅上一期 (80 期 ) 通讯. ■ 视窗的建立 视窗的建立, 以 newwin() 这个函式来完成. 同时, 需宣告此视窗为 WINDOW 结构变数. WINDOW *newwin(lines,colums,start_y,start_x); WINDOW *win; win=newwin(10,20,0,0); 如此, 将以 (0,0) 为原点, 取一个 10 列 20 行的矩形为一新的视窗. 今後 我们只要呼叫 win 这个变数, 就可以对这新视窗做处理. 如: wmove(win,3,2); ■ 多视窗处理函式的格式 这一类函式和一般的基本函式极为类似, 几乎每一个基本函式都有一个对应的 视窗处理函式. 一般将 'w' 加在函式的里头作为区别, 'w' 乃 'window' 之 意. 另外, 因为可同时处理多个视窗, 在呼叫使用时, 需特别指定欲处理的视 窗. 当然, 如果您指定对 stdscr 做处理, 由於是对标准输出入萤幕处理, 其 作用将相当於一般基本的函式. 如: wmove(win,y,x) 即对 win 这个视窗做 move() 动作. wmove(stdscr,y,x) 相当於 move(y,x) 介绍一些较重要的函式 wmove(win,y,x) touchwin(win) wrefresh(win) mvwaddstr(win,y,x,str) wattron(attr) delwin(win) subwin(win,ny,nx,y,x) 其他函式多和基本函式互为对应, 故不全部列出, 详细名称可参考 curses 的 online manual. ■ 视窗内的座标系 视窗内的座标系, 将以此视窗的起始点为新原点, 并以其相对位置作为新的 座标. 举例来说 win=newwin(10,20,5,5); wmove(win,2,3); 将以 (5,5) 为新原点, y 方向移动 2 单位, x 方向移动 3 单位. 因此实际 上, 游标将移动至 y=7 x=8 的位置上. ■ POP-UP 视窗的建立 利用 curses 所提供的视窗处理函式, 我们可以做出像 ONLINE HELP 的 POP -UP 画面. 当按下某键後, 一个新的视窗将像 " 跳 " 出来一般覆盖原来的画 面. 当关掉此视窗後, 又不会影响到原来被覆盖的画面. 下面的例子, 我们及模拟 ONLINE HELP 的形式, 当按下 'h' 键时, 视窗即出现 #include <curses.h> main() { int ch,x,y; WINDOW *win; initscr(); ←┐ cbreak; │ 启动 curses 模式 noecho(); │ nonl(); ←┘ win=newwin(4,30,LINES/2-3, COLS/2-15);/* 建立一个新视窗, 其中LINES,COLS*/ box(win,'|','-'); /* 为 curses 内定值,即萤幕行/列数*/ mvwaddstr(win,1,4,"This is another screen"); mvwaddstr(win,2,2,"Press anykey to continue.."); for (y=0;y<LINES;++y) /* 以'@'填满萤幕 */ for (x=0;x<COLS;++x) mvprintw(y,x,"@"); for(;;) { refresh(); ch=getch(); switch(ch) { case 'q': /* 按 'q' 键离开 */ endwin(); exit(0); case '\t': /* 按 [TAB] 键 呼叫另一视窗 */ touchwin(win); /* wrefresh() 前需 touchwin() */ wrefresh(win); getch(); /* 按任意键关闭视窗 */ touchwin(stdscr); break; default:break; } } } 执行结果: ┌————————————————————————————┐ │ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │ │ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │ │ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │ │ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │ │ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │ │ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │ │ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │ │ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │ │ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │ │ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │ │ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │ │ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │ │ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │ └————————————————————————————┘ ↑ 原来画面被 '@' 填满, 按下[TAB]键後 ↓ 出现 POP-UP 画面. ┌————————————————————————————┐ │ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │ │ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │ │ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │ │ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │ │ @@@@@@@@@@@@@□---------------------------+@@@@@@@@@@@ │ │ @@@@@@@@@@@@@| This is another screen |@@@@@@@@@@@ │ │ @@@@@@@@@@@@@| Press anykey to continue.. |@@@@@@@@@@@ │ │ @@@@@@@@@@@@@□---------------------------+@@@@@@@@@@@ │ │ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │ │ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │ │ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │ │ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │ │ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │ └————————————————————————————┘ ■ 视窗的卷动 视窗的卷动, 掖Q用来配合视窗的处理, 当我们持续对视窗输出直到视窗的游 标移动至最後一列时, 如果我们再输出一列或是输出一个换行字元时, 视窗可 整个往上卷动一行. 这对我们撰写一个编辑程式时, 是尤其重要的, 一个画面 无法卷动的编辑器, 势必无法处理超过一个萤幕大小的档案. 视窗的卷动是预设为关闭的, 并以 scrollok() 来控制开闭. scrollok(win,TRUE); 开启 scrollok(win,FALSE); 关闭 下面的例子因为不断地输出 0,1,2.. 故将以一个 40 * 10 的视窗不停的卷动 #include <curses.h> main() { int i; WINDOW *scrwin,*boxwin; initscr(); ←┐ cbreak; │ 启动 curses 模式 noecho(); │ nonl(); ←┘ scrwin=newwin(10,40,LINES/2-6,COLS/2-25); /* 设定另一视窗大小 */ boxwin=newwin(12,42,LINES/2-7,COLS/2-26); /* 设定外框视窗大小 */ scrollok(scrwin,TRUE); /* 开启视窗卷动功能 */ box(boxwin,'|','-'); refresh(); wrefresh(boxwin); for (i=0;;++i) /* 不断地在视窗内输出 0-8 的数字,使视窗卷动*/ { wprintw(scrwin,"%d",i%9); wrefresh(scrwin); } } 执行结果: ┌——————————————————————┐ │ □---------------------□ │ │ |3456780123456780123412| ↑ 视 │ │ |3456780123456780123456| │ 窗 │ │ |7801234567801234567801| │ 不 │ │ |2345678012345678012345| │ 停 │ │ |6780123456780123456780| │ 往 │ │ |1234567801234567801234| │ 上 │ │ |5678012345678012345678| │ 卷 │ │ |0123456780123456780123| │ 动 │ │ □---------------------□ │ │ │ └——————————————————————┘ ■ □例 - 模拟 joe 分割画面同时编辑两个档案 在下面的例子里, 我们应用了多视窗处理的函式, 改良上回介绍的编辑器, 在这个程式里, 我们可以同时编辑两个画面, 并以 [ESC] 做不同视窗间的 切换. 同时, 按下 [TAB] 键, 会出现 POP-UP 的 ONLINE HELP. #include <curses.h> void initial(); main() { WINDOW *win[2],*curwin,*helpwin; int nowwin; int x,y; int i; int ch; initial(); win[0]=newwin(LINES/2-1,COLS-1,0,0); /* 设定两个视窗的大小*/ win[1]=newwin(LINES/2-1,COLS-1,LINES/2,0); helpwin=newwin(3,30,2,COLS/2-15 ); /* ONLINE HELP 的大小 */ box(helpwin,'|','-'); mvwaddstr(helpwin,0,10,"ONLINE HELP"); /* ONLINE HELP 的内容 */ mvwaddstr(helpwin,1,4,"Hit any key to continue.."); for (i=0;i<COLS-1;++i) /* 画两个视窗间的界限 */ mvaddch(LINES/2-1,i,'-'); nowwin=0; /* 先指定游标在第一视窗 */ curwin=win[nowwin]; getyx(curwin,y,x); move(0,0); refresh(); refresh(); do { ch=getch(); switch(ch) { case KEY_UP: --y; /* 判断是否"↑"键被按下 */ break; case KEY_DOWN: ++y; /* 判断是否"↓"键被按下 */ break; case KEY_RIGHT: ++x; /* 判断是否"→"键被按下 */ break; case KEY_LEFT: --x; /* 判断是否"←"键被按下 */ break; case '\r': /* 判断是否 ENTER 键被按下 */ ++y; x=0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -