此篇内容属C++控制台编程的一点基础应用,所以嘛,偶就偷个懒,不再做文字的讲解,直接代码。
哦,对了!代码之前,先就代码的组成作个简单说明。代码的内容共分为三块:
- 以宏RUN_ATEXIT_SAMPLE标识的atexit调用样例
- 以宏RUN_SETCONSOLECTRLHANDLER_SAMPLE标识的SetConsoleCtrlHandler调用样例
- 以宏RUN_READCONSOLEINPUT_SAMPLE标识的ReadConsoleInput调用样例
其中,第3段样例代码来自于MSDN:http://msdn.microsoft.com/en-us/library/ms685035(v=VS.85).aspx
OK,开始代码!!
#include <windows.h>
#include <iostream>
#include <string>
using namespace std;
#define RUN_ATEXIT_SAMPLE
#define RUN_SETCONSOLECTRLHANDLER_SAMPLE
#define RUN_READCONSOLEINPUT_SAMPLE
#define SECOND(n) (n * 1000)
// ATEXIT_SAMPLE
void Run_atexit_Sample(void);
// SETCONSOLECTRLHANDLER_SAMPLE
BOOL WINAPI ConsoleHandler(__in DWORD dwCtrlType);
// READCONSOLEINPUT_SAMPLE
HANDLE hStdin;
DWORD fdwSaveOldMode;
VOID ErrorExit(LPSTR);
VOID KeyEventProc(KEY_EVENT_RECORD);
VOID MouseEventProc(MOUSE_EVENT_RECORD);
VOID ResizeEventProc(WINDOW_BUFFER_SIZE_RECORD);
VOID Run_ReadConsoleInput_Sample(VOID);
int main(void)
{
#ifdef RUN_ATEXIT_SAMPLE
Run_atexit_Sample();
#endif
#ifdef RUN_SETCONSOLECTRLHANDLER_SAMPLE
cout << "[RUN_SETCONSOLECTRLHANDLER_SAMPLE] START" << endl;
cout << "\t (Note: You just have 15sec to do the operations.)" << endl;
// 【SetConsoleCtrlHandler(HandlerRoutine, Add)】:
// Add == TRUE: 处理HandlerRoutine 被添加
// 如果 HandlerRoutine == NULL,则忽略对 CTRL+C 输入处理
// Add == FALSE: 处理HandlerRoutine 被移除
// 如果 HandlerRoutine == NULL,则恢复对 CTRL+C 输入的处理
// 对 CTRL+C 输入处理的忽略与恢复,将被子进程所继承
if (SetConsoleCtrlHandler((PHANDLER_ROUTINE)ConsoleHandler, TRUE) == FALSE) {
DWORD dwErr = GetLastError();
cout << "[RUN_SETCONSOLECTRLHANDLER_SAMPLE] Failed to SetConsoleCtrlHandler! Err: " << dwErr << endl;
return (int)dwErr;
}
Sleep(SECOND(15));
cout << "[RUN_SETCONSOLECTRLHANDLER_SAMPLE] END" << endl;
#endif
#ifdef RUN_READCONSOLEINPUT_SAMPLE
cout << "[RUN_READCONSOLEINPUT_SAMPLE] Enter Run_ReadConsoleInput_Sample()" << endl;
Run_ReadConsoleInput_Sample();
cout << "[RUN_READCONSOLEINPUT_SAMPLE] Leave Run_ReadConsoleInput_Sample()" << endl;
#endif
system("pause");
return 0;
}
/**///////////////////////////////////////////////////////////////////////////
void ExitProc_1(void)
{
cout << "[RUN_ATEXIT_SAMPLE] This is ExitProc_1" << endl;
}
void ExitProc_2(void)
{
cout << "[RUN_ATEXIT_SAMPLE] This is ExitProc_2" << endl;
}
// 【注意】:
// 1. atexit() 成功时返回 0
// 2. atexit() 的参数类型为 void (__cdecl *func )( void )
// 3. atexit() 是将所传入的回调函数放入栈中,故回调函数的执行顺序与atexit的顺序相反
// 4. atexit() 只有当应用程序正常结束时,回调函数才能执行
// 5. atexit() 回调函数不能依赖于任何DLL,因为在回调函数执行时DLL可能已经被卸载
// 6. 类似函数:
// _onexit(_onexit_t) ==> int (__clrcall * _onexit_t)(void)
// _onexit_m(_onexit_t_m) ==> int (__clrcall * _onexit_m_t)(void)
// 其中,_onexit是微软的扩展;ANSI程序则应使用atexit;对于混合模式,则可使用_onexit_m版本
void Run_atexit_Sample(void)
{
cout << "[RUN_ATEXIT_SAMPLE] Enter Run_atexit_Sample()" << endl;
cout << "[RUN_ATEXIT_SAMPLE] Call atexit() first by ExitProc_1, then by ExitProc_2" << endl;
atexit(ExitProc_1);
atexit(ExitProc_2);
cout << "[RUN_ATEXIT_SAMPLE] Leave Run_atexit_Sample()" << endl;
}
/**///////////////////////////////////////////////////////////////////////////
// 如果事件得到了处理,则返回 TRUE
// 如果还需要将事件传递给下一个事件处理函数,则返回 FALSE
BOOL WINAPI ConsoleHandler( __in DWORD dwCtrlType )
{
switch (dwCtrlType) {
case CTRL_C_EVENT: // CTRL + C
// 亦可通过GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0)触发
cout << "\n[RUN_SETCONSOLECTRLHANDLER_SAMPLE] CTRL_C_EVENT" << endl;
break;
case CTRL_BREAK_EVENT: // CTRL + BREAK
// 亦可通过GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, 0)触发
cout << "\n[RUN_SETCONSOLECTRLHANDLER_SAMPLE] CTRL_BREAK_EVENT" << endl;
break;
case CTRL_CLOSE_EVENT: // 关闭控制台程序
cout << "\n[RUN_SETCONSOLECTRLHANDLER_SAMPLE] CTRL_CLOSE_EVENT" << endl;
break;
case CTRL_LOGOFF_EVENT: // 用户注销(退出登录)
cout << "\n[RUN_SETCONSOLECTRLHANDLER_SAMPLE] CTRL_LOGOFF_EVENT" << endl;
break;
case CTRL_SHUTDOWN_EVENT: // 关机
cout << "\n[RUN_SETCONSOLECTRLHANDLER_SAMPLE] CTRL_SHUTDOWN_EVENT" << endl;
break;
default:
cout << "\n[RUN_SETCONSOLECTRLHANDLER_SAMPLE] Unknown console ctrl event: " << dwCtrlType << endl;
break;
}
return TRUE;
}
/**///////////////////////////////////////////////////////////////////////////
VOID ErrorExit (LPSTR lpszMessage)
{
fprintf(stderr, "%s\n", lpszMessage);
// Restore input mode on exit.
SetConsoleMode(hStdin, fdwSaveOldMode);
ExitProcess(0);
}
VOID KeyEventProc(KEY_EVENT_RECORD ker)
{
printf("Key event: ");
if(ker.bKeyDown)
printf("key pressed\n");
else printf("key released\n");
}
VOID MouseEventProc(MOUSE_EVENT_RECORD mer)
{
#ifndef MOUSE_HWHEELED
#define MOUSE_HWHEELED 0x0008
#endif
printf("Mouse event: ");
switch(mer.dwEventFlags)
{
case 0:
if(mer.dwButtonState == FROM_LEFT_1ST_BUTTON_PRESSED)
{
printf("left button press \n");
}
else if(mer.dwButtonState == RIGHTMOST_BUTTON_PRESSED)
{
printf("right button press \n");
}
else
{
printf("button press\n");
}
break;
case DOUBLE_CLICK:
printf("double click\n");
break;
case MOUSE_HWHEELED:
printf("horizontal mouse wheel\n");
break;
case MOUSE_MOVED:
printf("mouse moved\n");
break;
case MOUSE_WHEELED:
printf("vertical mouse wheel\n");
break;
default:
printf("unknown\n");
break;
}
}
VOID ResizeEventProc(WINDOW_BUFFER_SIZE_RECORD wbsr)
{
printf("Resize event\n");
printf("Console screen buffer is %d columns by %d rows.\n", wbsr.dwSize.X, wbsr.dwSize.Y);
}
VOID Run_ReadConsoleInput_Sample( VOID )
{
DWORD cNumRead, fdwMode, i;
INPUT_RECORD irInBuf[128];
int counter=0;
// Get the standard input handle.
hStdin = GetStdHandle(STD_INPUT_HANDLE);
if (hStdin == INVALID_HANDLE_VALUE)
ErrorExit("GetStdHandle");
// Save the current input mode, to be restored on exit.
if (! GetConsoleMode(hStdin, &fdwSaveOldMode) )
ErrorExit("GetConsoleMode");
// Enable the window and mouse input events.
fdwMode = ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT;
if (! SetConsoleMode(hStdin, fdwMode) )
ErrorExit("SetConsoleMode");
// Loop to read and handle the next 100 input events.
while (counter++ <= 100)
{
// Wait for the events.
if (! ReadConsoleInput(
hStdin, // input buffer handle
irInBuf, // buffer to read into
128, // size of read buffer
&cNumRead) ) // number of records read
ErrorExit("ReadConsoleInput");
// Dispatch the events to the appropriate handler.
for (i = 0; i < cNumRead; i++)
{
switch(irInBuf[i].EventType)
{
case KEY_EVENT: // keyboard input
KeyEventProc(irInBuf[i].Event.KeyEvent);
break;
case MOUSE_EVENT: // mouse input
MouseEventProc(irInBuf[i].Event.MouseEvent);
break;
case WINDOW_BUFFER_SIZE_EVENT: // scrn buf. resizing
ResizeEventProc( irInBuf[i].Event.WindowBufferSizeEvent );
break;
case FOCUS_EVENT: // disregard focus events
case MENU_EVENT: // disregard menu events
break;
default:
ErrorExit("Unknown event type");
break;
}
}
}
// Restore input mode on exit.
SetConsoleMode(hStdin, fdwSaveOldMode);
}
最后,本人还是博客新人,有什么好的意见或建议,还望各位能大力提点!!