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

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

ただいまの
回答率

90.48%

  • C

    4641questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

  • C++

    4505questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

  • Win32 API

    297questions

    Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

  • MFC

    146questions

    MFC (Microsoft Fouondation Class)とは、MicrosoftがVC++用に開発したWindows用アプリケーションのフレームワークです。

メッセージボックスのOKボタンを自動でクリック出来るようにしたい。

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 160

oppeke

score 1

前提・実現したいこと

とあるソフトを使用していると、一定の間隔でメッセージボックスが表示されます。
手動でOKを押すのが手間だったので、自動でOKボタンをクリックするツールを作ろうと思いました。

プログラムの流れとしては、
OKボタンの位置にマウスカーソル移動

クリックのイベント送信
という簡単な処理だけです。

発生している問題・エラーメッセージ

メッセージボックスのOKボタンの位置にカーソル移動はするのですが、OKボタンがクリックされません。
クリック自体は出来ているよう(他のウィンドウをその位置に置くとそのウィンドウが前面にきます)です。
ボタンをクリック出来るようにするには、どう改善すればいいのでしょうか?

該当のソースコード

MFCのダイアログベースで作成しています。
現在はテストの為にボタンが押された時に処理しようとしています。
ボタンのクリックのイベントで以下の処理を追加しました。

void CMFCApplication2Dlg::OnBnClickedButton1()
{
    // ボタンの位置
    SetCursorPos(1135, 603);

    INPUT input = {};
    input.type = INPUT_MOUSE;
    input.mi.dx = 0;
    input.mi.dy = 0;
    input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP;

    SendInput(1, &input, sizeof(INPUT));

    //mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
    //mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);


}

試したこと

コメントアウトしている部分のソースでも試しましたが、結果は同じでした。

ウィンドウハンドルを取得して、メッセージを送信するという方法も行うと思いましたが、
少し調べるとメッセージボックスのウィンドウハンドルはWinApiでは取得できないと
情報があったので([リンク]別言語の情報ですが、同じWinApiのトピックなので参考にしました)、簡単にカーソル位置を移動させる方法にしようと思いました。
また、spy++も使いましたが、メッセージボックスのハンドルは取得できませんでした。

補足情報(FW/ツールのバージョンなど)

リンク
上記URLを参考にボタンクリックの処理は作成しました。

環境は
MFC
VisualStudio2017
windows7
です

表示されるメッセージボックスは、Windows標準のものになります(MessageBox関数で出るものと同じです)

  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

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

  • atata0319

    2019/06/10 02:59 編集

    メッセージボックスの種類(Windows標準か該当ソフトウェア独自か)を記載いただくと回答しやすくなります。いろいろ対応はかなり手間ですので・・・。

    ただ、フリーソフト等で対応できない理由がなければフリーソフトを使った方が良いかと思います。と言うのとフリーソフトを使用できない技術的な理由があれば質問に追記いただけると回答を得やすいと思います。

    キャンセル

  • t_obara

    2019/06/10 11:29

    https://teratail.com/questions/81883
    ウィンドウハンドルをどのように取得するかは色々あるかと思いますが、
    とあるソフト限定であれば、spyとか使うのが一番かと。

    キャンセル

  • oppeke

    2019/06/10 12:18

    追記ありがとうございます。

    atata0319さん
    メッセージボックスの種類について追記致しました。
    Windows標準のものになります。
    フリーソフトを使わない理由については、プログラミングの勉強もついでにできると思ったからです。正直なところ大きな理由はありません。
    どうしても無理そうなら、フリーソフトの利用も検討したいと思います。

    t_obaraさん
    メッセージを送信する方法でも行おうと思いましたが、
    WinApiではメッセージボックスのハンドルは取得できないと情報があったので一旦やめていました。
    出来そうならもう一度試してみたいと思います。

    キャンセル

回答 2

checkベストアンサー

+3

標準のメッセージボックスについては RPA 等の自動操作分野で一般的になった手法があります。WinEvent フックと t_obara さんが提示されている、WM_COMMAND を送信する方式の組み合わせです。

以下に提示するサンプルのように特定のプロセスに対して SetWinEventHook の EVENT_SYSTEM_DIALOGSTART を仕掛けてダイアログ表示を検出し、検出したダイアログに対して SendMessage で WM_COMMAND を送信して閉じる手法になります。ダイアログはメッセージボックス以外にも検出されますが、検出したダイアログのサイズ等の情報によりメッセージボックスのみを閉じるようにしたりします。

void Cteratail194066Dlg::OnBnClickedOk()
{
    if (m_event == nullptr)
    {
        m_event = SetWinEventHook(
            EVENT_SYSTEM_DIALOGSTART,
            EVENT_SYSTEM_DIALOGSTART,
            NULL,
            WinEventProc,
            GetDlgItemInt(IDC_PROCESSID),
            0,
            WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS
        );
        if (m_event != nullptr)
        {
            SetDlgItemText(IDOK, _T("停止"));
        }
    }
    else
    {
        UnhookWinEvent(m_event);
        m_event = nullptr;
        SetDlgItemText(IDOK, _T("開始"));
    }
}

void CALLBACK Cteratail194066Dlg::WinEventProc(HWINEVENTHOOK hWinEventHook, DWORD event, HWND hwnd, LONG idObject, LONG idChild, DWORD idEventThread, DWORD dwmsEventTime)
{
    ::SendMessage(hwnd, WM_COMMAND, IDOK, 0);
}

github に全体のサンプルを上げましたので、必要であれば内容を確認してみてください。
https://github.com/atata0319/teratail194066


上記サンプルは Windows 10 のメモ帳相手に実験しています。他の環境ではこのままのコードでは駄目なようです。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/06/11 22:13 編集

    ご回答ありがとうございます。
    SetWinEventHook関数は知らなかったので、勉強になりました。
    おかげさまで、メッセージボックスを閉じる事ができました!
    しかし、
    ::SendMessage(hwnd, WM_COMMAND, IDOK, 0);
    では何故か閉じる事が出来なかったため、
    t_obaraさんのご回答と追記のリンクを参考に、
    HWND hwndChild = FindWindowEx(hwnd, 0, "Button", "OK");
    SendMessage(hwndChild, BM_CLICK, 0, 0);
    と変更することで、閉じる事ができました。

    あとは、メッセージボックスの判別を出来るように改善していこうと思います。
    本当にありがとうございました!

    キャンセル

+2

https://stackoverflow.com/questions/14962081/click-on-ok-button-of-message-box-using-winapi-in-c-sharp

C#のサンプルですが、適宜読み替えればよろしいかと思います。

MessageBoxのウィンドウハンドルに対して、WM_COMMANDを投げる形ですね。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/06/11 22:14 編集

    ご回答ありがとうございます。
    ご提示頂いたリンクとatata0319さんのご回答を元に、
    自動でメッセージボックスを閉じる事ができました!
    ありがとうございました。

    キャンセル

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

  • C

    4641questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

  • C++

    4505questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

  • Win32 API

    297questions

    Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

  • MFC

    146questions

    MFC (Microsoft Fouondation Class)とは、MicrosoftがVC++用に開発したWindows用アプリケーションのフレームワークです。