分享
 
 
 

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

王朝other·作者佚名  2006-01-10
窄屏简体版  字體: |||超大  

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

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有