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

经常看到一些程序在运行的时候有一个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

  1<windows.h>   
  2#include <tchar.h>   
  3class CConsoleOutInfo   
  4{   
  5public:   
  6int m_cursorX;   
  7int m_cursorY;   
  8int m_cursorStartLine;   
  9int m_cursorVisible;   
 10LPBYTE m_consoleBuffer;   
 11}; 
 12
 13class CConsoleMgr   
 14{   
 15public:   
 16CConsoleMgr(void);   
 17virtual ~CConsoleMgr(void); 
 18
 19BOOL CreateConsole(TCHAR * tstrName,BOOL bFullDosMode=FALSE);   
 20BOOL OutputToConsole(CConsoleOutInfo &amp;outInfo);   
 21BOOL CloseConsole(); 
 22
 23BOOL ThreadIsStart(){return m_hConsoleThread&amp;&amp;m_idConsoleThread;} 
 24
 25virtual DWORD ProcessConsoleInput(INPUT_RECORD* pInputRec,DWORD dwInputs) =0;   
 26protected:   
 27void SetConsoleBufferSize(SMALL_RECT &amp;writeRegion,   
 28COORD &amp;bufferSize,   
 29COORD &amp;bufferCoord); 
 30
 31void ResetThreadInfo();   
 32private:   
 33HANDLE m_hConsoleThread;   
 34DWORD m_idConsoleThread;   
 35};   
 36
 37
 38//cpp文件 
 39
 40#include "StdAfx.h"   
 41#include ".\consolemgr.h" 
 42
 43#define MAX_SHADOW_CONSOLE_INPUT_BUFFER 50 
 44
 45DWORD WINAPI ConsoleInputMonitor(LPVOID lParam);   
 46BOOL WINAPI MyHandlerRoutine(DWORD dwCtrlType); 
 47
 48CConsoleMgr::CConsoleMgr(void)   
 49{   
 50ResetThreadInfo();   
 51} 
 52
 53void CConsoleMgr::ResetThreadInfo()   
 54{   
 55m_hConsoleThread = 0;   
 56m_idConsoleThread = 0;   
 57} 
 58
 59CConsoleMgr::~CConsoleMgr(void)   
 60{   
 61if(m_hConsoleThread&amp;&amp;m_idConsoleThread)   
 62CloseConsole();   
 63} 
 64
 65BOOL CConsoleMgr::CreateConsole(TCHAR * tstrName,BOOL bFullDosMode)   
 66{   
 67m_hConsoleThread = CreateThread(NULL, 0, ConsoleInputMonitor,   
 68this, CREATE_SUSPENDED, &amp;m_idConsoleThread); 
 69
 70if (m_hConsoleThread)   
 71{   
 72SetThreadPriority(m_hConsoleThread, THREAD_PRIORITY_ABOVE_NORMAL); 
 73
 74if(AllocConsole())   
 75{   
 76SetConsoleTitle(tstrName);   
 77SetConsoleCtrlHandler((PHANDLER_ROUTINE)MyHandlerRoutine,TRUE);   
 78if(bFullDosMode)   
 79{   
 80SetConsoleTitle("Sharing Full Screen DOS");   
 81keybd_event(VK_MENU, (BYTE)MapVirtualKey(VK_MENU, 0),   
 820, GetMessageExtraInfo());   
 83// Simulate ENTER is pressed,   
 84keybd_event(VK_RETURN, (BYTE)MapVirtualKey(VK_RETURN, 0),   
 850, GetMessageExtraInfo());   
 86// Simulate ENTER is released,   
 87keybd_event(VK_RETURN, (BYTE)MapVirtualKey(VK_RETURN, 0),   
 88KEYEVENTF_KEYUP, GetMessageExtraInfo());   
 89// Simulate ALT is released,   
 90keybd_event(VK_MENU, (BYTE)MapVirtualKey(VK_MENU, 0),   
 91KEYEVENTF_KEYUP, GetMessageExtraInfo());   
 92} 
 93
 94SetThreadPriority(m_hConsoleThread, THREAD_PRIORITY_NORMAL);   
 95ResumeThread(m_hConsoleThread);   
 96}   
 97return TRUE;   
 98}   
 99return FALSE;   
100} 
101
102void CConsoleMgr::SetConsoleBufferSize( SMALL_RECT &amp;writeRegion,   
103COORD &amp;bufferSize,   
104COORD &amp;bufferCoord)   
105{   
106bufferSize.X = 80;   
107bufferSize.Y = 25;   
108bufferCoord.X = 0;   
109bufferCoord.Y = 0;   
110writeRegion.Top = 0;   
111writeRegion.Left = 0;   
112writeRegion.Bottom = 24;   
113writeRegion.Right = 79;   
114} 
115
116BOOL CConsoleMgr::OutputToConsole(CConsoleOutInfo &amp;outInfo)   
117{   
118HANDLE hConsoleOutput;   
119COORD CursorPosition;   
120COORD bufferSize;   
121COORD bufferCoord;   
122SMALL_RECT writeRegion;   
123CHAR_INFO buffer[25*80];   
124CONSOLE_CURSOR_INFO ConsoleCursorInfo; 
125
126CursorPosition.X = (SHORT)outInfo.m_cursorX;   
127CursorPosition.Y = (SHORT)outInfo.m_cursorY;   
128if( outInfo.m_cursorStartLine == 0 )   
129ConsoleCursorInfo.dwSize = 14; //Default size   
130else   
131ConsoleCursorInfo.dwSize = (DWORD)(0x10-outInfo.m_cursorStartLine)*100/0x10; 
132
133ConsoleCursorInfo.bVisible = (BOOL)outInfo.m_cursorVisible; 
134
135// Convert the raw data to console screen buffer format.   
136for(int i=0; i&lt;25*80; i++)   
137{   
138buffer[i].Char.AsciiChar = outInfo.m_consoleBuffer[i*2];   
139buffer[i].Attributes = outInfo.m_consoleBuffer[i*2+1];   
140} 
141
142SetConsoleBufferSize(writeRegion,bufferSize,bufferCoord); 
143
144// Write texts to screen.   
145hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE);   
146WriteConsoleOutput(hConsoleOutput, buffer, bufferSize,   
147bufferCoord, &amp;writeRegion); 
148
149// Set cursor information.   
150SetConsoleCursorInfo(hConsoleOutput, &amp;ConsoleCursorInfo); 
151
152// Set cursor position.   
153SetConsoleCursorPosition(hConsoleOutput, CursorPosition);   
154return FALSE;   
155} 
156
157BOOL CConsoleMgr::CloseConsole()   
158{   
159DWORD dwEventNum;   
160INPUT_RECORD Input_Record; 
161
162Input_Record.EventType = MOUSE_EVENT;   
163Input_Record.Event.MouseEvent.dwMousePosition.X = 0;   
164Input_Record.Event.MouseEvent.dwMousePosition.Y = 0;   
165Input_Record.Event.MouseEvent.dwButtonState = 0;   
166Input_Record.Event.MouseEvent.dwControlKeyState = 0;   
167Input_Record.Event.MouseEvent.dwEventFlags = MOUSE_MOVED; 
168
169WriteConsoleInput(GetStdHandle(STD_INPUT_HANDLE), &amp;Input_Record, 1, &amp;dwEventNum); 
170
171SetConsoleCtrlHandler((PHANDLER_ROUTINE)MyHandlerRoutine,FALSE); 
172
173//Waiting for the thread termination.   
174if( WaitForSingleObject(m_hConsoleThread, 10000) == WAIT_TIMEOUT )   
175{   
176TerminateThread(m_hConsoleThread, 0);   
177}   
178CloseHandle(m_hConsoleThread); 
179
180FreeConsole();   
181ResetThreadInfo(); 
182
183return FALSE;   
184} 
185
186DWORD WINAPI ConsoleInputMonitor(LPVOID lParam)   
187{   
188CConsoleMgr *pConsoleMgr = (CConsoleMgr *)lParam;   
189if(pConsoleMgr == NULL) return -1; 
190
191HANDLE hConsoleInput;   
192DWORD dwInputs;   
193INPUT_RECORD Input_Record[MAX_SHADOW_CONSOLE_INPUT_BUFFER]; 
194
195hConsoleInput = GetStdHandle(STD_INPUT_HANDLE); 
196
197FlushConsoleInputBuffer(hConsoleInput); 
198
199while( pConsoleMgr-&gt;ThreadIsStart() )   
200{   
201hConsoleInput = GetStdHandle(STD_INPUT_HANDLE); 
202
203// If there are input events in buffer, this object is signaled   
204WaitForSingleObject(hConsoleInput, INFINITE); 
205
206GetNumberOfConsoleInputEvents(hConsoleInput, &amp;dwInputs); 
207
208ReadConsoleInput(hConsoleInput, Input_Record,   
209min(dwInputs,MAX_SHADOW_CONSOLE_INPUT_BUFFER),   
210&amp;dwInputs); 
211
212pConsoleMgr-&gt;ProcessConsoleInput(Input_Record,0);   
213} 
214
215return 0;   
216} 
217
218BOOL WINAPI MyHandlerRoutine(DWORD dwCtrlType)   
219{   
220return TRUE;   
221} 
222
223如果你想为你的程序创建一个CONSOLE,那么你只要从该类继承即可,然后调用对应的方法。该类没有对输出进行格式化,所以使用起来有些不方便,过段时间处理一下。</tchar.h></windows.h>
Published At
Categories with Web编程
Tagged with
comments powered by Disqus