C++ 如何在没有窗口的情况下防止系统关闭?

C++ 如何在没有窗口的情况下防止系统关闭?,c++,winapi,shutdown,C++,Winapi,Shutdown,我有这个源代码的windows应用程序 #include <Windows.h> #include <thread> #include <chrono> int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int cmdShow) { MSG msg; while (GetMessage(&ms

我有这个源代码的windows应用程序

#include <Windows.h>
#include <thread>
#include <chrono>

int WinMain(HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPTSTR    lpCmdLine,
    int       cmdShow)
{
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return msg.wParam;
}
LRESULT CALLBACK WinProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
    switch (Message)
    {
        case WM_QUERYENDSESSION:
            MessageBox(NULL, "Triggered?", "Message", 0);
            AbortSystemShutdown(NULL);
            return 0;

        default:
            return DefWindowProc(hWnd, Message, wParam, lParam);
    }

    return 0;
}
#包括
#包括
#包括
int WinMain(HINSTANCE HINSTANCE,
HINSTANCE HPPrevenstance,
LPTSTR lpCmdLine,
int cmdShow)
{
味精;
while(GetMessage(&msg,NULL,0,0))
{
翻译信息(&msg);
发送消息(&msg);
}
返回msg.wParam;
}
LRESULT回调WinProc(HWND-HWND,UINT消息,WPARAM-WPARAM,LPARAM-LPARAM)
{
开关(信息)
{
案例WM_查询结束会话:
MessageBox(空,“已触发?”,“消息”,0);
中止系统关闭(空);
返回0;
违约:
返回DefWindowProc(hWnd、Message、wParam、lParam);
}
返回0;
}
我需要知道系统何时关闭并阻止它,或者至少向用户发送消息

我的应用程序似乎没有收到
WM\u QUERYENDSESSION
消息

我还尝试使用
ShutdownBlockReasonCreate()
,但我没有用于窗口的
HWND


我应该如何做到这一点?

如以下参考中所述:

窗口通过其WindowProc功能接收此消息

您有一个WindowProc,但缺少一个窗口。WindowProc必须与窗口关联,否则Windows不知道它。要将WindowProc与窗口关联,可以调用
RegisterClassEx
,然后调用
CreateWindowEx
。在调用
CreateWindowEx
中指定新创建的窗口类的名称

该窗口必须是顶级窗口。它可以不可见,但在这种情况下,以下内容适用(从):

还要注意,如果应用程序没有可见的顶级窗口, 如果需要成功阻止关机,则必须使用此API[]。这样的 如果应用程序阻止关闭,它们将自动终止 没有使用API

请注意,a

工作示例:

#include <windows.h>

LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam );

int APIENTRY wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
                       LPWSTR lpCmdLine, int nCmdShow )
{
    WNDCLASSEXW wx = { sizeof(wx) }; // set cbSize member and zero-initialize all other
    wx.lpfnWndProc = WndProc;
    wx.hInstance = hInstance;
    wx.lpszClassName = L"MyWindowClass";

    if( ! RegisterClassExW( &wx ) )
        return 1;  // TODO: improve error handling

    HWND hWnd = CreateWindowExW( 0, wx.lpszClassName, L"My Application", 0, 0, 0, 0, 0, 
                                 NULL, NULL, NULL, NULL );
    if( ! hWnd )
        return 2;  // TODO: improve error handling

    MSG msg;
    while( GetMessage( &msg, nullptr, 0, 0 ) )
    {
        TranslateMessage( &msg );
        DispatchMessage( &msg );
    }

    return static_cast<int>( msg.wParam );
}

LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
    switch( message )
    {
        case WM_QUERYENDSESSION:
        {
            // Try to block shutdown.
            ShutdownBlockReasonCreate( hWnd, L"I don't want to sleep (yet)!" );
            return FALSE;
        }
        case WM_ENDSESSION:
        {
            // TODO: Always handle this message because shutdown can be forced
            // even if we return FALSE from WM_QUERYENDSESSION!
            return 0;
        }
        default:
        {
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
    }
    return 0;
}
#包括
LRESULT回调WndProc(HWND HWND,UINT消息,WPARAM WPARAM,LPARAM LPARAM);
int APIRENT wWinMain(HINSTANCE HINSTANCE、HINSTANCE hPrevInstance、,
LPWSTR lpCmdLine,int nCmdShow)
{
WNDCLASSEXW wx={sizeof(wx)};//设置cbSize成员并将所有其他成员初始化为零
wx.lpfnWndProc=WndProc;
wx.hInstance=hInstance;
wx.lpszClassName=L“MyWindowClass”;
如果(!RegisterClassesXW(&wx))
返回1;//TODO:改进错误处理
HWND HWND=CreateWindowExW(0,wx.lpszClassName,L“我的应用程序”,0,0,0,0,
空,空,空,空);
如果(!hWnd)
返回2;//TODO:改进错误处理
味精;
while(GetMessage(&msg,nullptr,0,0))
{
翻译信息(&msg);
发送消息(&msg);
}
返回静态_cast(msg.wParam);
}
LRESULT回调WndProc(HWND HWND,UINT消息,WPARAM WPARAM,LPARAM LPARAM)
{
开关(信息)
{
案例WM_查询结束会话:
{
//尝试阻止关机。
ShutdownBlockReasonCreate(hWnd,L“我还不想睡觉!”;
返回FALSE;
}
案例WM_ENDSESSION:
{
//TODO:始终处理此消息,因为可以强制关闭
//即使我们从WM_QUERYENDSESSION返回FALSE!
返回0;
}
违约:
{
返回DefWindowProc(hWnd、message、wParam、lParam);
}
}
返回0;
}
进一步阅读:

#include <windows.h>

LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam );

int APIENTRY wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
                       LPWSTR lpCmdLine, int nCmdShow )
{
    WNDCLASSEXW wx = { sizeof(wx) }; // set cbSize member and zero-initialize all other
    wx.lpfnWndProc = WndProc;
    wx.hInstance = hInstance;
    wx.lpszClassName = L"MyWindowClass";

    if( ! RegisterClassExW( &wx ) )
        return 1;  // TODO: improve error handling

    HWND hWnd = CreateWindowExW( 0, wx.lpszClassName, L"My Application", 0, 0, 0, 0, 0, 
                                 NULL, NULL, NULL, NULL );
    if( ! hWnd )
        return 2;  // TODO: improve error handling

    MSG msg;
    while( GetMessage( &msg, nullptr, 0, 0 ) )
    {
        TranslateMessage( &msg );
        DispatchMessage( &msg );
    }

    return static_cast<int>( msg.wParam );
}

LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
    switch( message )
    {
        case WM_QUERYENDSESSION:
        {
            // Try to block shutdown.
            ShutdownBlockReasonCreate( hWnd, L"I don't want to sleep (yet)!" );
            return FALSE;
        }
        case WM_ENDSESSION:
        {
            // TODO: Always handle this message because shutdown can be forced
            // even if we return FALSE from WM_QUERYENDSESSION!
            return 0;
        }
        default:
        {
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
    }
    return 0;
}

通常在尝试处理窗口消息之前先创建窗口。“窗口过程”(或“winproc”)连接到窗口类。如果没有窗口或窗口类,那么事件循环实际上就没有什么可做的。名为
WinProc
的函数没有什么特别之处,Windows不会自动调用它。
WM\u QUERYENDSESSION
的文档中不清楚此消息是发送到所有顶级窗口(这很荒谬,但也不是不可想象的)还是任务消息。也就是说,如果微软的文档是可靠的,那么可以从“由windows proc处理”推断它被发送到了一个窗口。但是文档中充满了这样的技术作者的许可证声明,其中大多数都是完全错误的(就像许多被高估的答案一样)。如果是任务消息,那么只需将处理移动到消息循环。但如果它被发送到顶级widnows,那么就创建一个顶级窗口。为什么要这样做?这听起来是个坏主意™.@干杯-如果你是说一条线索信息?实际上,如果您考虑“代码> WMQQueEngEngutsEng/<代码>具有返回值这一事实,还不清楚。因此,它无法将值返回给发送方。这只剩下
SendMessage*
函数系列,它们总是与窗口关联。啊,不可见窗口。工作起来像个小丑“它可以是隐形的。”:如果你想阻止关机,就不要这样做。MS'docs说:“请注意,系统不允许控制台应用程序或没有可见窗口的应用程序取消关机。”()@cheers-sandhth.-Alf至少在Win 10下,即使只有一个不可见窗口,它也会显示
ShutdownBlockReasonCreate
消息。还没有测试过旧的操作系统。也许文档是错的。这不是第一次了。“但如果屏幕外有一个可见的窗口,也许会更好?”Cheerrsandhth.-Alf我现在已经在Win7和Win8.1下成功地测试了上述代码。此行为也在上得到确认:“但是,如果没有可见顶级窗口的应用程序使用新API主动指示它需要阻止关闭,windows Vista将不会自动终止它,而是将其视为具有可见顶级窗口的应用程序。”。再往下一页,是