8. 属性

我们已经看到了如何使用属性来打印具有特殊效果的字符的示例。谨慎地设置属性可以以简单易懂的方式呈现信息。以下程序接受 C 文件作为输入,并以粗体打印文件中的注释。浏览代码。

示例 5. 一个简单的属性示例

/* pager functionality by Joseph Spainhour" <spainhou@bellsouth.net> */
#include <ncurses.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{ 
  int ch, prev, row, col;
  prev = EOF;
  FILE *fp;
  int y, x;

  if(argc != 2)
  {
    printf("Usage: %s <a c file name>\n", argv[0]);
    exit(1);
  }
  fp = fopen(argv[1], "r");
  if(fp == NULL)
  {
    perror("Cannot open input file");
    exit(1);
  }
  initscr();				/* Start curses mode */
  getmaxyx(stdscr, row, col);		/* find the boundaries of the screeen */
  while((ch = fgetc(fp)) != EOF)	/* read the file till we reach the end */
  {
    getyx(stdscr, y, x);		/* get the current curser position */
    if(y == (row - 1))			/* are we are at the end of the screen */
    {
      printw("<-Press Any Key->");	/* tell the user to press a key */
      getch();
      clear();				/* clear the screen */
      move(0, 0);			/* start at the beginning of the screen */
    }
    if(prev == '/' && ch == '*')    	/* If it is / and * then only
                                     	 * switch bold on */    
    {
      attron(A_BOLD);			/* cut bold on */
      getyx(stdscr, y, x);		/* get the current curser position */
      move(y, x - 1);			/* back up one space */
      printw("%c%c", '/', ch); 		/* The actual printing is done here */
    }
    else
      printw("%c", ch);
    refresh();
    if(prev == '*' && ch == '/')
      attroff(A_BOLD);        		/* Switch it off once we got *
                                 	 * and then / */
    prev = ch;
  }
  endwin();                       	/* End curses mode */
  fclose(fp);
  return 0;
}

不要担心所有那些初始化和其他废话。专注于 while 循环。它读取文件中的每个字符并搜索模式 /*。一旦发现该模式,它就会使用以下代码打开 BOLD 属性:attron()。当我们得到模式 */ 时,它会被以下代码关闭:attroff() .

上面的程序还向我们介绍了两个有用的函数:getyx()move()。第一个函数将当前光标的坐标获取到变量 y, x 中。由于 getyx() 是一个宏,我们不必传递变量的指针。函数move()将光标移动到给定的坐标。

上面的程序实际上是一个简单的程序,功能不多。沿着这些思路,可以编写一个更有用的程序,该程序读取 C 文件,解析它并以不同的颜色打印它。甚至可以将其扩展到其他语言。

8.1. 详细信息

让我们深入了解属性的更多细节。函数attron(), attroff(), attrset(),及其姊妹函数attr_get()等等,可用于打开/关闭属性、获取属性并产生彩色显示。

函数 attron 和 attroff 接受属性的位掩码,并分别打开或关闭它们。以下视频属性(在 <curses.h> 中定义)可以传递给这些函数。

    
    A_NORMAL        Normal display (no highlight)
    A_STANDOUT      Best highlighting mode of the terminal.
    A_UNDERLINE     Underlining
    A_REVERSE       Reverse video
    A_BLINK         Blinking
    A_DIM           Half bright
    A_BOLD          Extra bright or bold
    A_PROTECT       Protected mode
    A_INVIS         Invisible or blank mode
    A_ALTCHARSET    Alternate character set
    A_CHARTEXT      Bit-mask to extract a character
    COLOR_PAIR(n)   Color-pair number n 
    

最后一个是最丰富多彩的 :-) 颜色将在下一节中解释。

我们可以对任意数量的上述属性进行 OR(|) 运算,以获得组合效果。如果您想要具有闪烁字符的反相视频,可以使用

    attron(A_REVERSE | A_BLINK);

8.2. attron() 与 attrset()

那么 attron() 和 attrset() 之间有什么区别呢?attrset 设置窗口的属性,而 attron 只是打开赋予它的属性。因此,attrset() 完全覆盖窗口先前拥有的任何属性,并将其设置为新属性。同样,attroff() 只是关闭作为参数赋予它的属性。这使我们能够灵活地轻松管理属性。但是,如果您不小心使用它们,您可能会丢失对窗口具有哪些属性的跟踪,并使显示混乱。在管理带有颜色和突出显示的菜单时,尤其如此。因此,请确定一致的策略并坚持下去。您始终可以使用standend(),它等效于attrset(A_NORMAL),它关闭所有属性并将您带回正常模式。

8.3. attr_get()

函数 attr_get() 获取窗口的当前属性和颜色对。尽管我们可能不会像上面这些函数那样频繁地使用它,但在扫描屏幕区域时,它很有用。假设我们想要在屏幕上进行一些复杂的更新,并且不确定每个字符与什么属性关联。那么这个函数可以与 attrset 或 attron 一起使用,以产生所需的效果。

8.4. attr_ 函数

有一系列函数,如 attr_set()、attr_on 等。这些函数与上述函数类似,只是它们采用类型为attr_t.

8.5. wattr 函数

对于上述每个函数,我们都有一个带有 'w' 的对应函数,它在特定窗口上运行。上述函数在 stdscr 上运行。

8.6. chgat() 函数

函数 chgat() 列在手册页 curs_attr 的末尾。它实际上是一个有用的函数。此函数可用于为一组字符设置属性而无需移动。我的意思是它!!!无需移动光标 :-) 它更改从当前光标位置开始的给定数量的字符的属性。

我们可以将 -1 作为字符计数,以更新到行尾。如果您想更改从当前位置到行尾的字符的属性,只需使用它。

    chgat(-1, A_REVERSE, 0, NULL);

当更改屏幕上已有的字符的属性时,此函数非常有用。移动到要更改的字符,然后更改属性。

其他函数 wchgat()、mvchgat()、wchgat() 的行为类似,只是 w 函数在特定窗口上运行。mv 函数首先移动光标,然后执行赋予它们的工作。实际上,chgat 是一个宏,它被替换为以 stdscr 作为窗口的 wchgat()。大多数“无 w”函数都是宏。

示例 6. Chgat() 用法示例

#include <ncurses.h>

int main(int argc, char *argv[])
{	initscr();			/* Start curses mode 		*/
	start_color();			/* Start color functionality	*/
	
	init_pair(1, COLOR_CYAN, COLOR_BLACK);
	printw("A Big string which i didn't care to type fully ");
	mvchgat(0, 0, -1, A_BLINK, 1, NULL);	
	/* 
	 * First two parameters specify the position at which to start 
	 * Third parameter number of characters to update. -1 means till 
	 * end of line
	 * Forth parameter is the normal attribute you wanted to give 
	 * to the charcter
	 * Fifth is the color index. It is the index given during init_pair()
	 * use 0 if you didn't want color
	 * Sixth one is always NULL 
	 */
	refresh();
    	getch();
	endwin();			/* End curses mode		  */
	return 0;
}

此示例还向我们介绍了 curses 的颜色世界。颜色将在稍后详细解释。使用 0 表示无颜色。