经常看到一些程序在运行的时候有一个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 &outInfo);
21BOOL CloseConsole();
22
23BOOL ThreadIsStart(){return m_hConsoleThread&&m_idConsoleThread;}
24
25virtual DWORD ProcessConsoleInput(INPUT_RECORD* pInputRec,DWORD dwInputs) =0;
26protected:
27void SetConsoleBufferSize(SMALL_RECT &writeRegion,
28COORD &bufferSize,
29COORD &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&&m_idConsoleThread)
62CloseConsole();
63}
64
65BOOL CConsoleMgr::CreateConsole(TCHAR * tstrName,BOOL bFullDosMode)
66{
67m_hConsoleThread = CreateThread(NULL, 0, ConsoleInputMonitor,
68this, CREATE_SUSPENDED, &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 &writeRegion,
103COORD &bufferSize,
104COORD &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 &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<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, &writeRegion);
148
149// Set cursor information.
150SetConsoleCursorInfo(hConsoleOutput, &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), &Input_Record, 1, &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->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, &dwInputs);
207
208ReadConsoleInput(hConsoleInput, Input_Record,
209min(dwInputs,MAX_SHADOW_CONSOLE_INPUT_BUFFER),
210&dwInputs);
211
212pConsoleMgr->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>