DOBON.NETプログラミング道掲示板
(現在 過去ログ3 を表示中)

[ 最新記事及び返信フォームをトピックトップへ ]

■33984 / inTopicNo.1)  エクスプローラーのポインタ下のアイテムの取得
  
□投稿者/ 猫まっしぐら 一般人(6回)-(2018/09/20(Thu) 18:19:34)
  • アイコン環境/言語:[Windows7 VB.net2005] 
    分類:[.NET] 

    デスクトップでのポインタ下のアイテムの取得はSysListView32にHITTESTすればいいのですがファイラーとして開いたエクスプローラーのファイルペインで同様のことをするにはどうすればいいのでしょう?
    DirectUIHWNDにHITTESTしても意味無いですし…
引用返信 削除キー/
■33985 / inTopicNo.2)  Re[1]: エクスプローラーのポインタ下のアイテムの取得
□投稿者/ 魔界の仮面弁士 大御所(1145回)-(2018/09/20(Thu) 22:02:04)
  • アイコン
    No33984に返信(猫まっしぐらさんの記事)
    > 環境/言語:[Windows7 VB.net2005] 
    > ポインタ下のアイテムの取得
    
    手元に 2005 が無いので、2017 で書いたコードですが、参考までに。
    
    ※High DPI 環境では、マニフェストで <dpiAware>True</dpiAware> を指定。
    
    
    '参照設定:Accessibility
    Imports System.Runtime.InteropServices
    Partial Public Class Form1
        Private Declare Auto Function AccessibleObjectFromPoint Lib "oleacc" (ByVal pt As Point, <Out, MarshalAs(UnmanagedType.Interface)> ByRef accObj As Accessibility.IAccessible, <Out> ByRef childId As Object) As UInt32
    
        Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
            Timer1.Interval = 1
            Timer1.Start()
        End Sub
    
        Private Sub Timer1_Tick(ByVal sender As Object, ByVal e As EventArgs) Handles Timer1.Tick
            Dim xy As Point = Cursor.Position
            ListBox1.BeginUpdate()
            ListBox1.Items.Clear()
            ListBox1.Items.Add("Pos=" & xy.ToString())
            Dim accObj As Accessibility.IAccessible = Nothing
            Dim varChildId As Object = Nothing
            Dim result As UInt32 = AccessibleObjectFromPoint(xy, accObj, varChildId)
            If result <> 0UI Then
                ListBox1.EndUpdate()
                Return
            End If
            For Each prop As String In New String() {"Name", "Role", "Description", "Help", "State", "Value"}
                Dim strItem As String = prop & "="
                Try
                    strItem &= CStr(CallByName(accObj, "acc" & prop, CallType.Get, 0))
                Catch ex As Exception
                    'strItem &= ex.Message
                End Try
                ListBox1.Items.Add(strItem)
            Next
            ListBox1.EndUpdate()
            If Marshal.IsComObject(accObj) Then
                Marshal.ReleaseComObject(accObj)
            End If
        End Sub
    End Class

引用返信 削除キー/
■33986 / inTopicNo.3)  Re[2]: エクスプローラーのポインタ下のアイテムの取得
□投稿者/ 猫まっしぐら 一般人(7回)-(2018/09/21(Fri) 14:36:04)
  • アイコンNo33985に返信(魔界の仮面弁士さんの記事)

    魔界の仮面弁士様、いつもありがとうございます

    で、このコード試してみたのですが、デスクトップからは取得できるもののエクスプローラーからは名前が取得出来ませんでした
    (accRoleとaccStateは取れていますので動いてはいるようです)
    何か足りないのでしょうか…
引用返信 削除キー/
■33987 / inTopicNo.4)  Re[3]: エクスプローラーのポインタ下のアイテムの取得
□投稿者/ 魔界の仮面弁士 大御所(1146回)-(2018/09/21(Fri) 16:41:54)
  • アイコン2018/09/21(Fri) 16:49:02 編集(投稿者)

    No33984に返信(猫まっしぐらさんの記事)
    > DirectUIHWNDにHITTESTしても意味無いですし…
    Win7 以降は、エクスプローラーのファイルペイン側のクラスが
    SysListView32 から DirectUIHWND に変わっているので、
    自分は MSAA か UI Automation でアクセスするようにしています。


    No33986に返信(猫まっしぐらさんの記事)
    > で、このコード試してみたのですが、デスクトップからは取得できるもののエクスプローラーからは名前が取得出来ませんでした

    追加検証した限りでは、
     VS2017(15.8.5) / Win10 Pro v1803 / .NET Framework 4.7.2
     VS2017(15.8.4) / Win10 Pro v1803 / .NET Framework 4.7.2
     VS2010 SP1 / Win7 Pro SP1 / .NET Framework 3.5.1
     VS2005 SP1 / Win7 Pro SP1 / .NET Framework 3.5.1
    のいずれも、マウスでエクスプローラーの各ファイルをポイントすると
    accValue からアイテム名が得られたのですけれどね。


    ただし、先のコードを当方で実験した場合は、そちらとはむしろ逆で、
    エクスプローラーの場合はファイル名を拾えましたが、
    デスクトップのファイルアイコンからは取得されない状況でした。

    原因は、プロパティに渡す引数(CallByName の最後の引数)を
    0 固定にしていたからなので、渡す引数を 0 ではなく
    varChildId に差し替えてやれば、デスクトップでもエクスプローラーでも
    取得できるようになりました。


    > (accRoleとaccStateは取れていますので動いてはいるようです)
    > 何か足りないのでしょうか…

    エクスプローラーは、詳細表示ですか? それともアイコン/一覧表示ですか?

    詳細表示の場合、accObj.accValue(varChildId) は
    ListViewSubItem 相当の取得になるので、
    名前列以外をポイントするとファイル名が選べません。

    更新日時やサイズ列をポイントした場合にもファイル名が
    得られるようにしたいのであれば、
    accObj.accParent.accName(varChildId)
    にすることで、ListViewItem 相当の取得になる見込みです。

    strItem &= CStr(CallByName(accObj.accParent, "acc" & prop, CallType.Get, varChildId ))

    (上記だと、デスクトップに対して正しく取得できなくなってしまいますが)
引用返信 削除キー/
■33988 / inTopicNo.5)  Re[4]: エクスプローラーのポインタ下のアイテムの取得
□投稿者/ 魔界の仮面弁士 大御所(1147回)-(2018/09/21(Fri) 17:41:55)
  • アイコン2018/09/21(Fri) 18:30:32 編集(投稿者)

    No33987に追記(魔界の仮面弁士の記事)
    >>DirectUIHWNDにHITTESTしても意味無いですし…
    > Win7 以降は、エクスプローラーのファイルペイン側のクラスが
    > SysListView32 から DirectUIHWND に変わっているので、
    > 自分は MSAA か UI Automation でアクセスするようにしています。

    UI Automation 版

    '参照設定:WindowsBase
    '参照設定:UIAutomationClient
    '参照設定:UIAutomationTypes
    Private Sub Timer1_Tick(ByVal sender As Object, ByVal e As EventArgs) Handles Timer1.Tick
      Dim xy As System.Drawing.Point = System.Windows.Forms.Cursor.Position
      ListBox1.BeginUpdate()
      ListBox1.Items.Clear()
      ListBox1.Items.Add("Pos=" & xy.ToString())
      Dim xy2 As New System.Windows.Point(CDbl(xy.X), CDbl(xy.Y))
      Try
        Dim elm As System.Windows.Automation.AutomationElement = System.Windows.Automation.AutomationElement.FromPoint(xy2)
        If elm IsNot Nothing Then
          ListBox1.Items.Add("Name=" & elm.Current.Name)

          Dim ptnObj As Object = Nothing
          If elm.TryGetCurrentPattern(System.Windows.Automation.ValuePattern.Pattern, ptnObj) Then
            Dim ptnValue As System.Windows.Automation.ValuePattern = DirectCast(ptnObj, System.Windows.Automation.ValuePattern)
            ListBox1.Items.Add("Value=" & ptnValue.Current.Value)
          End If
        End If
      Catch
      End Try
      ListBox1.EndUpdate()
    End Sub
引用返信 削除キー/
■33989 / inTopicNo.6)  Re[5]: エクスプローラーのポインタ下のアイテムの取得
□投稿者/ 猫まっしぐら 一般人(8回)-(2018/09/21(Fri) 21:27:08)
  • アイコンNo33988に返信(魔界の仮面弁士さんの記事)

    何度もすみません

    >>エクスプローラーは、詳細表示ですか? それともアイコン/一覧表示ですか?

    一覧表示です
    相変わらずデスクトップからしか返ってきません(varChildId指定してもです)
    こちらではaccValueではなくaccNameに入っています
    遅ればせながらVS2005Exp SP2 / Windows7 HomePremium SP1 / .net Framework4.7.2です
    何でこんなに動作が違うのでしょう…

    >>自分は MSAA か UI Automation でアクセスするようにしています。

    UI AutomationってWPF用ですよね
    MSAAを調べようとしても古すぎるのかさっぱり出てこないし…
引用返信 削除キー/
■33990 / inTopicNo.7)  Re[6]: エクスプローラーのポインタ下のアイテムの取得
□投稿者/ 魔界の仮面弁士 大御所(1148回)-(2018/09/21(Fri) 22:40:10)
  • アイコン2018/09/21(Fri) 23:04:41 編集(投稿者)

    No33989に返信(猫まっしぐらさんの記事)
    > 相変わらずデスクトップからしか返ってきません(varChildId指定してもです)
    ヒットテストで、どの階層のオブジェクトが取得されていますか?

    > こちらではaccValueではなくaccNameに入っています
    取得したオブジェクトが ListViewSubItem 相当の階層の場合は .accValue 、
    ListViewItem 相当の場合は、.accName(varChildId) で得られるかと思います。

    UIAutomation の場合は Value Control Pattern で得られるかと。


    > 遅ればせながらVS2005Exp SP2 / Windows7 HomePremium SP1 / .net Framework4.7.2です
    > 何でこんなに動作が違うのでしょう…
    inspect.exe からは拾えていますか?

    Windows SDK をインストールされている場合には、
     C:\Program Files (x86)\Windows Kits\{バージョン}\bin\x64\inspect.exe
    などにあるはずです。Win9x などの、より古い OS で検証したいような場合には、
     https://www.ka-net.org/blog/?p=1131
    などから以前のバージョンを入手することもできますが…。


    > UI AutomationってWPF用ですよね
    操作する側、つまりプログラムからの呼び出しという意味であるなら、
    .NET Framewrok 版だけではなく、COM 版も提供されていますので、
    VB6 や Excel VBA などからも利用できます。
    https://www.ka-net.org/blog/?p=4628

    操作される側、今回でいうところのエクスプローラーなどの話だとしたら、
    それもやはり WPF 専用という訳ではありません。
    WPF 以外のフレームワークで作られたアプリケーションを対象にする場合も、
    UI オートメーションプロバイダーが提供されているならば取得できます。
    (動作については、各アプリの UI Automation プロバイダーの実装に依存)
    https://docs.microsoft.com/ja-jp/dotnet/framework/ui-automation/ui-automation-and-microsoft-active-accessibility
    https://blogs.msdn.microsoft.com/japan_platform_sdkwindows_sdk_support_team_blog/2011/05/26/ui-automation/

    ちなみに Google Chrome の場合は、HTML コンテンツのオブジェクトを取得するために
    「chrome://accessibility/」で Internal オプションを有効化する必要があります。


    > MSAAを調べようとしても古すぎるのかさっぱり出てこないし…
    最近だと、‘Multi-sample AntiAliasing’の方の MSAA がヒットしちゃうんですよね。
    ‘Microsoft Active Accessibility’の方の MSAA だと、情報としてはこのあたり。

    https://msdn.microsoft.com/ja-jp/library/cc401822.aspx
    https://msdn.microsoft.com/ja-jp/library/cc421916.aspx

    日本語で書かれた MSAAv2.doc ドキュメントのダウンロードサイトは閉鎖されて
    いるようなので、キャッシュサイトから。
    https://web.archive.org/web/20111219235214/download.microsoft.com/download/D/A/1/DA18D61C-F61A-473A-875D-E8D690CD1D41/MSAAv2.doc
    https://web.archive.org/web/20060504074150/www.microsoft.com/japan/msdn/accessibility/msaa/default.asp
引用返信 削除キー/
■33991 / inTopicNo.8)  Re[7]: エクスプローラーのポインタ下のアイテムの取得
□投稿者/ 猫まっしぐら 一般人(9回)-(2018/09/21(Fri) 23:53:05)
  • アイコンNo33990に返信(魔界の仮面弁士さんの記事)

    > inspect.exe からは拾えていますか?

    すみません、SDKは入れてません
    AccExplorerてのでやってみたらファイルペインは全然取れませんでした

    >>UI AutomationってWPF用ですよね
    いえ、Imports System.Windows.Automationしようとしたらそんなのは無いと言われたので…

    すみません、今使ってるのが唯のAccessibilityでその次がActive〜なのかと勘違いしてました(^^;
    で「AA」だとまた何か変わってるのかな?と思っただけでした

    何か間抜けさらしてるだけみたいになってきましたね…
    もう少し勉強しなおします
引用返信 削除キー/
■33992 / inTopicNo.9)  Re[8]: エクスプローラーのポインタ下のアイテムの取得
□投稿者/ 魔界の仮面弁士 大御所(1149回)-(2018/09/22(Sat) 08:46:32)
  • アイコンNo33991に返信(猫まっしぐらさんの記事)
    >>inspect.exe からは拾えていますか?
    > すみません、SDKは入れてません
    Visual Studio なら、Windows SDK も一緒にインストールされるのですが、
    Visual Basic Express だと含まれていないかも知れませんね。

    > AccExplorerてのでやってみたらファイルペインは全然取れませんでした
    Accessible Explorer は、Windows 2000 時代の古いバージョンなので、
    可能であれば、SDK 8.1 や 10 に含まれるツールを試してみてください。

    また、Vista 以降で 96dpi 以外の環境で実行している場合などは、
    スケーリングの問題から、そのままだと座標が正しく取得されないため、
    マニフェスト等で高 DPIの互換設定を調整する必要があります。


    >>> UI AutomationってWPF用ですよね
    > いえ、Imports System.Windows.Automationしようとしたらそんなのは無いと言われたので…
    それは失礼しました。たとえば「System.Windows.Automation 名前空間の AutomationElement クラス」を扱うのであれば、参照設定に UIAutomationClient が必要です。

    クラス名で検索してみると、参照設定に必要なアセンブリ(DLL)を調べることができます。
    https://docs.microsoft.com/ja-jp/dotnet/api/system.windows.automation.automationelement


    > で「AA」だとまた何か変わってるのかな?と思っただけでした
    Active Accessibility では、IAccessible/IAccessible2 を用いますね。
    UIAutomation はその後継なので、今なら後者を用いた方が良いと思います。
引用返信 削除キー/



トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

Mode/  Pass/


- Child Tree -