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

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

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

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

Win32 API

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

Q&A

解決済

1回答

3299閲覧

WinMergeをWinAPIで操作

ExcelVBAer

総合スコア1175

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

Win32 API

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

0グッド

2クリップ

投稿2019/04/03 08:50

編集2019/04/04 00:30

ExcelVBAの修正前後で、ソースの差異を検証する為に、
WinMergeを使っており、一部の操作を自動化したく、
現在、修正前、修正後で、各ソースをフォルダにエクスポートし、
WinMergeに各フォルダのパスを渡し、
比較結果を、Htmlレポートで出力しています。
※WinMergeのツール → レポートの生成 → フォルダ比較レポート

このWinMergeの操作で、
「ツール(T)」を押下、
「レポート作成(R)」を押下
をSendKeyで操作している為に、
他の作業をしているとエラーになってしまいます。

そこで、ユーザー作業の影響を受けないよう、
Window Message 等で直接操作したく、
Menuのハンドルを取得し、
ツール(T) のIDを取得し、
PostMessage で WM_Command を送る等を試みたのですが、
自分では解決できず、
どなたか、解決の糸口、ヒント等をご教示頂けましたら、
大変助かります。

※IAccessible では実現できない事も判明しています。。。

どうぞ宜しくお願い致します。

<実現イメージ>
イメージ説明

VBA

1Private Declare Function GetMenu Lib "user32" (ByVal hWnd As Long) As Long 2Private Declare Function GetSubMenu Lib "user32" (ByVal hMenu As Long, ByVal nPos As Long) As Long 3 4'メイン部分のみですが、取り急ぎご参考まで... 5Private Function prWinMerge操作() 6 7 'WinMergeのウィンドウハンドルを取得 8 Dim hWinMerge As Long 9 hWinMerge = fWinHnd_Window_Find(, "WinMergeWindowClassW") 10 If hWinMerge = 0 Then Exit Function 11 12 'アクティブなスレッドにアタッチして、ウィンドウをアクティブ化 13 Call fWinHnd_Activate(hWinMerge) 14 15 'メニュ-のハンドルを取得 16 Dim hMenu As Long 17 hMenu = GetMenu(hWinMerge) 18 19 'メニューの「ツール(T)」のハンドルを取得 20 Dim hSubMenu As Long 21 hSubMenu = GetSubMenu(hMenu, 6) 22 23 'メニューの「ツール(T)」ボタン押下 ⇒ 押下状態にならない... 24 Call PostMessage(hWinMerge, WM_COMMAND, hSubMenu, 0&) 25 26 '押下できたか、少し待つ 27 Call fApp_Wait(1) 28 29 '押下できていたら、更に「レポート作成(R)」ボタン押下 30 31 32End Function

<追記>
SPY++で「レポート(R)」押下時のWM_COMMANDを確認
イメージ説明

VBA

1'修正版のコード 2Private Function prWinMerge操作() 3 4 'WinMergeのウィンドウハンドルを取得 5 Dim hWinMerge As Long 6 hWinMerge = fWinHnd_Window_Find(, "WinMergeWindowClassW") 7 If hWinMerge = 0 Then Exit Function 8 9 '「レポート(R)」を押下 10 Const wID As Long = 32868 11 Call PostMessage(hWinMerge, WM_COMMAND, wID, 0&) 12 13End Function

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

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

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

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

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

atata0319

2019/04/03 09:27 編集

逆に現在SendKeysを使用しているコードを記載いただいた方が回答しやすいかもしれません。
m.ts10806

2019/04/03 09:37

SVN入れたほうがいいような
ExcelVBAer

2019/04/04 00:00

クローズドな環境なもので、他のソフトをイストールできず...
m.ts10806

2019/04/04 00:06

んーなるほど了解です
guest

回答1

0

ベストアンサー

当面の目的の操作はWinMergeの「ツール(T)」-->「レポート作成(R)」とメニュー選択することで良いでしょうか。
そうだとすると、PostMessageWM_COMMANDを送るときのパラメーターが違います。最終的に必要なメニュー指定は「レポート作成(R)」で、これを選択したときにWM_COMMANDがメインのウィンドウへ送られます。このときのWM_COMMANDのパラメータは、WPARAMがメニューハンドルではなくメニューIDで、LPARAMが0になります。

Microsoft Docs - WM_COMMAND message

手持ちのWinMerge(2.4.10.0 Unicode ※日本語化はしていません) をSpy++で確認した限りですが、このメニューIDは32868でした。

ちなみにExcelVBAではありませんが、Win32 ネイティブ(32ビット)の外部プログラムから以下のコードで「レポート作成(R)」メニューを選択したときのファイル選択ダイアログボックスを出すことができました。

C++

1// うまく動かないときは各APIの返り値をチェックしてください。 2HWND hwnd = ::FindWindow(_T("WinMergeWindowClassW"), NULL); 3if (hwnd != NULL) { 4 WPARAM wParam = MAKEWPARAM(32868, 0); 5 LPARAM lParam = 0; 6 7 BOOL b = ::PostMessage(hwnd, WM_COMMAND, wParam, lParam); 8 ATLTRACE2(_T("b=%d\n"), b); 9}

ただ、最終的にやりたい操作がWinMergeのコマンドラインオプションのみならず、上記でもこなせかったり、更にSendKeysでも難しい場合はUIAutomationの機能を使ったり、UiPathなどのRPA製品を使ったほうが良いかもしれません。

投稿2019/04/03 10:13

編集2019/04/03 10:16
dodox86

総合スコア9183

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

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

ExcelVBAer

2019/04/04 00:03

ありがとうございます! パラメータが違ってましたか(汗) 早速やってみます!!
ExcelVBAer

2019/04/04 00:19

無事にこちらでも再現できました~!(涙) SPY++ にも慣れておらず、 ようやくパラメータの意味が分かりました! ありがとうございました!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問