Win32 Console Applications

Win32 Console Applications
[ 主要内容是翻译自一篇国外的文章,我一边看,一边挑重点翻译了让自己好看,就有了本文 ]
 
记得刚学 C++ 的发现怎么做出来的程序都是黑乎乎的,难看死了。后来知道了 MFC 这个 GUI 库,才知道漂亮的程序是这么写出来的,当然 SDK 也可以写。后来一次浏览网站发现了《 Win32 Console Applications 》,才知道控制台也可以进行界面编程。控制台应用程序,它看起来象是 DOS 应用程序,但它却是 WIN32 的程序,拥有独立的 4GB 虚拟内存空间。

屏幕 I/O 的许多基本动作只能在控制台模式下才能正常工作。也就是说,在控制台的 C 程序中,你必须包含 STDIO.H 和(或) CONIO.H 文件才能使用 printf gets getchar getch 等函数。这些函数让你可以控制在屏幕上输出数据。而 C++ 程序则使用 iostream.h ,因为 cin cout 。他们是不能同时存在。这里我使用 C++ 做示范, IDE VC++6.0

//-----------------------------
修改标题 ------------------------
默认的,控制台程序是用程序所在的完整路径做为窗口标题。如果我们想改变标题可以使用 API 函数
SetConsoleTitle
,但是注意要包含头文件 windows.h 。还要注意的是这只适合与 VC++ 控制台程序。
C
程序在它的编译器 TC 里有单独的方法。

#include <windows.h>
#include <iostream.h>

int main()
{
SetConsoleTitle("Hello!");
cout << "Hello World!" << endl;
return 0;
}


//-----------------------------
出错机智 ------------------------
正如通常一样,所有的 API 函数都会返回调用成功或者失败的状态 . 上面的例子中我并没有检查返回值 .
为了更加专业 , 当你调用 API 函数的时候应该检查它的返回值 . 即使你不能修复这个错误 , 调试的时候去
发现调用不成功的原因依然是有用的 , 最好能知道为什么 . 下面这个程序示范了如何处理返回值 , ( 注意
常规 API exit() 包含在 process.h ). 你应翻阅编译器的帮助文件或者 MSDN 来理解返回值表示的意义。

#include <windows.h>
#include <process.h>
#include <iostream.h>

int main()
{
int Status;

Status = SetConsoleTitle("Hello!");
if (Status == 0)
{
  Status = GetLastError();
  cout << "SetConsoleTitle() failed! Reason : " << Status << endl;
  exit(Status);
}

cout << "Hello World!" << endl;
return 0;
}

//-----------------------------
标准句柄 ------------------------
所有的控制台有 3 " 标准句柄 " ,并且许多控制台处理函数需要 HANDLE 作为参数来处理 I/O
一个句柄就是一个 32 位整数 . 它是窗口用来对同型事物进行区别的 . 考虑一下控制台 , 它有一个标题栏
,最小化、最大化、关闭按纽,一个或多个滚动条 . 那就是,当你想到这些是多么复杂的一件事。 Windows 隐藏所有复杂的东西 , 当然你也可以自己处理这些东西,但是我的建议是如果不需要处理,你
最好别动 . Windows 会为你照顾好一切 , 你所需要做的就是使用句柄处理你感兴趣的东西 . 一旦你深入到
windows
程序 , 你就会发现需要事情需要 handle 的支持。如果你现在不明白,也不必要担心,句柄非常容易获得也非常容易处理。

为了得到句柄 , 你需要声明 HANDLE 类型的变量并调用 GetStdHandle() 函数来初始化它 .
函数 GetStdHandle(), 其声明如下
HANDLE GetStdHandle(
DWORD nStdHandle
);
GetStdHandle()
返回标准的输入、输出或错误的设备的句柄 , 也就是获得输入、输出 / 错误的屏幕
缓冲区的句柄 . 其参数 nStdHandle 的值为下面几种类型的一种 :
          含义
STD_INPUT_HANDLE
标准输入的句柄
STD_OUTPUT_HANDLE
标准输出的句柄
STD_ERROR_HANDLE
标准错误的句柄
下面这个程序演示了如何获得句柄。

#include <windows.h>

int main()
{
HANDLE hIn;
HANDLE hOut;
HANDLE hError;

hIn = GetStdHandle(STD_INPUT_HANDLE);
hOut = GetStdHandle(STD_OUTPUT_HANDLE);
hError = GetStdHandle(STD_ERROR_HANDLE);

return 0;
}

这里有两个常规函数 ReadConsole() WriteConsole() 会使用到句柄。


//-----------------------------
改变输出光标位置 ------------------------
现在我们已经可以得到句柄 , 是时候我们该做些什么了 , 那么就让我们来改变光标输出位置 . 其中我们
需要使用到结构体 COORD. 这是简单的结构体包含一个 x y 坐标对 . 它的定义如下:
typedef struct _COORD {
SHORT X;
SHORT Y;
} COORD;
屏幕左上角为原点 (0,0) 。往右 X 为正,往下 Y 为正。
为了移动光标 , 你只要简单的使用 COORD 指定你想光标移动到的坐标值并且调 API 函数 SetConsoleCursorPosition() 。下面是简单的示范。

#include <windows.h>
#include <iostream.h>

int main()
{
HANDLE hOut;
int i;
COORD Position;

hOut = GetStdHandle(STD_OUTPUT_HANDLE);

for(i=0; i<10; i+=2)
{
  Position.X = i;
  Position.Y = i;
  SetConsoleCursorPosition(hOut,
              Position);
  cout << "*" << flush;
}

return 0;
}
正如你所理解的 , 每步循环移动光标两格下两格右。如果想还原,只要把坐标设为 (0,0).


//-----------------------------
自定义位置输出 ------------------------
下面要介绍的是函数 FillConsoleOutputCharacter(). 这个函数允许你自定义位置填充字符串 .
函数原型如下:
BOOL FillConsoleOutputCharacter(
HANDLE hConsoleOutput,//
标准输出句柄
TCHAR cCharacter,   //
要输出的字符
DWORD nLength,   //
输出字符的次数
COORD dwWriteCoord,   //
开始输出坐标
LPDWORD lpNumberOfCharsWritten //
存放所写的字节数,并作为函数的返回值
);
如果你写的字符个数超过一行,输出会转到下一行继续进行。如果你试图写的字符数超出了缓冲区
范围,什么事也不会发生,也不会有额外的调用来处理这些多出的字符。这样,如果你用 80x25 格式的
代码写程序就很安全。如果你要计算用来刷新整个屏幕字符的确切数目,可以使用
GetConsoleScreenBufferInfo
函数。

下面这个例子使用 FillConsoleOutputCharacter() 来从 (4,4) 开始输出一行 15 "X" 字符。

#include <windows.h>
#include <iostream.h>

int main()
{
HANDLE hOut;
COORD Position;
DWORD Written;

hOut = GetStdHandle(STD_OUTPUT_HANDLE);

Position.X = 4;
Position.Y = 4;

FillConsoleOutputCharacter(hOut,
            'X',
            15,
            Position,
            &Written);

return 0;
}

//-----------------------------
自定义位置输入 ------------------------
下面介绍的这个函数可以屏幕缓冲区的指定位置读入一个和多个字符。参数基本同上一个介绍的函数。
BOOL ReadConsoleOutputCharacter(
HANDLE hConsoleOutput,
LPTSTR lpCharacter,
DWORD nLength,
COORD dwReadCoord,
LPDWORD lpNumberOfCharsRead
);

这个程序使用了函数两次 , 第一次从 (0,0) 处读入一个字符,第二次从 (4,0) 读入五个字符 . 如果要读入
的字符长度大于现有行的字符个数,那么继续从下一行读入字符补足。当然正如前面也说过的,如果要
读入字符个数大于了缓冲区,读到缓冲区最后一个字符就会返回。实际读入的字符个数将在最后一个参
数返回。

#include <windows.h>
#include <iostream>
using namespace std;

int main()
{
HANDLE hOut;
char Letter;
char Letters[5];
COORD Where;
DWORD NumRead;
int i;

hOut = GetStdHandle(STD_OUTPUT_HANDLE);

cout << "A line of little consequence." << endl;

Where.X = 0;
Where.Y = 0;
ReadConsoleOutputCharacter(hOut,
            &Letter,
            1,
            Where,
            &NumRead);
cout << "Letter at (0,0) is " << Letter << endl;

Where.X = 4;
ReadConsoleOutputCharacter(hOut,
            Letters,
            5,
            Where,
            &NumRead);
cout << "5 letters starting from (4,0) ";
for (i=0; i<5; i++)
{
  cout << Letters;
}
cout << endl;

return 0;
}

//-----------------------------
光标的显示与隐藏 ------------------------
也许你想隐藏或者改变控制台里的光标 . 另一个 API SetConsoleCursorInfo() 可以实现这个功能 , . 该函数有两个参数 , 一个标准的输出句柄,还有一个 CONSOLE_CURSOR_INFO 结构体的指针 .
结构体的定义如下:
typedef struct _CONSOLE_CURSOR_INFO {
DWORD dwSize;
BOOL   bVisible;
} CONSOLE_CURSOR_INFO, *PCONSOLE_CURSOR_INFO;
第一个值是取值范围为 1-100 的整数 , 它描述了光标填充一个字符单元的百分比 .
另一个值是个 boolean 类型,他描述了光标是否可见 . true- 可见, false- 不可见
#include <windows.h>

int main()
{
HANDLE hOut;
CONSOLE_CURSOR_INFO ConCurInf;

hOut = GetStdHandle(STD_OUTPUT_HANDLE);

SetConsoleTitle("Size 50");

ConCurInf.dwSize = 50;//
示范使用的是 50
ConCurInf.bVisible = TRUE;

SetConsoleCursorInfo(hOut,
          &ConCurInf);

return 0;
}

#include <windows.h>

int main()
{
HANDLE hOut;
CONSOLE_CURSOR_INFO ConCurInf;

hOut = GetStdHandle(STD_OUTPUT_HANDLE);

SetConsoleTitle("No Cursor");

ConCurInf.dwSize = 10;
ConCurInf.bVisible = FALSE;

SetConsoleCursorInfo(hOut,
          &ConCurInf);

return 0;
}


//-----------------------------
文字的颜色与背景 ------------------------
函数 SetConsoleTextAttribute() 的作用是在 console 程序设置输入或输出文本的文本颜色和背景颜
. 只有在此函数设置后才能显示彩色的文本 . 其函数原型为 :

BOOL SetConsoleTextAttribute(
HANDLE hConsoleOutput, // console
屏幕缓冲区的句柄
WORD wAttributes //
文本及背景的颜色
);
如果函数设置文本及背景颜色成功 , 则返回非零 ; 如失败返回零 . 其参数含义如下 :
hConsoleOutput-------------console
屏幕缓冲区的句柄 .
WORD wAttributes-----------
文本及背景的颜色 .

其文本与背景颜色可以是
FOREGROUND_BLUE, FOREGROUND_GREEN, FOREGROUND_RED, FOREGROUND_INTENSITY,
BACKGROUND_BLUE, BACKGROUND_GREEN, BACKGROUND_RED, and BACKGROUND_INTENSITY.
#include<windows.h>
#include<iostream>
using namespace std;

void SetColor(unsigned short ForeColor=0,unsigned short BackGroundColor=0)
{
HANDLE hCon=GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hCon,ForeColor|BackGroundColor);
}

int main()
{
int FC,BC;
for(BC=0;BC<=1;BC++)
{
  for(FC=0;FC<=255;FC++)
  {
    SetColor(FC,BC);
    std::cout<<FC<<','<<BC<<'/t';
    SetColor(7,0);
    if(FC%16==15)std::cout<<endl;
  }
}

return 0;
}

完了
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值