测试环境:VC++ 6.0
作者:hi.baidu.com/console_app(文章有改动)
批注:未完美解决问题,实现部分功能
批处理在运行的期间可以通过Ctrl+C或者点击窗体右上角的关闭按钮中止运行。如果想要在关闭之前做进一步操作,则需要截取用户点击关闭按钮的消息。
截取Ctrl+C消息可以通过API函数SetConsoleCtrlHandler,但是不能截取点击窗体关闭按钮的消息。由于控制台窗口并不是进程拥有,因此也不能进行SetWindowLong子类化。
解决方法是,进行鼠标钩子。使用SetWindowsHookEx进行低级鼠标钩子,当受到WM_LBUTTONDOWN消息的时候,向控制台窗口发送WM_NCHITTEST测试点击部位是否是关闭按钮。若是,则吞掉此消息并进行处理。
源程序如下:
typedef HWND (WINAPI *PROCGETCONSOLEWINDOW)();
PROCGETCONSOLEWINDOW GetConsoleWindow;
HHOOK hHook;
DWORD HookProc(int nCode,WPARAM wParam,LPARAM lParam)
{
if(nCode>=0&&wParam==WM_LBUTTONDOWN)
{
DWORD pt[2];
memcpy(&pt[0],(void*)lParam,8);
if(SendMessage(GetConsoleWindow(),WM_NCHITTEST,0,(LPARAM)pt[0]+0x10000*pt[1])==HTCLOSE)
{
PostThreadMessage(GetCurrentThreadId(),WM_USER+1,0,0);
return 1;
}
}
return CallNextHookEx(hHook,nCode,wParam,lParam);
}
int main(int argc, char* argv[])
{
HMODULE hKernel32=GetModuleHandle("kernel32");
GetConsoleWindow=(PROCGETCONSOLEWINDOW)GetProcAddress(hKernel32,"GetConsoleWindow");
hHook=SetWindowsHookEx(14,(HOOKPROC)HookProc,NULL,NULL);
MSG msg;
while(GetMessage(&msg,NULL,0,0))
{
if(msg.message==WM_USER+1)
{
if(MessageBox(NULL,"QUIT?","Console",MB_YESNO)==IDYES) SendMessage(GetConsoleWindow(),WM_CLOSE,NULL,NULL);
}
}
UnhookWindowsHookEx(hHook);
return 0;
}
以上代码实现了在点击关闭按钮的时候,弹出对话框询问是否关闭,点是则关闭,否则保留。
期待其他方法及思路。
范例下载地址:
(注意:第一次运行该程序加载可能有些慢)