ncurses面板库:new_panel(),doupdate(),show_panel(),hide_panel(),move_panel(),del_panel()...

  • Copyright(C) NCURSES Programming HOWTO

面板库

在精通curses 库后,你可能会想尝试着做一些更大的项目。为了让界面看起来更专业,你可能会创建许多重叠的窗口,但不幸的是,你很快会发现它们变得难以管理,多次的更新窗口使开发变得异常困难。如果你没有按照适当的顺序刷新那些窗口的话,它们就会给你带来很多麻烦。

不过别失望,面板库(Panel Library)提供了一个很好的解决方案。用ncureses 的开发者的话来说就是:

如果你的界面设计需要使窗口在运行时置底或者置顶,虽然会为此付出很大代价,但是想要显示正确的结果仍然很困难。这时候Panels 库就可以派上用场了。 如果你要处理重叠的窗口,panels 库就派上用场了。它使程序员避免使用大量的wnoutrefresh()doupdate()函数来处理这个问题,并且减轻了由底向上正确处理这些信息的负担。这个库维持着窗口重叠关系以及窗口顺序,并在适当的时候更新它们。

那么还等什么呢?让我们开始吧!

基础知识

面板对象实际上是一个窗口,和其它窗口一样被隐含地处理为容器的一部分。这个容器实际上是一个,栈顶的面板是完全可见的。而其它面板在栈中所处的位置,决定了它们是否可见。其基本思想是:创建一个栈来保存那些重叠的面板,然后使用面板库来正确的显示它们。 例如调用一个类似于refresh()函数就按正确的顺序来显示这些面板。面板库提供了一系列隐藏、显示、移动、改变大小等面板操作的函数,使操作重叠的窗口变得更加简单。 通常,一个面板程序的设计流程如下:

  • 使用newwin()函数创建一个窗口,它将添加到面板里。
  • 创建面板(利用所创建的窗口)并将面板依据用户指定的可见顺序压进栈。调用new_panel()函数即可创建该面板。
  • 调用update_panels()函数就可将面板按正确的顺序写入虚拟屏幕,调用doupdate()函数就能让面板显示出来。
  • show_panel()hide_panel()move_panel()等函数分别用来对面板进行显示、隐藏、移动等操作时,可以使用panel_hidden()panel_window()这两个辅助函数。你也可以使用用户指针来存储面板的数据,set_panel_userptr()panel_userptr()函数分别用来设置和取得一个面板的用户指针。
  • 当一个面板使用完毕后,用del_panel()函数就可删除指定的面板。

现在让我们通过一些程序来加深对这些概念的理解。下面将要看到的程序创建了3 个重叠的面板并把它们按次序显示在屏幕上。

编译包含面板库的程序

要使用面板库里的函数,你首先要把panel.h 这个头文件包含到你的代码中,同时编译并连接与面板库相关的程序必须添加-lpanel–lncurses 两个参数。

#include <panel.h>

编译和连接: gcc <program file> -lpanel –lncurses

例.一个有关面板库的基础例子

/*
Compile: gcc main.c -lncurses -lpanel
*/
#include <ncurses.h>
#include <panel.h>

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();
}
/**
结果:
    ┌──────────────────────────────────────┐
    │    ┌──────────────────────────────────────┐
    │    │    ┌──────────────────────────────────────┐
    │    │    │                                      │
    │    │    │                                      │
    │    │    │                                      │
    │    │    │                                      │
    │    │    │                                      │
    │    │    │                                      │
    └────│    │                                      │
         └────│                                      │
              └──────────────────────────────────────┘
*/

如你所见,这个程序就是按照16.1 所介绍的流程进行的。用newwin()函数来创建窗口,然后通过new_panel()函数把窗口添加到panels 栈里面,当那些面板一个一个压进栈的时候,栈就随之更新了。最后调用update_panels()函数和doupdate()函数就可以让它们在屏幕上显示出来。

面板浏览

下面给出一个较复杂的例子。它创建了3 个窗口,通过<TAB> 键可以使它们循环置顶显示。让我们来看一下代码:

例 一个面板窗口浏览的例子

/*
Compile: gcc main.c -lncurses -lpanel
*/
#include <ncurses.h>
#include <panel.h>
#include <string.h>

#define NLINES 10
#define NCOLS 40

void init_wins(WINDOW **wins, int n);
void win_show(WINDOW *win, char *label, int label_color);
void print_in_middle(WINDOW *win, int starty, int startx, 
                     int width, char *string, chtype color);
int main()
{ 
    WINDOW *my_wins[3];
    PANEL *my_panels[3];
    PANEL *top;
    int ch;
    
    /*初始化curses */
    initscr();
    start_color();
    cbreak();
    noecho();
    keypad(stdscr, TRUE);
    
    /* 初始化所有的颜色*/
    init_pair(1, COLOR_RED, COLOR_WHITE);
    init_pair(2, COLOR_GREEN, COLOR_BLACK);
    init_pair(3, COLOR_BLUE, COLOR_BLACK);
    init_pair(4, COLOR_CYAN, COLOR_BLACK);
    init_wins(my_wins, 3);
    
    /* 按自底向上的顺序,把每个窗口添加进一个面板*/
    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*/
    /* 为下一个面板建立用户指针*/
    set_panel_userptr(my_panels[0],my_panels[1]);
    set_panel_userptr(my_panels[1],my_panels[2]);
    set_panel_userptr(my_panels[2],my_panels[0]);
    /* 更新面板栈的顺序。把面板2 置于栈顶*/
    update_panels();
    /* 在屏幕上显示*/
    attron(COLOR_PAIR(4));
    mvprintw(LINES-2, 0, "Use tab to browse through the windows (F1 to Exit)");
    attroff(COLOR_PAIR(4));
    doupdate();
    top = my_panels[2];
    while((ch = getch()) != KEY_F(1))
    { 
        switch(ch)
        { 
            case 9:
                top = (PANEL *)panel_userptr(top);
                top_panel(top);
                break;
        }
        update_panels();
        doupdate();
    }
    endwin();
    return 0;
}
/* 显示所有的窗口*/
void init_wins(WINDOW **wins, int n)
{ 
    int x, y, i;
    char label[80];
    
    y = 2;
    x = 10;
    
    for(i = 0; i < n; ++i)
    { 
        wins[i] = newwin(NLINES, NCOLS, y, x);
        sprintf(label, "Window Number %d", i + 1);
        win_show(wins[i], label, i + 1);
        y += 3;
        x += 7;
    }
}
/* 用一个边框和控件显示所有的窗口*/
void win_show(WINDOW *win, char *label, int label_color)
{ 
    int startx, starty, height, width;
    getbegyx(win, starty, startx);
    getmaxyx(win, height, width);
    box(win, 0, 0);
    mvwaddch(win, 2, 0, ACS_LTEE);
    mvwhline(win, 2, 1, ACS_HLINE, width-2);
    mvwaddch(win, 2, width-1,ACS_RTEE);
    print_in_middle(win, 1, 0, width, label, COLOR_PAIR(label_color));
}
void print_in_middle(WINDOW *win, int starty, int startx, 
                                  int width, char *string, chtype color)
{ 
    int length, x, y;
    float temp;
    if(win == NULL)
        win = stdscr;
    getyx(win, y, x);
    if(startx != 0)
        x = startx;
    if(starty != 0)
        y = starty;
    if(width == 0)
        width = 80;
    length = strlen(string);
    temp = (width - length)/2;
    x = startx + (int)temp;
    wattron(win, color);
    mvwprintw(win, y, x, "%s", string);
    wattroff(win, color);
    refresh();
}
/**
结果:
          ┌──────────────────────────────────────┐
          │           Window Number 1            │
          ├──────────────────────────────────────┤
          │      ┌──────────────────────────────────────┐
          │      │           Window Number 2            │
          │      ├──────────────────────────────────────┤
          │      │      ┌──────────────────────────────────────┐
          │      │      │           Window Number 3            │
          │      │      ├──────────────────────────────────────┤
          └──────│      │                                      │
                 │      │                                      │
                 │      │                                      │
                 └──────│                                      │
                        │                                      │
                        │                                      │
                        └──────────────────────────────────────┘
Use tab to browse through the windows (F1 to Exit)

*/

使用用户指针

在上面例子中,使用用户指针在循环里查找下一个要显示的面板。我们可以通过指定一个用户指针给面板添加自定义信息,这个指针可以指向你想要存储的任何信息。在这个例子中,我们用指针存储了循环中下一个要显示的面板。其中,用户指针可以用set_panel_userptr()函数设定。要想访问某个面板的用户指针,就必须以该面板作为panel_userprt()函数的参数,函数就会返回该面板的用户指针。结束面板的查找后, top_panel()函数就会将其置于面板栈的顶层。要想将任意一个面板置于面板栈的顶层,只需将该面板作为top_panel()函数的参数。

移动面板和改变面板的大小

move_panel()函数可将面板移动到屏幕上指定的位置,而不是改变面板在栈中的位置。确保在移动面板窗口时使用move_panel()函数,而不是mvwin()函数。改变面板大小有点儿复杂,因为没有一个函数可以直接改变面板所关联窗口的大小。一个可替代的解决方案是按照所需的大小创建一个新窗口,再调用replace_panel()函数来替换相应面板上的关联窗口。别忘了替换后删除原窗口,使用panel_window() 函数可以找到与该面板关联的窗口。 下面这个程序就体现了这种思想。你可以像先前那样,用<Tab>键循环查看窗口。如果要改变当前面板大小或移动当前面板的位置,就要分别按下‘r’‘m’键,然后使用方向键来调节,最后以<Enter>键确定大小或者位置.。这个例子利用用户数据保存程序运行的必要数据。

例、一个移动和改变面板大小的例子

/*
Compile: gcc main.c -lncurses -lpanel
*/
#include <ncurses.h>
#include <panel.h>
#include <string.h>
#include <stdlib.h>

typedef struct _PANEL_DATA
{
    int x, y, w, h;
    char label[80];
    int label_color;
    PANEL *next;
}PANEL_DATA;

#define NLINES 10
#define NCOLS 40

void init_wins(WINDOW **wins, int n);
void win_show(WINDOW *win, char *label, int label_color);
void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color);
void set_user_ptrs(PANEL **panels, int n);

int main()
{ 
    WINDOW *my_wins[3];
    PANEL *my_panels[3];
    PANEL_DATA *top;
    PANEL *stack_top;
    WINDOW *temp_win, *old_win;
    int ch;
    int newx, newy, neww, newh;
    int size = FALSE, move = FALSE;
    /* 初始化curses */
    initscr();
    start_color();
    cbreak();
    noecho();
    keypad(stdscr, TRUE);
    /* 初始化所有的颜色*/
    init_pair(1, COLOR_RED, COLOR_BLACK);
    init_pair(2, COLOR_GREEN, COLOR_BLACK);
    init_pair(3, COLOR_BLUE, COLOR_BLACK);
    init_pair(4, COLOR_CYAN, COLOR_BLACK);
    init_wins(my_wins, 3);
    /* 更新面板栈的顺序。把面板2 置于栈顶*/
    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*/
    set_user_ptrs(my_panels,3);
    /* 更新面板栈的顺序。把面板2 置于栈顶*/
    update_panels();
    /* 在屏幕上显示出来*/
    attron(COLOR_PAIR(4));
    mvprintw(LINES-3,0, "Use 'm' for moving, 'r' for resizing");
    mvprintw(LINES-2,0, "Use tab to browse through the windows (F1 to Exit)");
    attroff(COLOR_PAIR(4));
    doupdate();
    stack_top = my_panels[2];
    top = (PANEL_DATA *)panel_userptr(stack_top);
    newx = top->x;
    newy = top->y;
    neww = top->w;
    newh = top->h;
    while((ch = getch()) != KEY_F(1))
    { 
        switch(ch)
        { 
            case 9: /* Tab 对应编号*/
                top = (PANEL_DATA *)panel_userptr(stack_top);
                top_panel(top->next);
                stack_top = top->next;
                top = (PANEL_DATA *)panel_userptr(stack_top);
                newx = top->x;
                newy = top->y;
                neww = top->w;
                newh = top->h;
                break;
            case 'r': /* 改变面板大小*/
                size = TRUE;
                attron(COLOR_PAIR(4));
                mvprintw(LINES-4,0, "Entered Resizing :Use Arrow Keys to"\
                                    "resizeand press <ENTER> to end resizing");
                refresh();
                attroff(COLOR_PAIR(4));
                break;
            case 'm':/* 移动面板*/
                attron(COLOR_PAIR(4));
                mvprintw(LINES-4,0, "Entered Moving: Use Arrow Keys to"\
                                    "Move and press <ENTER> to end moving");
                refresh();
                attroff(COLOR_PAIR(4));
                move = TRUE;
                break;
            case KEY_LEFT:
                if(size == TRUE)
                { 
                    --newx;
                    ++neww;
                }
                if(move == TRUE)
                    --newx;
                break;
            case KEY_RIGHT:
                if(size == TRUE)
                { 
                    ++newx;
                    --neww;
                }
                if(move == TRUE)
                    ++newx;
                break;
            case KEY_UP:
                if(size == TRUE)
                { 
                    --newy;
                    ++newh;
                }
                if(move == TRUE) 
                    --newy;
                break;
            case KEY_DOWN:
                if(size == TRUE)
                { 
                    ++newy;
                    --newh;
                }
                if(move == TRUE)
                    ++newy;
                break;
            case 10: /* Enter 对应编号*/
                move(LINES-4,0);
                clrtoeol();
                refresh();
                if(size == TRUE)
                { 
                    old_win = panel_window(stack_top);
                    temp_win = newwin(newh, neww, newy, newx);
                    replace_panel(stack_top,temp_win);
                    win_show(temp_win, top->label, top->label_color);
                    delwin(old_win);
                    size = FALSE;
                }
                if(move == TRUE)
                { 
                    move_panel(stack_top,newy, newx);
                    move = FALSE;
                }
                break;
        }
        attron(COLOR_PAIR(4));
        mvprintw(LINES-3,0, "Use 'm' for moving, 'r' for resizing");
        mvprintw(LINES-2,0, "Use tab to browse through the windows (F1 to Exit)");
        attroff(COLOR_PAIR(4));
        refresh();
        update_panels();
        doupdate();
    }
    endwin();
    return 0;
}
/* 显示所有的窗口*/
void init_wins(WINDOW **wins, int n)
{ 
    int x, y, i;
    char label[80];
    y = 2;
    x = 10;
    for(i = 0; i < n; ++i)
    { 
        wins[i] = newwin(NLINES, NCOLS, y, x);
        sprintf(label, "Window Number %d", i + 1);
        win_show(wins[i], label, i + 1);
        y += 3;
        x += 7;
    }
}
/* 把每个面板设置为PANEL_DATA 结构*/
void set_user_ptrs(PANEL **panels, int n)
{ 
    PANEL_DATA *ptrs;
    WINDOW *win;
    int x, y, w, h, i;
    char temp[80];
    ptrs = (PANEL_DATA *)calloc(n, sizeof(PANEL_DATA));
    for(i = 0;i < n; ++i)
    { 
        win = panel_window(panels[i]);
        getbegyx(win, y, x);
        getmaxyx(win, h, w);
        ptrs[i].x = x;
        ptrs[i].y = y;
        ptrs[i].w = w;
        ptrs[i].h = h;
        sprintf(temp, "Window Number %d", i + 1);
        strcpy(ptrs[i].label,temp);
        ptrs[i].label_color = i + 1;
        if(i + 1 == n)
            ptrs[i].next = panels[0];
        else
            ptrs[i].next = panels[i + 1];
        set_panel_userptr(panels[i],&ptrs[i]);
    }
}
/* 用一个边框和标题栏来显示窗口*/
void win_show(WINDOW *win, char *label, int label_color)
{
    int startx, starty, height, width;
    getbegyx(win, starty, startx);
    getmaxyx(win, height, width);
    box(win, 0, 0);
    mvwaddch(win, 2, 0, ACS_LTEE);
    mvwhline(win, 2, 1, ACS_HLINE, width-2);
    mvwaddch(win, 2, width-1,ACS_RTEE);
    print_in_middle(win, 1, 0, width, label, COLOR_PAIR(label_color));
}
void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color)
{ 
    int length, x, y;
    float temp;
    if(win == NULL)
        win = stdscr;
    getyx(win, y, x);
    if(startx != 0)
        x = startx;
    if(starty != 0)
        y = starty;
    if(width == 0)
        width = 80;
    length = strlen(string);
    temp = (width-length)/2;
    x = startx + (int)temp;
    wattron(win, color);
    mvwprintw(win, y, x, "%s", string);
    wattroff(win, color);
    refresh();
}

结果测试

原始:
          ┌──────────────────────────────────────┐
          │           Window Number 1            │
          ├──────────────────────────────────────┤
          │      ┌──────────────────────────────────────┐
          │      │           Window Number 2            │
          │      ├──────────────────────────────────────┤
          │      │      ┌──────────────────────────────────────┐
          │      │      │           Window Number 3            │
          │      │      ├──────────────────────────────────────┤
          └──────│      │                                      │
                 │      │                                      │
                 │      │                                      │
                 └──────│                                      │
                        │                                      │
                        │                                      │
                        └──────────────────────────────────────┘
Use 'm' for moving, 'r' for resizing
Use tab to browse through the windows (F1 to Exit)

Tab键功能:
          ┌──────────────────────────────────────┐
          │           Window Number 1            │
          ├──────────────────────────────────────┤
          │                                      │──────┐
          │                                      │      │
          │                                      │──────┤
          │                                      │─────────────┐
          │                                      │3            │
          │                                      │─────────────┤
          └──────────────────────────────────────┘             │
                 │      │                                      │
                 │      │                                      │
                 └──────│                                      │
                        │                                      │
                        │                                      │
                        └──────────────────────────────────────┘
                        
调整大小:
          ┌──────────────────────────────────────┐──────┐
          │           Window Number 1            │      │
          ├──────────────────────────────────────┤──────┤
          │                                      │─────────────┐
          │                                      │3            │
          │                                      │─────────────┤
          └──────────────────────────────────────┘             │
                 │      │                                      │
                 │      │                                      │
                 └──────│                                      │
                        │                                      │
                        │                                      │
                        └──────────────────────────────────────┘

调整位置:
          ┌──────────────────────────────────────┐
          │           Window Number 1            │
          ├──────────────────────────────────────┤
          │   ┌──────────────────────────────────────┐─────────┐
          │   │           Window Number 2            │         │
          │   ├──────────────────────────────────────┤─────────┤
          └───│                                      │         │
              │                                      │         │
              │                                      │         │
              │                                      │         │
              │                                      │         │
              │                                      │         │
              └──────────────────────────────────────┘─────────┘

让我们把注意力集中在主while 循环体上。一旦该循环发现某个键被按下,程序就会执行该键相应的处理。 当按下‘r’键时,程序就会执行“更改大小”操作,同时你就可以通过方向键更改面板的大小,然后按<Enter>键确定大小。在“更改大小”模式下,程序不会显示窗口是怎样更改大小的。请读者思考一下如何用“点”来打印更改大小后窗口的边框。 当按下‘m’键时,程序就会执行“移动面板”操作。这个操作比“更改大小”简单一点。按下方向键的同时,面板的位置随之改变,当按下<Enter>键时,程序就会调用move_panel()函数把面板固定到当前光标的位置。 在这个程序中, PANEL_DATA 就是所谓的用户数据,它在查找面板的相关信息时扮演重要角色,正如说明中所说的那样,PANEL_DATA保存了面板的尺寸,标题,标题颜色以及指向下一个面板的指针。

隐藏和显示面板

使用hide_panel()函数可以隐藏面板,它仅仅是把面板从面板栈中移走,不会破坏被隐藏面板所关联的结构。而要在屏幕上隐藏面板需要调用update_panels()函数和doupdate()函数。此外,show_panel()函数可以让显示已隐藏面板。 以下程序展示了面板的隐藏。按下’a’ 或’b’ 或‘c’ 键分别显示或隐藏第一、二、三个窗口。使用了用户数据中一个叫做hide 的变量来跟踪窗口,标记出该窗口是否被隐藏。由于某些原因,panel_hidden()函数(它用来告诉用户一个面板是否隐藏)不能够正常工作。MichaelAndres 在这里提供了一个错误报告。

例、一个隐藏和显示面板的例子

/*
Compile: gcc main.c -lncurses -lpanel
*/
#include <ncurses.h>
#include <panel.h>
#include <string.h>
#include <stdlib.h>

typedef struct _PANEL_DATA {
    int hide; /* 如果面板是隐藏的时候为真*/
}PANEL_DATA;

#define NLINES 10
#define NCOLS 40

void init_wins(WINDOW **wins, int n);
void win_show(WINDOW *win, char *label, int label_color);
void print_in_middle(WINDOW *win, int starty, int startx, 
                     int width, char *string, chtype color);
int main()
{ 
    WINDOW *my_wins[3];
    PANEL *my_panels[3];
    PANEL_DATA panel_datas[3];
    PANEL_DATA *temp;
    int ch;
    
    /* 初始化curses */
    initscr();
    start_color();
    cbreak();
    noecho();
    keypad(stdscr, TRUE);
    
    /* 初始化所有的颜色*/
    init_pair(1, COLOR_RED, COLOR_BLACK);
    init_pair(2, COLOR_GREEN, COLOR_BLACK);
    init_pair(3, COLOR_BLUE, COLOR_BLACK);
    init_pair(4, COLOR_CYAN, COLOR_BLACK);
    
    init_wins(my_wins, 3);
    
    /* 更新面板栈的顺序。把面板2 置于栈顶*/
    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*/
    
    /* 初始化所有的面板并都设为非隐藏的*/
    panel_datas[0].hide= FALSE;
    panel_datas[1].hide= FALSE;
    panel_datas[2].hide= FALSE;
    set_panel_userptr(my_panels[0],&panel_datas[0]);
    set_panel_userptr(my_panels[1],&panel_datas[1]);
    set_panel_userptr(my_panels[2],&panel_datas[2]);
    /* 更新面板栈的顺序,第二个面板将置于栈顶*/
    update_panels();
    /* 在屏幕上显示*/
    attron(COLOR_PAIR(4));
    mvprintw(LINES-3,0, "Show or Hide a window with 'a'(first window)"\
                        "'b'(Second Window)'c'(ThirdWindow)");
    mvprintw(LINES-2,0, "F1 to Exit");
    attroff(COLOR_PAIR(4));
    doupdate();
    while((ch = getch()) != KEY_F(1))
    {
        switch(ch)
        { 
            case 'a':
                temp = (PANEL_DATA *)panel_userptr(my_panels[0]);
                if(temp->hide == FALSE)
                { 
                    hide_panel(my_panels[0]);
                    temp->hide = TRUE;
                }
                else
                { 
                    show_panel(my_panels[0]);
                    temp->hide = FALSE;
                }
                break;
            case 'b':
                temp = (PANEL_DATA *)panel_userptr(my_panels[1]);
                if(temp->hide == FALSE)
                { 
                    hide_panel(my_panels[1]);
                    temp->hide = TRUE;
                }
                else
                { 
                    show_panel(my_panels[1]);
                    temp->hide = FALSE;
                }
                break;
            case 'c':
                temp = (PANEL_DATA *)panel_userptr(my_panels[2]);
                if(temp->hide == FALSE)
                { 
                    hide_panel(my_panels[2]);
                    temp->hide = TRUE;
                }
                else
                { 
                    show_panel(my_panels[2]);
                    temp->hide = FALSE;
                }
                break;
        }
        update_panels();
        doupdate();
    }
    endwin();
    return 0;
}
/* 显示所有窗口*/
void init_wins(WINDOW **wins, int n)
{ 
    int x, y, i;
    char label[80];
    y = 2;
    x = 10;
    for(i = 0; i < n; ++i)
    { 
        wins[i] = newwin(NLINES, NCOLS, y, x);
        sprintf(label, "Window Number %d", i + 1);
        win_show(wins[i], label, i + 1);
        y += 3;
        x += 7;
    }
}
/* 通过边框和标题显示窗口*/
void win_show(WINDOW *win, char *label, int label_color)
{
    int startx, starty, height, width;
    getbegyx(win, starty, startx);
    getmaxyx(win, height, width);
    box(win, 0, 0);
    mvwaddch(win, 2, 0, ACS_LTEE);
    mvwhline(win, 2, 1, ACS_HLINE, width-2);
    mvwaddch(win, 2, width-1,ACS_RTEE);
    print_in_middle(win, 1, 0, width, label, COLOR_PAIR(label_color));
}

void print_in_middle(WINDOW *win, int starty, int startx, 
                     int width, char *string, chtype color)
{
    int length, x, y;
    float temp;
    if(win == NULL)
        win = stdscr;
    getyx(win, y, x);
    if(startx != 0)
        x = startx;
    if(starty != 0)
        y = starty;
    if(width == 0)
        width = 80;
    length = strlen(string);
    temp = (width-length)/2;
    x = startx + (int)temp;
    wattron(win, color);
    mvwprintw(win, y, x, "%s", string);
    wattroff(win, color);
    refresh();
}

测试结果

原始:
          ┌──────────────────────────────────────┐
          │           Window Number 1            │
          ├──────────────────────────────────────┤
          │      ┌──────────────────────────────────────┐
          │      │           Window Number 2            │
          │      ├──────────────────────────────────────┤
          │      │      ┌──────────────────────────────────────┐
          │      │      │           Window Number 3            │
          │      │      ├──────────────────────────────────────┤
          └──────│      │                                      │
                 │      │                                      │
                 │      │                                      │
                 └──────│                                      │
                        │                                      │
                        │                                      │
                        └──────────────────────────────────────┘
Show or Hide a window with 'a'(first window)'b'(Second Window)'c'(ThirdWindow)
F1 to Exit

隐藏window1,press“a”
                 ┌──────────────────────────────────────┐
                 │           Window Number 2            │
                 ├──────────────────────────────────────┤
                 │      ┌──────────────────────────────────────┐
                 │      │           Window Number 3            │
                 │      ├──────────────────────────────────────┤
                 │      │                                      │
                 │      │                                      │
                 │      │                                      │
                 └──────│                                      │
                        │                                      │
                        │                                      │
                        └──────────────────────────────────────┘
同理,隐藏window2和window3按“b”,“c”
          ┌──────────────────────────────────────┐
          │           Window Number 1            │
          ├──────────────────────────────────────┤
          │                                      │
          │                                      │
          │                                      │
          │                                      │─────────────┐
          │                                      │3            │
          │                                      │─────────────┤
          └──────────────────────────────────────┘             │
                        │                                      │
                        │                                      │
                        │                                      │
                        │                                      │
                        │                                      │
                        └──────────────────────────────────────┘
          ┌──────────────────────────────────────┐
          │           Window Number 1            │
          ├──────────────────────────────────────┤
          │      ┌──────────────────────────────────────┐
          │      │           Window Number 2            │
          │      ├──────────────────────────────────────┤
          │      │                                      │
          │      │                                      │
          │      │                                      │
          └──────│                                      │
                 │                                      │
                 │                                      │
                 └──────────────────────────────────────┘

panel_above()panel_below()类函数

panel_above()panel_below()函数可以分别用来查看某个面板的上层和下层面板。如果参数为NULL,它们就分别返回面板栈中最上层和最下层面板的指针。

猜你喜欢

转载自blog.csdn.net/rong_toa/article/details/80774978