SetConsoleCtrlHandler 處理控制臺消息
一、如何處理所有的控制臺消息。
第一步,首先要安裝一個事件鉤子,也就是說要建立一個回調函數。調用Win32 API,原型如下:
BOOL SetConsoleCtrlHandler(
PHANDLER_ROUTINE HandlerRoutine, // 回調函數
BOOL Add // 表示添加還是刪除
);
參數HandlerRoutine是一個指向函數的指針,原型如下:
BOOL WINAPI HandlerRoutine(
DWORD dwCtrlType // 控制事件類型
);
所有的HandlerRoutine函數只有一個參數dwCtrlType,他表示控制臺發出了什么消息。參數有下列值:
CTRL_C_EVENT - 當用戶按下了CTRL+C,或者由GenerateConsoleCtrlEvent API發出.
CTRL_BREAK_EVENT - 用戶按下CTRL+BREAK, 或者由GenerateConsoleCtrlEvent API發出.
CTRL_CLOSE_EVENT - 當試圖關閉控制臺程序,系統發送關閉消息。
CTRL_LOGOFF_EVENT - 用戶退出時,但是不能決定是哪個用戶.
CTRL_SHUTDOWN_EVENT - 當系統被關閉時.
當收到事件的時候,HandlerRoutine可以選擇處理,或者簡單的忽略。如果回調函數選擇忽略,函數返回FALSE,系統將處理下一個鉤子程序。如果處理消息,程序在處理完消息后應該返回TRUE。
CTRL_CLOSE_EVENT,
CTRL_LOGOFF_EVENT和CTRL_SHUTDOWN_EVENT通常被用來處理一些程序的清理工作,然后調用ExitProcess
API。另外,這三個事件有超時機制,CTRL_CLOSE_EVENT是5秒,另外兩個是20秒。如果程序超時候,系統將會彈出結束進程的對話框。如果用戶選擇了結束進程,任何清理工作都不會做,所以應該在超時時間內完成工作。下面是一個回調函數的例子:
BOOL WINAPI ConsoleHandler(DWORD CEvent)
{
char mesg[128];
switch(CEvent)
{
case CTRL_C_EVENT:
MessageBox(NULL,
"CTRL+C received!","CEvent",MB_OK);
break;
case CTRL_BREAK_EVENT:
MessageBox(NULL,
"CTRL+BREAK received!","CEvent",MB_OK);
break;
case CTRL_CLOSE_EVENT:
MessageBox(NULL,
"Program being closed!","CEvent",MB_OK);
break;
case CTRL_LOGOFF_EVENT:
MessageBox(NULL,
"User is logging off!","CEvent",MB_OK);
break;
case CTRL_SHUTDOWN_EVENT:
MessageBox(NULL,
"User is logging off!","CEvent",MB_OK);
break;
}
return TRUE;
}
好,現在已經有了回調函數,再來看看怎么安裝鉤子:
if (SetConsoleCtrlHandler(
(PHANDLER_ROUTINE)ConsoleHandler,TRUE)==FALSE)
{
// unable to install handler...
// display message to the user
printf("Unable to install handler!\n");
return -1;
}
第一個參數是函數指針,就是上面的那個函數。第二個參數是標志,如果為TRUE那么就安裝鉤子,如果為FALSE那么刪除鉤子。
好了,在安裝了鉤子后,我們就能收到控制臺消息了,在程序退出前,要刪除鉤子。很簡單吧。