▲[ 103692 ] / 返信無し
■103694 / 3階層) |
Re[3]: EXCEL VBAからのWindows.Forms呼出方法 |
□投稿者/ 魔界の仮面弁士 (3847回)-(2025/05/26(Mon) 10:44:40)
|
2025/05/26(Mon) 10:56:33 編集(投稿者)
■No103692 (PATIO さん) に返信 > 某社が.net frameworkベースで開発してるGUIライブラリです。 その会社に協力を要請できないのでしょうか。
> そもそもライブラリの仕様すら公開されていません。 dnSpy を使えば、.NET や .NET Framework の EXE/DLL に対してデバッグや実装解析が可能です。 それを許容しない会社の場合、難読化されていて読み解けない可能性もありますが。 https://qiita.com/Tokeiya/items/54fbf30cb21c77c05c41 https://hakase0274.hatenablog.com/entry/2019/09/11/222621
> リストに基づいて処理を進めるようなインターフェイスが無いので > EXCELマクロを利用してその部分の自動化をしようとしています。 .NET においては、無人操作のために Codeer Friendly を利用している所は見かけます。 https://www.nuget.org/packages?q=Codeer.Friendly
ただ、これは COM インターフェイスは搭載していなかったはずなので、VBA から呼び出したいのであれば、 先述の通り、VBA から呼び出すためのラッパーを C# 等で別途作成する必要があるでしょう。
■No103689 (PATIO さん) に返信 > Accessibility Insights For Windowsでみた所、Nameプロパティで拾えるケースがある ソースコードはこちら。 https://github.com/microsoft/accessibility-insights-windows
■No103690 (魔界の仮面弁士) に追記 > Set objIUIAutomationElement = objUIAuto.ElementFromHandle(ByVal hWnd) 'もしくは ElementFromPoint ElementFromHandle の呼び出しは可能ですが、VBA からだと ElementFromPoint は直接呼び出せないことを忘れていました…。 ElementFromPoint の引数定義が「ByVal As ユーザー定義型」のため、VBA からは直接呼べません。
COM の低レベルAPI(DispCallFunc 関数)を使えば呼び出せますけれどね。 http://blog.livedoor.jp/tarboh_w-inko/archives/39939041.html
AccessibleObjectFromPoint API の方も「ByVal As ユーザー定義型」な引数ですが、 Declare 宣言を変更することで、同等の呼び出しスタックを再現できるため、 API 版の方が融通が利きます。
UIAutomation の ElementFromPoint メソッドで IUIAutomationElement を得る代わりに AccessibleObjectFromPoint API でカーソル配下の IAccessible を得るようにしてみたサンプル。
'ThisWorkbook Option Explicit
Private Declare PtrSafe Function GetCursorPos Lib "user32" (ByVal lpPoint As LongPtr) As Long
#If Win64 Then Private Declare PtrSafe Function AccessibleObjectFromPoint Lib "Oleacc" (ByVal ptScreen As LongLong, ByRef ppacc As IAccessible, ByRef pvarChild As Variant) As Long #Else Private Declare PtrSafe Function AccessibleObjectFromPoint Lib "Oleacc" (ByVal x As Long, ByVal y As Long, ByRef ppacc As IAccessible, ByRef pvarChild As Variant) As Long #End If
Public Sub ExampleWankuma103689() Dim pos(0 To 1) As Long Dim endTime As Double Dim accProp(0 To 2) As Variant Dim acc As Office.IAccessible Const CHILDID_SELF As Variant = &H0& Dim vnt As Variant vnt = CHILDID_SELF '10 秒間繰り返し Dim msg As String endTime = Timer + 10# Do Until endTime <= Timer GetCursorPos VarPtr(pos(0)) msg = Format(endTime - Timer, "0.000") & "秒 (" & CStr(pos(0)) & ", " & CStr(pos(1)) & ")" Erase accProp On Error Resume Next #If Win64 Then Dim posXY As LongLong posXY = pos(1) * &H100000000^ Or CLngLng(pos(0)) AccessibleObjectFromPoint posXY, acc, vnt #Else AccessibleObjectFromPoint pos(0), pos(1), acc, vnt #End If If Not acc Is Nothing Then accProp(0) = Replace(acc.accName, vbNullChar, "") accProp(1) = Replace(acc.accValue, vbNullChar, "") accProp(2) = Replace(acc.accDescription, vbNullChar, "") Set acc = Nothing msg = msg & ",Name=[" & accProp(0) & "],Value=[" & accProp(1) & "],Description=[" & accProp(2) & "]" End If On Error GoTo 0 [Sheet1!A1].Value = msg DoEvents Loop End Sub
ただ、相手が .NET Framework 製のライブラリということで、 上記の IAccessible からでは十分に情報を得られないかも知れません。 UI の操作を行うことが目的なら、IAccessible よりも UI Automation の方が 目的に合致しすいかと。UI Automation の場合、上位のオブジェクトから And/Or の条件指定で子孫要素を探索できる機構がありますし、 Web 上にも、VBA / .NET いずれに対してもそれなりに情報があると思います。
参考までに、ソースコード付きの VBA サンプルが下記にあります。 https://qiita.com/fenblen_puyo/items/d6d51470a648b9862c07
|
|