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

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

新規登録して質問してみよう
ただいま回答率
85.48%
MFC

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

C

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

Win32 API

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

C++

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

Q&A

解決済

2回答

6953閲覧

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

oppeke

総合スコア11

MFC

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

C

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

Win32 API

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

C++

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

2グッド

2クリップ

投稿2019/06/09 15:45

編集2019/06/10 03:25

前提・実現したいこと

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

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

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

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

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

該当のソースコード

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

c++

1void CMFCApplication2Dlg::OnBnClickedButton1() 2{ 3 // ボタンの位置 4 SetCursorPos(1135, 603); 5 6 INPUT input = {}; 7 input.type = INPUT_MOUSE; 8 input.mi.dx = 0; 9 input.mi.dy = 0; 10 input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP; 11 12 SendInput(1, &input, sizeof(INPUT)); 13 14 //mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); 15 //mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); 16 17 18}

試したこと

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

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

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

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

環境は
MFC
VisualStudio2017
windows7
です

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

atata0319, witchy👍を押しています

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

atata0319

2019/06/09 18:00 編集

メッセージボックスの種類(Windows標準か該当ソフトウェア独自か)を記載いただくと回答しやすくなります。いろいろ対応はかなり手間ですので・・・。 ただ、フリーソフト等で対応できない理由がなければフリーソフトを使った方が良いかと思います。と言うのとフリーソフトを使用できない技術的な理由があれば質問に追記いただけると回答を得やすいと思います。
t_obara

2019/06/10 02:29

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

2019/06/10 03:18

追記ありがとうございます。 atata0319さん メッセージボックスの種類について追記致しました。 Windows標準のものになります。 フリーソフトを使わない理由については、プログラミングの勉強もついでにできると思ったからです。正直なところ大きな理由はありません。 どうしても無理そうなら、フリーソフトの利用も検討したいと思います。 t_obaraさん メッセージを送信する方法でも行おうと思いましたが、 WinApiではメッセージボックスのハンドルは取得できないと情報があったので一旦やめていました。 出来そうならもう一度試してみたいと思います。
guest

回答2

0

ベストアンサー

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

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

C++

1void Cteratail194066Dlg::OnBnClickedOk() 2{ 3 if (m_event == nullptr) 4 { 5 m_event = SetWinEventHook( 6 EVENT_SYSTEM_DIALOGSTART, 7 EVENT_SYSTEM_DIALOGSTART, 8 NULL, 9 WinEventProc, 10 GetDlgItemInt(IDC_PROCESSID), 11 0, 12 WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS 13 ); 14 if (m_event != nullptr) 15 { 16 SetDlgItemText(IDOK, _T("停止")); 17 } 18 } 19 else 20 { 21 UnhookWinEvent(m_event); 22 m_event = nullptr; 23 SetDlgItemText(IDOK, _T("開始")); 24 } 25} 26 27void CALLBACK Cteratail194066Dlg::WinEventProc(HWINEVENTHOOK hWinEventHook, DWORD event, HWND hwnd, LONG idObject, LONG idChild, DWORD idEventThread, DWORD dwmsEventTime) 28{ 29 ::SendMessage(hwnd, WM_COMMAND, IDOK, 0); 30}

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


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

投稿2019/06/10 17:54

編集2019/06/11 14:10
atata0319

総合スコア881

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

oppeke

2019/06/11 13:17 編集

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

0

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

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

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

投稿2019/06/10 07:07

t_obara

総合スコア5488

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

oppeke

2019/06/11 13:18 編集

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問