1.当我们的程序收到系统的WM_QUERYENDSESSION函数时,返回false,并且使用ShutdownBlockReasonCreate弹提示说明关机被打断的原因
2.向系统安装钩子处理控制台消息(初始化的时候)
3.过滤控制台消息,如果用户强制关机,发送WM_CLOSE给我们的程序
4.这时候我们调用ShutdownBlockReasonDestroy让关机继续进行
这是处理控制台的钩子函数
BOOL WINAPI
ConsoleCtrlHandler(DWORD dwCtrlType)
{
// 用户按下CTRL+BREAK, 或者由GenerateConsoleCtrlEvent API发出,当试图关闭控制台程序,系统发送关闭消息。
if (dwCtrlType == CTRL_C_EVENT ||
dwCtrlType == CTRL_BREAK_EVENT ||
dwCtrlType == CTRL_CLOSE_EVENT) {
SendMessage(hWnd, WM_CLOSE, 0, 0);
return TRUE;
}
return FALSE;
}
注册窗口类
void
register (HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)procWndMsg; //回调函数
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = L"TestClass";
wcex.hIconSm = NULL;
// 安装钩子处理控制台消息
SetConsoleCtrlHandler((PHANDLER_ROUTINE)ConsoleCtrlHandler, TRUE);
创建窗口类
BOOL creatWindow(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance;
RECT sz = {0, 0, 512, 512};
AdjustWindowRect(&sz, WS_OVERLAPPEDWINDOW, TRUE);
hWnd = CreateWindow(L"TestClass", L"Test Window", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, sz.right - sz.left, sz.bottom - sz.top,
NULL, NULL, hInstance, NULL);
if(!hWnd)
{
return FALSE;
}
}
处理信息回调函数
LRESULT CALLBACK procWndMsg(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
switch(message)
{
case WM_QUERYENDSESSION:
if (ncOSUtil::IsWinXPFamily ()){
static BOOL bFlag = FALSE;
if (bFlag) {
return TRUE;
}
//这里建议弹出个等待窗口来提示,因为XP没有还有进程未关闭那个界面
bFlag = TRUE;
return FALSE;
}
else {
return FALSE;
}
break;
case WM_CREATE:
if (!ncOSUtil::IsWinXPFamily ()) {
//这里使用函数指针来调用,否则在XP下,USER32里面没有这两个函数,会无法找到入口
//即使用if不进入这里也会报错,亲测
typedef BOOL (WINAPI* SHUTDOWNBLOCKREASONCREATE) (__in HWND hWnd, __in LPCWSTR pwszReason);
HMODULE hUser32Dll = GetModuleHandle (_T("User32"));
SHUTDOWNBLOCKREASONCREATE pShutdownBlockReasonCreate = (SHUTDOWNBLOCKREASONCREATE)GetProcAddress (hUser32Dll, "ShutdownBlockReasonCreate");
if (pShutdownBlockReasonCreate) {
pShutdownBlockReasonCreate (hwnd, L"程序正在运行,建议手动关闭后在关机或注销,以免引起数据丢失。"); //弹提示,阻止关机
}
}
break;
case WM_DESTROY:
if (!ncOSUtil::IsWinXPFamily ()) {
typedef BOOL (WINAPI* SHUTDOWNBLOCKREASONDESTROY) (__in HWND hWnd);
HMODULE hUser32Dll = GetModuleHandle (_T("User32"));
SHUTDOWNBLOCKREASONDESTROY pShutdownBlockReasonDestroy = (SHUTDOWNBLOCKREASONDESTROY)GetProcAddress (hUser32Dll, "ShutdownBlockReasonDestroy");
if (pShutdownBlockReasonDestroy) {
pShutdownBlockReasonDestroy (hwnd); //继续关机
}
PostQuitMessage (0); //退出消息循环
}
break;
default:
break;
}
return TRUE;
}
MSG msg;
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;