让你的控制台程序也支持自动补齐

nanhongni

nanhongni

2016-02-19 13:58

今天天气好晴朗处处好风光,好天气好开始,图老师又来和大家分享啦。下面给大家推荐让你的控制台程序也支持自动补齐,希望大家看完后也有个好心情,快快行动吧!

 对Windows 2000, Windows XP, Windows Server 2003操作系统下的“命令提示符程序 (cmd.exe)”了解稍多的人都会知道“命令提示符”有几个很好用的功能。一、支持命令历史记录,可以用上下键来切换以前输入的命令;二、支持快捷键功能(F1~F9)[具体每个键的功能请读者自己试吧];三、支持目录/文件名的自动补齐,这样可以快速输入目录/文件名。

  这些功能对于用户来讲是非常友好的,可以让用户更方便的输入和编辑命令。我也相信任何一个写控制台程序的人都希望在自己的程序当中能够实现这样的功能。

  那么如何让自己的程序有如上的功能呢?

  对于上面提到前两个功能,操作系统本身已经提供了,你只需要简单的调用ReadConsole这个API就可以了。这个API会跟据你输入时的按键来执行这些功能。
 
  对于第三个功能,MSDN中未曾提及,ReadConsole API的说明中任何一点都和此功能无关。实际上自动补齐功能要用到ReadConsole的一个公开的功能,而且只有Unicode版本的ReadConsoleW提供了该功能,ANSI版本的ReadConsoleA并不支持。

  我们先看看ReadConsole这个API的原型(from MSDN)

  BOOL ReadConsole(

  HANDLE hConsoleInput, // handle to console input buffer

  LPVOID lpBuffer, // data buffer

  DWORD nNumberOfCharsToRead, // number of characters to read

  LPDWORD lpNumberOfCharsRead, // number of characters read

(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/bianchengyuyan/)

  LPVOID lpReserved // reserved

  );

  在MSDN中提到参数lpReserved这个参数必须为NULL值,当然MSDN中是这么提的,但对于ReadConsoleW来讲就不是了,因为自动补齐这个功能要靠ReadConsoleW的lpReserved参数了。

  该参数不为NULL时,可以指向一个如下的结构体

  struct read_console_param

  {

  DWORD cbSize;

  DWORD dwInitLen;

  DWORD dwWakeMask;

  DWORD dwUnknown;
  };

  其中每个成员变量的意义如下

  cbSize - 该结构体的长度,16字节

  dwInitLen – 指出lpBuffer中已有字符的数目,这样ReadConsole在等待用户输入时,也会把lpBuffer中已有的内容算进去。

  dwWakeMask – 指出ReadConsole在接收到哪些Ctrl序列后返回,其中bit0对应^@, bit1对应^A, bit2对应^B,bit3对应^C,以此类推。当用户输入时,输入了dwWakeMask中指定的任何一个Ctrl按键,ReadConsole将返回。

  dwUnknown具体什么意义暂不清楚,最初设为0即可

  了解了ReadConsoleW的这个新功能后(其实该功能早就有了,只不过很多人不知道),那么就可以很容易地实现自动补齐了。

  以下是我给的一个简单例子:

  #include

  #include

  #include

  #include

  #include

  #define Ctrl(x) ((x) & 0x37)

  struct read_console_param

  {

  DWORD nLength;

  DWORD dwInitLen;

  DWORD dwWakeMask;

  DWORD dwUnknown;

  };

  int main (void)

  {

  HANDLE hInput, hOutput;

  WCHAR buf [0x100];

  read_console_param param;

  setlocale (LC_ALL, ".ACP");

  memset (¶m, 0, sizeof (param));

  param.nLength = sizeof (param);

  hInput = GetStdHandle (STD_INPUT_HANDLE);
  hOutput = GetStdHandle (STD_OUTPUT_HANDLE);

  buf [0] = 0;
 
  while (wcscmp (buf, L"quit") != 0)

  {
 
  DWORD read, written;

  printf ("$");

  param.dwInitLen = 0;

  param.dwUnknown = 0;

  // 我们使用^F和^D来进行自动补齐

  param.dwWakeMask = (1 Ctrl ('F'))

  | (1 Ctrl ('D'));

  again:

  if (ReadConsoleW (hInput, buf, 0x100, &read, ¶m))

  {

  if (buf [read-1] == Ctrl ('F'))

  { // 用户按下了^F键, 自动补齐字符串"fff",

(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/bianchengyuyan/)

  // 然后继续等待输入

  wcscpy (buf+read-1, L"fff");

  WriteConsoleW (hOutput, L"fff", 3,

  &written, NULL);

  param.dwInitLen = read - 1 + 3;

  goto again;

  }

  else if (buf [read-1] == Ctrl ('D'))

  { // 用户按下了^D键, 自动补齐字符串"ddd",

  // 然后继续等待输入

  wcscpy (buf+read-1, L"ddd");

  WriteConsoleW (hOutput, L"ddd", 3,

&written, NULL);

  param.dwInitLen = read-1+3;

  goto again;

  };

  // 去掉回车换行
 
  if (buf [read-1] == '')

  --read;

  if (buf [read-1] == '')

  --read;

  buf [read] = 0;

  printf ("you inputed: [%S]", buf);

  }

  else

  {

  printf ("ReadConsole failed with error %d",

  GetLastError ());

  break;

  };

  };

  };

  这个例子是个最简单的例子,目前只支持在输入字符串的末尾进行自动补齐,无法在输入字符串的中间进行自动补齐;如果要写出cmd.exe那样的效果,还需要加很多的代码。

  最后祝所有的程序员都能在Windows下写出支持自动补齐的控制台程序!

展开更多 50%)
分享

猜你喜欢

让你的控制台程序也支持自动补齐

编程语言 网络编程
让你的控制台程序也支持自动补齐

Windows中控制台程序的全屏模式开关

编程语言 网络编程
Windows中控制台程序的全屏模式开关

s8lol主宰符文怎么配

英雄联盟 网络游戏
s8lol主宰符文怎么配

mysql 控制台操作

编程语言 网络编程
mysql 控制台操作

让故障恢复控制台入驻硬盘

windows 操作系统
让故障恢复控制台入驻硬盘

lol偷钱流符文搭配推荐

英雄联盟 网络游戏
lol偷钱流符文搭配推荐

《辐射3》控制台秘籍

电脑网络
《辐射3》控制台秘籍

《辐射3》控制台-技能代码

电脑网络
《辐射3》控制台-技能代码

lolAD刺客新符文搭配推荐

英雄联盟
lolAD刺客新符文搭配推荐

密码强度检测函数(正则)

密码强度检测函数(正则)

那一刻我快要窒息 - QQ伤感分组

那一刻我快要窒息 - QQ伤感分组
下拉加载更多内容 ↓