经常看到一些程序在运行的时候有一个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,那么你只要从该类继承即可,然后调用对应的方法。该类没有对输出进行格式化,所以使用起来有些不方便,过段时间处理一下。