控制台界面控制(七):移动文本

来源:互联网 发布:数据集成技术 编辑:程序博客网 时间:2024/04/29 23:11

本文为转载文档,原文链接:http://blog.csdn.net/bnb45/article/details/8034597


控制文本的移动,可以取代清屏再重绘操作。如果用来做文本编辑器的滚动条是很合适的,也许也可以用在俄罗斯方块上面。控制台使用一个函数把某个区域内的文本移动到另一个区域。

效果

在缓冲区中输出4行字,分别在对应的行上。然后使用移动文本的函数把第三行后面的文本移到第一行后面;

[cpp] view plaincopy
  1. #include "MyConsole.h"  
  2. #include <stdio.h>  
  3.   
  4. int main()    
  5. {    
  6.     CMyConsole myConsole;    
  7.   
  8.     printf("\n1111111111111111111\n");  
  9.     printf("2222222222222222222\n");  
  10.     printf("3333333333333333333\n");  
  11.     printf("4444444444444444444\n");  
  12.   
  13.     system("pause");    // 暂停  
  14.   
  15.     SMALL_RECT rc = {0, 3, 30, 20};     // 要移动的区域  
  16.     myConsole.MoveText(rc, 10, 1);      // 移动到坐标(10,1)  
  17.     system("pause");    
  18.   
  19.     return 0;    
  20. }    

    

相关信息

缓冲区的文本移动使用的函数是:ScrollConsoleScreenBuffer,文本中对它的解释如下:

[cpp] view plaincopy
  1. BOOL ScrollConsoleScreenBuffer(  
  2.             HANDLE              hConsoleOutput,         // 句柄  
  3.             CONST SMALL_RECT*   lpScrollRectangle,      // 要滚动或移动的区域  
  4.             CONST SMALL_RECT*   lpClipRectangle,        // 裁剪区域  
  5.             COORD               dwDestinationOrigin,    // 新的位置  
  6.             CONST CHAR_INFO*    lpFill                  // 填充字符  
  7.  );  

比较容易搞不明白的是第二个参数和第三个参数,它们都是 SMALL_RECT 指针类型。为了说明这个函数的使用方法,教程里还举了另一个函数为例:DeleteLine。它的功能是删除指定行,并将下面的文本上移,例如删除上面例子中的第二行,则1111的下一行变成了3333。

[cpp] view plaincopy
  1. void DeleteLine(int row)  
  2. {  
  3.     SMALL_RECT  rcScroll, rcClip;  
  4.     COORD       crDest = {0, row - 1};  
  5.     CHAR_INFO   chFill;  
  6.   
  7.     CONSOLE_SCREEN_BUFFER_INFO bInfo;  
  8.     GetConsoleScreenBufferInfo( hOut, &bInfo );     // 获取控制台信息  
  9.   
  10.     rcScroll.Left = 0;  
  11.     rcScroll.Top = row;  
  12.     rcScroll.Right = bInfo.dwSize.X - 1;  
  13.     rcScroll.Bottom = bInfo.dwSize.Y - 1;           // 设置要滚动的区域  
  14.   
  15.     rcClip = rcScroll;                              // 设置裁剪区域  
  16.   
  17.     chFill.Attributes = bInfo.wAttributes;  
  18.     chFill.Char.AsciiChar = ' ';                    // 设置要填充的文本和属性  
  19.   
  20.     ScrollConsoleScreenBuffer(hOut, &rcScroll, &rcClip, crDest, &chFill);  
  21. }  

上面的一段代码中,滚动区域从要删除的行开始到缓冲区的末尾,裁剪区域和滚动区域一样。然后把这一整块移动到要删除的行的前一行(上移),根据教程的说法,因为向上一行不包括在裁剪区域内,所以不会被更新,也就是消失了,从而达到删除行的目的。从这里可以了解到更多的信息,比如简单如第一参数(句柄),第四参数(目标坐标),第五参数(替换为空,属性为控制台现有属性)。即使这样,对于第二和第三参数的理解仍然不够透彻。接下来以上面的四行输出做两个实验:

实验一:滚动区域大于裁剪区域

滚动区域为第二行到末尾,裁剪区域为第二行和第三行;执行上移一行操作:


第二、三行和第四行都上移了,第二行因为超出裁剪区被裁剪掉,原本的第四行没变。它在裁剪区域外。

实验二:裁剪区域大于滚动区域

滚动区域为第二行到第三行,裁剪区域为第二行到末尾;执行上移一行操作:


第二、三行上移,第二行被裁剪,第三行由参数填充;

ScrollConsoleScreenBuffer 结论


  1. 首先对滚动区域执行移动操作;
  2. 产生两个画面:移动前画面;移动后画面;
  3. 裁剪区域绘制的是移动后画面;
  4. 裁剪区域绘制的是移动前画面;

文本移动函数

[cpp] view plaincopy
  1. // ---- 移动文本  
  2. void CMyConsole::MoveText(SMALL_RECT rc, int x, int y)  
  3. {  
  4.     COORD       crDest =  {x, y};  
  5.     CHAR_INFO   chFill;  
  6.   
  7.     chFill.Attributes = bInfo.wAttributes;  
  8.     chFill.Char.AsciiChar = ' ';  
  9.   
  10.     // -- 滚动和移动文本  
  11.     // @param   HANDLE              [in] 句柄  
  12.     // @param   CONST SMALL_RECT *  [in] 要滚动或移动的区域  
  13.     // @param   CONST SMALL_RECT *  [in] 裁剪区域,NULL时为默认整个缓冲区  
  14.     // @param   COORD               [in] 新的位置  
  15.     // @param   CONST CHAR_INFO     [in] 填充字符  
  16.     ScrollConsoleScreenBuffer(hOut, &rc, NULL, crDest, &chFill);  
  17. }  



0 0
原创粉丝点击