2011-02-01 15 views
3

私はGF用のホットキーを使ってシステムマスターボリュームを制御する小さなユーティリティアプリを作成しています。その理由は何らかの理由でそのようなファンクションキーがないからです。私はかなりすぐにコードを書き上げて、主な機能は完璧に動作しています。しかし、私はウィンドウを作成していないので(WM_HOTKEYメッセージを処理するメッセージループ)、私はプロセスを無慈悲に終了するよりもエレガントな方法でアプリケーションを終了できません(また、システムがシャットダウンしているときウィンドウタイトルが通常あるところにゴミが入ったウィンドウを "終了するか、今すぐ終了するか"を示しています)。WinAPIでウィンドウレスのアプリケーションを正常に終了する

WM_CLOSEメッセージを傍受するだけのために偽のウィンドウを作成する必要がない方法はありますか?

はここのコードです(私は意図的にミキサ制御機能を残し、彼らは質問とは無関係です):事前に

int WINAPI WinMain(HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nCmdShow) { 
    MSG msg; 
    int step; 
    MixerInfo_t mi; 
    HANDLE mutex; 

    mutex = CreateMutex(NULL, TRUE, "volhotkey"); 
    if (mutex == NULL) 
     return 1; 
    if (GetLastError() == ERROR_ALREADY_EXISTS) 
     return 0; 

    RegisterHotKey(NULL, 1, MOD_ALT | MOD_CONTROL, VK_F5); 
    RegisterHotKey(NULL, 2, MOD_ALT | MOD_CONTROL, VK_F6); 
    RegisterHotKey(NULL, 3, MOD_ALT | MOD_CONTROL, VK_F7); 

    mi = GetMixerControls(); 
    step = (mi.maxVolume - mi.minVolume)/20; 

    while (GetMessage(&msg, NULL, 0, 0)) { 
     switch (msg.message) { 
      case WM_HOTKEY: 
       switch (msg.wParam) { 
        case 1: 
         AdjustVolume(&mi, -step); 
         break; 
        case 2: 
         AdjustVolume(&mi, step); 
         break; 
        case 3: 
         SetMute(&mi, !IsMuted(&mi)); 
         break; 
       } 
       MessageBeep(MB_ICONASTERISK); 
       break; 
      case WM_DESTROY: 
       PostQuitMessage(0); 
       break; 
      default: 
       break; 
     } 
    } 

    UnregisterHotKey(NULL, 1); 
    UnregisterHotKey(NULL, 2); 

    return msg.wParam; 
} 

感謝を!

ああ、レコードの場合、WM_DESTROYも決して転記されません。

+0

ラップトップの製造元のサポートサイトで、そのようなユーティリティがすでに提供されているかどうか確認しましたか? – Ferruccio

+0

私は持っていますが、彼らはしません。これはHP nx6110であり、すでに質問に記載されているようにボタンがありません。 – IneQuation

答えて

4

シャットダウンイベントを待機するには、SetConsoleCtrlHandler()関数を使用できます。

SetConsoleCtrlHandler(ShutdownHandler, TRUE); 

あなたのハンドラは、このようなものになります。名前にもかかわらず

BOOL WINAPI ShutdownHandler(DWORD dwCtrlType) 
{ 
    if(dwCtrlType == CTRL_SHUTDOWN_EVENT || dwCtrlType == CTRL_LOGOFF_EVENT) 
    { 
     ExitProcess(0); 
     return TRUE; // just to keep the compiler happy 
    } 

    return FALSE; 
} 

を、のSetConsoleCtrlHandler()にかかわらず、アプリケーションがコンソールアプリケーションであるかどうかの動作します。

+1

ありがとう、これは私が探していたものです! :)実際に質問を完全に読んだのはおそらく唯一の人でしょう。 – IneQuation

+0

ようこそ。お役に立てて嬉しいです。 –

0

システムトレイには、エレガントに閉じることができるだけのものをいつでも簡単に表示できます。ユーザーが最終的にホットキーを設定または変更できるようにするか、一時的にオフにして別のアプリケーションなどを妨害する可能性があるため、アプリケーションが大きくなると望ましいことがあります。

設定オプションを備えた小さなウィンドウ?

+0

アプリケーションは成長しません。ちょうど小さなプライベートアプリです。ウィンドウレスソリューションを求めています。 – IneQuation

1

プロセスを正常にシャットダウンするためのExitProcess APIコールをご覧ください。 Windowsのシャットダウンを検出するには、メッセージ処理にWM_ENDSESSIONを含めます。アプリケーションが投稿されたものより複雑な場合は、ExitThreadの機能を確認することもできます。

+0

このメッセージを私の注意を引くためにありがとう、それは便利になる! – IneQuation

1

あなたは隠されたものではなく、ウィンドウを作成しませんでした。したがって、ウィンドウにメッセージを送信してループを終了させる方法はありません。また、WM_DESTROYが決して発動しない理由。

残っているのは、WM_QUITを投稿するPostThreadMessage()です。あなたは何とかスレッドIDを見つけることができなければなりません。 Shell_NotifyIcon()を使用するのは賢明でしょう。

+0

ええと、しかし、)私は具体的に偽造されていないウィンドウのソリューションを求めて、b)終了メッセージを投稿することは問題ありません。問題は、アプリを正常に閉じるための外部リクエストを処理することです。 – IneQuation

+0

Erm、偽のものではなく、実際のもの。ただ見えない。また、Windowsがシャットダウンしているのを発見するのにも非常に便利です。そうすれば、Windowsを停止したり、頭にぶつかることなくアプリケーションを終了することができます。ウィンドウを使用したくない場合は、名前付きパイプを使用します。 –

関連する問題