Linux 版 (精华区)

发信人: tcpip (偶的昵称改了), 信区: Linux
标  题: UNIX 屏幕导向程序的发展利器 - curses (之二)
发信站: 紫 丁 香 (Fri Mar 24 19:13:48 2000) WWW-POST

Copyleft by Wilbur Lang. If you have any 
question, please read licenses.
UNIX 屏幕导向程序的发展利器 - curses (之二) 

作者:林建宏

     在上期为您介绍完了 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;
                       break;
             case '\t':                    /* 判断是否 TAB 键被按下      */
                       touchwin(helpwin);
                       wrefre

--
"这一千多年没写诗了?"
"写了, 不过只写了两句."
"千年得两句, 一定是万古丽句了. 念来听听."
"好吧, 我现丑了" 太白星清了清嗓子, 浑厚的男中音在天庭响起:
大海啊, 都是水;
骏马啊, 四条腿;

※ 来源:·紫 丁 香 bbs.hit.edu.cn·[FROM: 202.118.244.244] 
[百宝箱] [返回首页] [上级目录] [根目录] [返回顶部] [刷新] [返回]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:209.611毫秒