質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.93%

(Win32API)ウインドウを生成せず、処理内容はバックグラウンドで行い、タスク常駐するアプリ

解決済

回答 4

投稿 編集

  • 評価
  • クリップ 2
  • VIEW 4,883

mercurian-teto

score 75

環境

windows 10 pro
visual studio 2017

質問

C#にあるようなWPF常駐タスクのアプリをwindowsAPIで実現する
C#のWPFの常駐タスクは

①タスクバーにアイコンが表示して、
②左クリックするとポップアップメニューが開かれたり、
③ウインドウを生成せず、バックグラウンドで処理内容を実行する

CのwinAPIの常駐アプリだと、①や②は自分でもできたのですが、
ウインドウを生成せず、バックグラウンドで処理(windowsを出さずに処理)
の実装方法がわかりません。

「windows API バックグラウンド」で検索してもいい情報が見当たりません。
また、C#のWPFアプリのようなものを目指しているので、windowsサービスではありません。
下にあるのが、windowsAPIの常駐タスクアプリです。
どういった実相を加えればよろしでしょうか。

また、windows APIで行いたい理由は
windows APIでシャットダウンを抑制するコマンドがあるからです。
これをバックグランで常駐して実行したいです。

サンプル
#include <Windows.h>
#include <tchar.h>

#define WM_TASKTRAY (WM_USER+1)
#define ID_TASKTRAY 0

HWND    g_hWnd;

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
    case WM_TASKTRAY:
        if (wParam == ID_TASKTRAY)
        {
            switch (lParam) {


                break;
            case WM_RBUTTONUP:
                /* 右ボタンが離された処理 */
                MessageBox(NULL,
                    _T("こんにちは"),
                    _T("Sample02"),
                    NULL);
                return 1;

                break;

            default:
                /* 上記以外の処理 */
                break;
            }

        }
        break;
    case WM_DESTROY:                                       //!< ウインドウを閉じる
        ::PostQuitMessage(0);                               //!< WM_QUITを送る
        return ::DefWindowProc(hWnd, msg, wParam, lParam);
    default:
        return ::DefWindowProc(hWnd, msg, wParam, lParam);
    }
    return ::DefWindowProc(hWnd, msg, wParam, lParam);
}

BOOL Init(HINSTANCE hInstance)
{
    // ウインドウ生成
    WNDCLASS                wc;                                       //!< ウインドウクラス
                                                                      // ウインドウクラスの登録
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = static_cast<WNDPROC>(WndProc);    //!< メッセージを受け取るウインドウ関数
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.hIcon = NULL;                                     //!< アイコン登録
    wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);    //!< カーソル登録
    wc.hbrBackground = static_cast<HBRUSH>(::GetStockObject(WHITE_BRUSH));
    wc.lpszMenuName = NULL;                        //!< メニューの登録
    wc.lpszClassName = L"常駐";
    // ウインドウクラスの登録
    if (!::RegisterClass(&wc)) return EXIT_FAILURE;

    // ウインドウを作成
    g_hWnd = ::CreateWindow(L"常駐",                     //!< クラス名
        L"常駐",                                            //!< タイトル名
        WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU, //!< スタイル
        0,                                                    //!< X座標
        0,                                                    //!< Y座標
        100,                                                //!< 横幅
        100,                                                //!< 高さ
        NULL,                                          //!< 親ウインドウのハンドル
        NULL,                                          //!< メニューハンドル
        hInstance,                                   //!< インスタンスハンドル
        NULL);                                        //!< lParam

                                                      // ウインドウの作成
    if (!g_hWnd) return EXIT_FAILURE;
    // ウインドウの表示状態の設定
    ::ShowWindow(g_hWnd, SW_SHOW);
    // ウインドウの更新
    ::UpdateWindow(g_hWnd);

    // http://yokohama.cool.ne.jp/chokuto/urawaza/struct/NOTIFYICONDATA.html
    // http://yokohama.cool.ne.jp/chokuto/urawaza/trayicon.html
    // http://www31.ocn.ne.jp/~yoshio2/vcmemo17-1.html
    NOTIFYICONDATA nif;
    // タスクトレイに登録
    nif.cbSize = sizeof(NOTIFYICONDATA);
    nif.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    nif.hWnd = g_hWnd;
    nif.uCallbackMessage = WM_TASKTRAY;
    nif.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
    nif.uID = ID_TASKTRAY;
    ::wcscpy_s(nif.szTip, 128, L"常駐");

    Shell_NotifyIcon(NIM_ADD, &nif);

    return EXIT_SUCCESS;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    MSG msg;

    if (Init(hInstance) == EXIT_FAILURE) return EXIT_FAILURE;

    while (::GetMessage(&msg, NULL, 0, 0))
    {
        ::TranslateMessage(&msg);
        ::DispatchMessage(&msg);
    }
    return EXIT_SUCCESS;
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • Zuishin

    2018/04/10 20:52

    C# タグを外してください。まったく関係ありません。Windows アプリはコンソールアプリやサービス以外基本的にウィンドウが必要です。ウィンドウを生成しないのではなく非表示にしてください。具体的な方法はほかの人に任せます。

    キャンセル

  • mercurian-teto

    2018/04/10 21:16

    お騒がせしました。すいません訂正します。

    キャンセル

回答 4

+1

タスクトレイ に常駐する アプリケーション を作成するには
上記ではMFCを使ってますが、ほぼ生APIなので参考になると思います。
あるいは拡張ウインドウスタイルWS_EX_TOOLWINDOWShell_NotifyIcon関数で検索すると他にも参考になるページが見つかると思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/04/19 17:28

    ありがとうございました。

    キャンセル

+1

こんにちは。

Windows APIをC#から直接呼ぶこともできますよ。定義を自力で作る必要がありますし、中にはできないものもあるとは思いますが。
「C# windows api」で検索すると結構たくさん出てきます。
呼びたい関数名とC#で検索すると運が良ければ、その関数をC#から呼ぶための定義を公開してる記事が見つかることもあります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/04/19 17:27

    C#でwinAPIを使えるのは知りませんでした。ありがとうございます。

    キャンセル

+1

C# から Win32 API を呼び出すのに必要な定義については、ずばりそれらをまとめたサイトがこちらになります。C# と VB.NET の両方の定義が出てきます。
PInvoke.net

Visual Studio の add-in で統合環境から直接検索、ペーストなんかもできたります。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/04/19 17:29

    C#でwinAPIでつかえるのは知りませんでした。
    回答ありがとうございました。

    キャンセル

checkベストアンサー

0

まーよくやるのは、スプラッシュウィンドウ的なものをFormで作っておいて、常駐後表示を消すってことしますな。

なにも言わずに常駐するってのは、ワタクシ的にはキモチワルイと思いますねー

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/04/19 17:30

    ::ShowWindow(g_hWnd, SW_HIDE);を使用するのに行き着きました。
    回答ありがとうございました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.93%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • トップ
  • C++に関する質問
  • (Win32API)ウインドウを生成せず、処理内容はバックグラウンドで行い、タスク常駐するアプリ