任何人都可以提供ShutdownBlockReasonCreate
的简单明确示例吗?我一直试图通过MSDN页面弄清楚它,但我不理解它,而且我已经厌倦了每次尝试测试它时都不能关闭我的电脑而且它不起作用。如果有人熟悉并且可以提供一个非常棒的简洁示例!
这是我到目前为止所做的,但我确实
#include <Windows.h>
#include <iostream>
std::wstring s2ws(const std::string& s)
{
int len;
int slength = (int)s.length() + 1;
len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0);
wchar_t* buf = new wchar_t[len];
MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len);
std::wstring r(buf);
delete[] buf;
return r;
}
int main(int argc, char* argv[])
{
if (ShutdownBlockReasonCreate(GetForegroundWindow(), s2ws("TEST").c_str()) != 0)
std::cout << "Success" << std::endl;
else
std::cout << "Failure" << std::endl;
while (1)
{
Sleep(1000);
std::cout << "Testing..." << std::endl;
}
}
答案 0 :(得分:8)
这适用于Windows 7.如果您愿意,也可以在控制台程序中执行此操作,这是一个更简单的编写示例。你应该添加错误检查,我没有把它简短。
#include <SDKDDKVer.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
HINSTANCE hInst;
HWND hWnd;
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
switch(message)
{
case WM_QUERYENDSESSION:
return FALSE;
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
break;
case WM_CREATE:
ShutdownBlockReasonCreate(hWnd, L"Don't do it!");
break;
case WM_DESTROY:
ShutdownBlockReasonDestroy(hWnd);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
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;
return RegisterClassEx(&wcex);
}
BOOL InitInstance(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;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
MyRegisterClass(hInstance);
if(!InitInstance(hInstance, nCmdShow))
{
return FALSE;
}
MSG msg;
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
控制台版本不需要完全不同,尽管您确实需要创建一个窗口并运行消息泵,因此我不确定它是通过GUI应用程序购买的。显然,如果你想在任何一个版本中工作,你很可能最终需要一个单独的线程用于窗口或你的工作。
这是我提出的最简单的控制台程序示例。您会注意到,除了ConsoleCtrlHandler之外,它几乎完全相同,可以截取关闭控制台窗口和杀死GUI窗口的各种方法。由于我不想在我的测试控制台项目中更改它,因此它也有望成为MBCS项目。
#include <SDKDDKVer.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
HINSTANCE hInst;
HWND hWnd;
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
switch(message)
{
case WM_QUERYENDSESSION:
return FALSE;
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
break;
case WM_CREATE:
ShutdownBlockReasonCreate(hWnd, L"Don't do it!");
break;
case WM_DESTROY:
ShutdownBlockReasonDestroy(hWnd);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
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 = "TestClass";
wcex.hIconSm = NULL;
return RegisterClassEx(&wcex);
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance;
RECT sz = {0, 0, 512, 512};
AdjustWindowRect(&sz, WS_OVERLAPPEDWINDOW, TRUE);
hWnd = CreateWindow("TestClass", "Test Window", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, sz.right - sz.left, sz.bottom - sz.top,
NULL, NULL, hInstance, NULL);
if(!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
BOOL WINAPI ConsoleCtrlHandler(DWORD dwCtrlType)
{
if(dwCtrlType == CTRL_C_EVENT ||
dwCtrlType == CTRL_BREAK_EVENT ||
dwCtrlType == CTRL_CLOSE_EVENT)
{
SendMessage(hWnd, WM_CLOSE, 0, 0);
return TRUE;
}
return FALSE;
}
int main()
{
SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE);
HINSTANCE hInstance = GetModuleHandle(NULL);
MyRegisterClass(hInstance);
if(!InitInstance(hInstance, SW_HIDE))
{
return FALSE;
}
MSG msg;
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
答案 1 :(得分:3)
正如您现在可能猜到的那样,ShutdownBlockReasonCreate()
实际上并不会阻止关机。它所做的就是告诉Windows弹出this screen时要说出的消息。
要在Windows上阻止关闭,您需要有一个窗口。这意味着您需要编写一个使用标准消息泵的GUI程序。 WM_QUERYENDSESSION
是系统要关闭时发送到所有窗口的消息。您可以处理该消息以阻止关闭请求。但要理解这一点,您需要了解Windows GUI编程。 (您可能不需要实际的GUI;只有消息的窗口可能工作。我不确定。)
关于此事的第一个问题是阻止系统服务的关闭。我不是Windows服务方面的专家,所以我不知道答案。但是,由于在会话0上运行,服务不应具有GUI。我不知道他们是否也可以使用仅限消息的窗口。