书山有路勤为径,学海无涯苦作舟

书山有路勤为径,学海无涯苦作舟!--windxucy@msn.com

原创 为你的程序创建一个控制台收藏

经常看到一些程序在运行的时候有一个WINDOWS控制台,感觉非常COOL。实际上有的时候帮助你监视系统运行是很方便的,那么怎么样创建一个控制台呢?

实际上WINDOWS为你提供了一系列的API来完成这个功能,例如:ReadConsole,WriteConsole等,具体参见MSDN。

下面我们用一段代码来说明如何创建Console.

1。首先调用AllocConsole函数来为你进程创建一个Console,该API是将当前进程Attache到一个新创建的Console上。你还可以通过调用SetConsoleTitle(tstrName);来设置Console的Title.

2。使用WriteConsoleOutput来将信息输出到Console上;在输出之前,先要得到Console的HANDLE,这通过GetStdHandle(STD_OUTPUT_HANDLE)来得到,然后将信息组织成Console的格式,然后输出。

3。关闭CONSOLE。当不需要这个CONSOLE的时候,调用FreeConsole来将当前进程从Console中Detach中。

4。通过创建一个进程来为监视你的CONSOLE输入和输出;你可以创建一个线程然后来,在线程中取得标准输入和输出CONSOLE的HANDLE,然后循环监视其事件,再对不同的事件进行处理。

下面是我写的一个实现以上功能的接口类:

//头文件

#pragma once

#include <Windows.h>
#include <tchar.h>
class CConsoleOutInfo
{
public:
 int   m_cursorX;
 int   m_cursorY;
 int   m_cursorStartLine;
 int   m_cursorVisible;
 LPBYTE  m_consoleBuffer;
};

class CConsoleMgr
{
public:
 CConsoleMgr(void);
 virtual ~CConsoleMgr(void);

 BOOL CreateConsole(TCHAR * tstrName,BOOL bFullDosMode=FALSE);
 BOOL OutputToConsole(CConsoleOutInfo &outInfo);
 BOOL CloseConsole();

 BOOL ThreadIsStart(){return m_hConsoleThread&&m_idConsoleThread;}

 virtual DWORD ProcessConsoleInput(INPUT_RECORD* pInputRec,DWORD dwInputs) =0;
protected:
 void SetConsoleBufferSize(SMALL_RECT &writeRegion,
        COORD &bufferSize,
        COORD &bufferCoord);

 void ResetThreadInfo();
private:
 HANDLE m_hConsoleThread;
 DWORD m_idConsoleThread;
};

//cpp文件

#include "StdAfx.h"
#include ".\consolemgr.h"

#define MAX_SHADOW_CONSOLE_INPUT_BUFFER  50

DWORD WINAPI ConsoleInputMonitor(LPVOID lParam);
BOOL WINAPI MyHandlerRoutine(DWORD  dwCtrlType);

CConsoleMgr::CConsoleMgr(void)
{
 ResetThreadInfo();
}

void CConsoleMgr::ResetThreadInfo()
{
 m_hConsoleThread = 0;
 m_idConsoleThread = 0;
}

CConsoleMgr::~CConsoleMgr(void)
{
 if(m_hConsoleThread&&m_idConsoleThread)
  CloseConsole();
}

BOOL CConsoleMgr::CreateConsole(TCHAR * tstrName,BOOL bFullDosMode)
{
 m_hConsoleThread = CreateThread(NULL, 0, ConsoleInputMonitor,
  this, CREATE_SUSPENDED, &m_idConsoleThread);

 if (m_hConsoleThread)
 {
  SetThreadPriority(m_hConsoleThread, THREAD_PRIORITY_ABOVE_NORMAL);

  if(AllocConsole())
  {   
   SetConsoleTitle(tstrName);
   SetConsoleCtrlHandler((PHANDLER_ROUTINE)MyHandlerRoutine,TRUE);
   if(bFullDosMode)
   {
    SetConsoleTitle("Sharing Full Screen DOS");
    keybd_event(VK_MENU, (BYTE)MapVirtualKey(VK_MENU, 0),
     0, GetMessageExtraInfo());
    // Simulate ENTER is pressed,
    keybd_event(VK_RETURN, (BYTE)MapVirtualKey(VK_RETURN, 0),
     0, GetMessageExtraInfo());
    // Simulate ENTER is released,
    keybd_event(VK_RETURN, (BYTE)MapVirtualKey(VK_RETURN, 0),
     KEYEVENTF_KEYUP, GetMessageExtraInfo());
    // Simulate ALT is released,
    keybd_event(VK_MENU, (BYTE)MapVirtualKey(VK_MENU, 0),
     KEYEVENTF_KEYUP, GetMessageExtraInfo());
   }

   SetThreadPriority(m_hConsoleThread, THREAD_PRIORITY_NORMAL);
   ResumeThread(m_hConsoleThread);
  }
  return TRUE;
 }
 return FALSE;
}

void CConsoleMgr::SetConsoleBufferSize( SMALL_RECT &writeRegion,
           COORD &bufferSize,
           COORD &bufferCoord)
{
 bufferSize.X  = 80;
 bufferSize.Y  = 25;
 bufferCoord.X = 0;
 bufferCoord.Y = 0;
 writeRegion.Top = 0; 
 writeRegion.Left = 0;
 writeRegion.Bottom = 24;
 writeRegion.Right = 79;
}

BOOL CConsoleMgr::OutputToConsole(CConsoleOutInfo &outInfo)
{
 HANDLE    hConsoleOutput;
 COORD    CursorPosition;
 COORD    bufferSize;
 COORD    bufferCoord;
 SMALL_RECT   writeRegion;
 CHAR_INFO   buffer[25*80];
 CONSOLE_CURSOR_INFO ConsoleCursorInfo;

 CursorPosition.X = (SHORT)outInfo.m_cursorX;
 CursorPosition.Y = (SHORT)outInfo.m_cursorY;
 if( outInfo.m_cursorStartLine == 0 )
  ConsoleCursorInfo.dwSize = 14; //Default size
 else
  ConsoleCursorInfo.dwSize = (DWORD)(0x10-outInfo.m_cursorStartLine)*100/0x10;

 ConsoleCursorInfo.bVisible = (BOOL)outInfo.m_cursorVisible;

 // Convert the raw data to console screen buffer format.
 for(int i=0; i<25*80; i++)
 {
  buffer[i].Char.AsciiChar = outInfo.m_consoleBuffer[i*2];
  buffer[i].Attributes  = outInfo.m_consoleBuffer[i*2+1];
 }

 SetConsoleBufferSize(writeRegion,bufferSize,bufferCoord);

 // Write texts to screen.
 hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE);
 WriteConsoleOutput(hConsoleOutput, buffer, bufferSize,
  bufferCoord, &writeRegion);

 // Set cursor information.
 SetConsoleCursorInfo(hConsoleOutput, &ConsoleCursorInfo);

 // Set cursor position.
 SetConsoleCursorPosition(hConsoleOutput, CursorPosition);
 return FALSE;
}

BOOL CConsoleMgr::CloseConsole()
{
 DWORD   dwEventNum;
 INPUT_RECORD Input_Record;

 Input_Record.EventType = MOUSE_EVENT;
 Input_Record.Event.MouseEvent.dwMousePosition.X = 0;
 Input_Record.Event.MouseEvent.dwMousePosition.Y = 0;
 Input_Record.Event.MouseEvent.dwButtonState  = 0;
 Input_Record.Event.MouseEvent.dwControlKeyState = 0;
 Input_Record.Event.MouseEvent.dwEventFlags  = MOUSE_MOVED;

 WriteConsoleInput(GetStdHandle(STD_INPUT_HANDLE), &Input_Record, 1, &dwEventNum);

 SetConsoleCtrlHandler((PHANDLER_ROUTINE)MyHandlerRoutine,FALSE);

 //Waiting for the thread termination.
 if( WaitForSingleObject(m_hConsoleThread, 10000) == WAIT_TIMEOUT )
 {
  TerminateThread(m_hConsoleThread, 0);
 }
 CloseHandle(m_hConsoleThread);

 FreeConsole();
 ResetThreadInfo();

 return FALSE;
}

DWORD WINAPI ConsoleInputMonitor(LPVOID lParam)

 CConsoleMgr *pConsoleMgr = (CConsoleMgr *)lParam;
 if(pConsoleMgr == NULL) return -1;

 HANDLE   hConsoleInput;
 DWORD   dwInputs;
 INPUT_RECORD Input_Record[MAX_SHADOW_CONSOLE_INPUT_BUFFER];

 hConsoleInput = GetStdHandle(STD_INPUT_HANDLE);

 FlushConsoleInputBuffer(hConsoleInput);

 while( pConsoleMgr->ThreadIsStart() )
 {
  hConsoleInput = GetStdHandle(STD_INPUT_HANDLE);

  // If there are input events in buffer, this object is signaled
  WaitForSingleObject(hConsoleInput, INFINITE);

  GetNumberOfConsoleInputEvents(hConsoleInput, &dwInputs);

  ReadConsoleInput(hConsoleInput, Input_Record,
   min(dwInputs,MAX_SHADOW_CONSOLE_INPUT_BUFFER),
   &dwInputs);

  pConsoleMgr->ProcessConsoleInput(Input_Record,0);
 }

 return 0;
}

BOOL WINAPI MyHandlerRoutine(DWORD  dwCtrlType)
{
 return TRUE;
}

如果你想为你的程序创建一个CONSOLE,那么你只要从该类继承即可,然后调用对应的方法。该类没有对输出进行格式化,所以使用起来有些不方便,过段时间处理一下。

发表于 @ 2005年11月27日 15:47:00|评论(loading...)

新一篇: Jasper-JPEG2000的实现(1) | 旧一篇: TIFF图像文件分析

用户操作
[即时聊天] [发私信] [加为好友]
笨笨
订阅我的博客
XML聚合  FeedSky
订阅到鲜果
订阅到Google
订阅到抓虾
笨笨的公告
文章分类
收藏
    图形编程
    OpenGL API查询
    另一个OPENGL AIP查询连接
    网络
    P2P编程相关文章
    中国IT实验室
    中国协议分析网
    相关链接
    beginstar的链接
    DOTNET论坛
    sourceforge.net
    什么是AJAX
    大宝(sodme)的专栏
    我另一个BLOG
    游戏开发
    存档
    软件项目交易
    Csdn Blog version 3.1a
    Copyright © 笨笨