2017-12-12 9 views
1

私は、システムがシャットダウンされたときに知っていて、それを防ぐ、あるいは少なくともユーザーにメッセージを送信する必要があり、このソースコードウィンドウを使用せずにシステムをシャットダウンする方法を教えてください。

#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; 
} 

でWindowsアプリケーションを持っています。

私のアプリケーションがWM_QUERYENDSESSIONメッセージを受信して​​いるようではありません。

私もShutdownBlockReasonCreate()を使用しようとしましたが、ウィンドウにはHWNDがありません。

私はこれをどのようにしたらよいでしょうか?

+3

メッセージを処理しようとする前にウィンドウを作成するのが普通です。 –

+1

"ウィンドウプロシージャ"(または "winproc")がウィンドウクラスに接続されています。ウィンドウやウィンドウクラスがない場合は、イベントループが実際に行うことはありません。 'WinProc'という名前の関数に特別なものは何もないので、Windowsはそれを自動的に呼び出さない。 –

+0

'WM_QUERYENDSESSION'のドキュメントは、このメッセージがすべての最上位レベルのウィンドウに送信されるかどうかは不明です(それは不合理ですが考えられないことではありません)か、タスクメッセージです。つまり、マイクロソフトの文書が信頼できるものであれば、 "windows procによって処理された"ことから、ウィンドウに送信されたことを推測することができます。しかし、そのようなハイテクライターのライセンスに関する記述はドキュメントに完全に含まれていますが、そのほとんどは非常に間違っています(多くの高度に上書きされたSOの回答のように)。タスクmessqageの場合は、メッセージループに処理を移してください。しかし、トップレベルウィジェットに送信された場合は、最上位ウィンドウを作成します。 –

答えて

3

WM_QUERYENDSESSIONための参照で述べたように:

ウィンドウは、WindowProc関数を介してこのメ​​ッセージを受信します。

あなたはWindowProcを持っていますが、ウィンドウがありません。 WindowProcはウィンドウに関連付けられていなければなりません。それ以外の場合はWindowsには認識されません。 WindowProcをウィンドウに関連付けるには、RegisterClassExと、その後にCreateWindowExとを呼び出すことができます。 CreateWindowExへの呼び出しで、新しく作成したウィンドウクラスの名前を指定します。

ウィンドウは最上位のウィンドウでなければなりません。それは目に見えないことができるが、この場合には、以下が(Application Shutdown Changes in Windows Vistaから)適用されます。

また、それはする必要がある場合、それは[ShutdownBlockReasonCreate()]このAPIを使用する必要があり 、あなたのアプリケーションは可視トップレベルウィンドウを持っていない場合ことに注意してください正常にシャットダウンをブロックする。このような アプリケーションは、APIを使用しないでシャットダウンをブロックすると自動的に終了します。

message-only window will not receive WM_QUERYENDSESSIONです。

実施例:

#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; 
} 

はさらに読み取り:

+0

ああ、目に見えないウィンドウ。魅力のように働いた –

+0

Re "It be be invisible。":シャットダウンをブロックしたい人はいません。 MSのドキュメントは次のように述べています。「コンソールアプリケーションやアプリケーションを表示ウィンドウなしでシャットダウンをキャンセルすることはできません」 (https://msdn.microsoft.com/en-us/library/windows/desktop/bb394721(v=vs.85).aspx) –

+0

@ Cheersandhth.-Alf少なくともWin 10の下には、「ShutdownBlockReasonCreate」メッセージが表示されますたとえ目に見えないウィンドウしかないとしても。しかし、古いOSをテストしていない。 – zett42

関連する問題