Windows7のエクスプローラをVBAで操作する方法

このQ&Aのポイント
  • Windows7のエクスプローラをVBAで操作する方法についてアドバイスをお願いします。Excel-VBAで起動しているエクスプローラに対してハンドルを取得してクリックやテキストボックスへの文字セットを行うプログラムを作成しました。しかし、WindowsXPでは問題なく動作していたプログラムがWindows7では正しく動作しません。SendMessageAnyによる値の返り値が1となってしまう現象が発生しています。ハンドルの値はInspect Objectsで確認し、正しく取得できていると思っています。対策方法を教えてください。
  • Windows7のエクスプローラをVBAで操作する方法について教えてください。Excel-VBAで起動しているエクスプローラに対してハンドルを取得し、クリックやテキストボックスへの文字セットを行うプログラムを作成しましたが、Windows7では正しく動作しません。SendMessageAnyの返り値が1となってしまう問題が発生しています。ハンドルの値はInspect Objectsで確認し、正しく取得できていると思います。どのような対策が考えられますか?
  • VBAを使用してWindows7のエクスプローラを操作する方法を教えてください。Excel-VBAで起動したエクスプローラに対してハンドルを取得し、クリックやテキストボックスへの文字セットを行うプログラムを作成しましたが、Windows7では正しく動作しません。SendMessageAnyの戻り値が1となってしまう問題が発生しています。ハンドルの値はInspect Objectsで確認し、正しく取得できていると思います。どのように対策すれば良いでしょうか?
回答を見る
  • ベストアンサー

windows7のエクスプローラをVBAで操作-1

アドバイスをお願いします。 Excel-VBAで起動しているエクスプローラに対してハンドルを取得してクリックしたり、テキストボックスに文字をセットするプログラムを作って動かしています。 WindowsXPのときはできていたのですが、Windows7になったら正しく動作しなくなりました。 下のコードはエクスプローラの現在のフォルダパスが表示されるところに(添付ファイル参照)文字を入れるものです。 最後のSendMessageAnyで1が返ってしまいます。何が考えられますでしょうか。どう対策したらいいでしょうか。 なおハンドルの値はSDKのInspect Objectsで確認していますので、正しく取得できていると思っています。 よろしくお願いします。 Declare Function FindWindow Lib "user32" Alias "FindWindowA" _ (ByVal lpClassName As Any, ByVal lpWindowName As Any) As Long Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" ( _ ByVal hwndParent As Long, _ ByVal hwndChildAfter As Long, _ ByVal lpClassName As String, _ ByVal lpWindowName As String) As Long Declare Function SendMessageAny Lib "user32.dll" _ Alias "SendMessageA" _ (ByVal hwnd As Long, _ ByVal MSG As Long, _ ByVal wParam As Long, _ ByVal lParam As Any) As Long Const WM_SETTEXT = &HC Private hwnd As Long Private FOLDER As String Sub Put_folder_name1() hwnd = FindWindow("CabinetWClass", vbNullString) hwnd = FindWindowEx(hwnd, 0, "WorkerW", vbNullString) hwnd = FindWindowEx(hwnd, 0, "ReBarWindow32", vbNullString) hwnd = FindWindowEx(hwnd, 0, "Address Band Root", vbNullString) hwnd = FindWindowEx(hwnd, 0, "msctls_progress32", vbNullString) hwnd = FindWindowEx(hwnd, 0, "ComboBoxEx32", vbNullString) hwnd = FindWindowEx(hwnd, 0, "ComboBox", vbNullString) hwnd = FindWindowEx(hwnd, 0, "Edit", vbNullString) FOLDER = "\\xx.xx.xx.xx\test" RC = SendMessageAny(hwnd, WM_SETTEXT, 0, ByVal FOLDER) end sub

質問者が選んだベストアンサー

  • ベストアンサー
  • kumatti1
  • ベストアンサー率60% (73/121)
回答No.2

いや、アドレスバーは ToolbarWindow32 です。 (ちなみに Accessible Explorer で確認しました) (取り合えず)C++で確認したところ、BM_CLICKでは無理でWM_LBUTTONDOWNなら反応しますが、座標の指定が面倒ですので 子要素のIAccessibleを取得してクリックさせるとか。 ただ、そんな事をしなくとも起動済みのExplorerが対象なら ShellWindows Collectionで列挙してnavigateメソッドで遷移させればいいのでは。 http://www.moug.net/faq/viewtopic.php?t=68947 (fullnameかtypename等でIEを除外する処理必要)

kootsuki4
質問者

お礼

kumatti1さん >ShellWindows Collectionで列挙してnavigateメソッドで遷移 うまくいきました。ありがとうございました。 ただ、先があって検索文字列をセットして検索させたいのです。 検索させた後の結果の取り出し部分はできています。 検索文字列セット部分の質問はVisualBasicのカテゴリにて登録しました。(「windows7のエクスプローラをVBAで操作-3」 URL:http://oshiete.goo.ne.jp/qa/8595559.html) 引き続きアドバイス戴けたら有難いです。 よろしくお願いします。

その他の回答 (1)

  • kumatti1
  • ベストアンサー率60% (73/121)
回答No.1

後続の質問で何でそんな事がしたいのか謎だったのですが、ここで繋がりました。 私も今調べて知ったのですが、デフォルトでは ComboBoxEx32 は非表示になってますね。 エクスプローラのアドレスバーをクリックすると入力が可能になると。 でも、パスを指定して開くのならば CreateObject("Shell.Application").Explore "C:\" とかでいいのではと。

kootsuki4
質問者

補足

kumatti1さん 回答ありがとうございました。 非表示という状態があるのですね。知りませんでした。 > エクスプローラのアドレスバーをクリックすると "msctls_progress32"のハンドルでSendMessage(hwnd, BM_CLICK, 0, 0)を すればいいのですかね? 今、デバッグできる環境でないので明日デバッグしてみます。   (パスを指定して開くのは用途が違っていましたので、こっちの線で進めます) あと「windows7のエクスプローラをVBAで操作-2」の方の回答もありがとうございました。 やっぱ、IAccessibleですか。勉強してみます。

関連するQ&A

  • windows7のエクスプローラをVBAで操作-2

    アドバイスをお願いします。 Excel-VBAで起動しているエクスプローラに対してハンドルを取得してクリックしたり、テキストボックスに文字をセットするプログラムを作って動かしています。 WindowsXPのときはできていたのですが、Windows7になったら正しく動作しなくなりました。 下のコードはエクスプローラのフォルダパスの右のボタン(添付ファイル参照)をクリックすべく、コーディングしたものです。 最後のSendMessage(hwnd, BM_CLICK, 0, 0) でクリックしたいのですが、その前にボタンのハンドルが取得できません。SDKのInspect Objectsで調べると、このボタンはClass="ToolbarWindow32"でName="前の場所"ですが、NativeWindowHandleが表示されず、Legacy.IAccessible.ChildID=1となっています。 このようなウィンドゥは別のやり方(IAccessible?)でないとクリックできないように感じていますが如何せん知識がありません。 どうしたらできるか、アドバイスよろしくお願いします。 Declare Function FindWindow Lib "user32" Alias "FindWindowA" _ (ByVal lpClassName As Any, ByVal lpWindowName As Any) As Long Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" ( _ ByVal hwndParent As Long, _ ByVal hwndChildAfter As Long, _ ByVal lpClassName As String, _ ByVal lpWindowName As String) As Long Declare Function SendMessage Lib "user32" Alias "SendMessageA" _ (ByVal hwnd As Long, ByVal MSG As Long, ByVal wParam As Long, lParam As Any) As Long Const BM_CLICK = &HF5 Private hwnd As Long Sub Click_button() hwnd = FindWindow("CabinetWClass", vbNullString) hwnd = FindWindowEx(hwnd, 0, "WorkerW", vbNullString) hwnd = FindWindowEx(hwnd, 0, "ReBarWindow32", vbNullString) hwnd = FindWindowEx(hwnd, 0, "Address Band Root", vbNullString) hwnd = FindWindowEx(hwnd, 0, "msctls_progress32", vbNullString) hwnd = FindWindowEx(hwnd, 0, "ToolbarWindow32", vbNullString) ' この次が分からない。 RC = SendMessage(hwnd, BM_CLICK, 0, 0) end sub

  • windows7のエクスプローラをVBAで操作-3

    アドバイスをお願いします。 Excel-VBAで起動しているエクスプローラに対してハンドルを取得してクリックしたり、テキストボックスに文字をセットするプログラムを作って動かしています。 WindowsXPのときはできていたのですが、Windows7になったらエクスプローラが変わったため正しく動作しなくなりました。 やりたいのはエクスプローラに検索文字列(添付ファイル参照)をセットして検索をさせたいのです。 「windows7のエクスプローラをVBAで操作-1」「windows7のエクスプローラをVBAで操作-2」のタイトルで質問させていただき、下のコードを考えましたが、★のところでハンドルが返らず0でした。InspectObjectsで見ると「読み込み専用」と。これが原因ですか?どうしたらいいのだろう・・・。 またこのハンドルを取得して、AccessibleObjectFromWindowでIAccessible を取り出して、accDoDefaultActionしたいのですが、UUIDの値が分かりません。OLEViewで見たのですがExplorer関連がいくつかあり(添付ファイル参照)どれを使っていいものやら。ボタンクリックの後に文字列セットがあるのですが、まだたどり着けず。 IAccessible初心者です。 質問ばかりで済みませんがコーディングのアドバイスお願いします。 Option Explicit Declare Function FindWindow Lib "user32" Alias "FindWindowA" _ (ByVal lpClassName As Any, ByVal lpWindowName As Any) As Long Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" ( _ ByVal hwndParent As Long, _ ByVal hwndChildAfter As Long, _ ByVal lpClassName As String, _ ByVal lpWindowName As String) As Long Private Declare Function AccessibleObjectFromWindow Lib "oleacc" _ (ByVal hWnd As Long, _ ByVal dwObjectID As Long, _ ByRef riid As Any, _ ByRef ppvObject As Any) As Long Const WM_SETTEXT = &HC '文字列送信 Const BM_CLICK = &HF5 'クリック Const OBJID_CLIENT As Integer = &HFFFFFFFC Private Type UUID Data1 As Long Data2 As Integer Data3 As Integer Data4(7) As Byte End Type Private IID_IAccessible As UUID Private oShell Private ie Private hWnd As Long Private SearchBoxハンドル As Long Private Search_Folder As String Private RC As Long 'Private objAcc As IAccessible Private objAcc As UUID Private varChild As Variant Private cnt Private fullnames As String Sub 検索指定のインプット() Search_Folder = "c:\xxx" Set oShell = CreateObject("Shell.Application") For cnt = oShell.Windows().Count - 1 To 0 Step -1 ' On Error Resume Next Set ie = oShell.Windows().Item(cnt) fullnames = ie.FullName ' On Error GoTo 0 If fullnames = "C:\Windows\Explorer.EXE" Then ie.Navigate (Search_Folder) hWnd = FindWindow("CabinetWClass", vbNullString) hWnd = FindWindowEx(hWnd, 0, "WorkerW", vbNullString) hWnd = FindWindowEx(hWnd, 0, "ReBarWindow32", vbNullString) hWnd = FindWindowEx(hWnd, 0, "UniversalSearchBand", vbNullString) hWnd = FindWindowEx(hWnd, 0, "Search Box", vbNullString) hWnd = FindWindowEx(hWnd, 0, "SearchEditBoxWrapperClass", vbNullString) hWnd = FindWindowEx(hWnd, 0, "SearchBox", vbNullString) ' ★--> 0 return SearchBoxハンドル = hWnd hWnd = FindWindowEx(SearchBoxハンドル, 0, "Button", "検索") hWnd = FindWindowEx(SearchBoxハンドル, 0, "SearchEditBox", vbNullString) ' "SearchEditBox" に検索文字列入力の予定だった With IID_IAccessible .Data1 = &H68284FAA .Data2 = &H6A48 .Data3 = &H11D0 .Data4(0) = &H8C .Data4(1) = &H78 .Data4(2) = &H0 .Data4(3) = &HC0 .Data4(4) = &H4F .Data4(5) = &HD9 .Data4(6) = &H18 .Data4(7) = &HB4 End With RC = AccessibleObjectFromWindow(hWnd, OBJID_CLIENT, IID_IAccessible, objAcc) ' 80004005が返る varChild = 2 ' Class="Button", Name="検索"のコントロールをクリックしたいが・・・ ' RC = objAcc.accDoDefaultAction(varChild) ' 書き方が違うみたい・・・ ' Class="SearchEditBox" に検索する文字列を入れたいが・・・ Exit Sub End If Set ie = Nothing Next End Sub

  • APIを使う時は参照設定は不要?

    例えば Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _ (ByVal lpClassName As String, ByVal lpWindowName As String) As Long Sub test() Dim Handle As Long Handle = FindWindow("IEFrame", vbNullString) Debug.Print Handle End Sub と言うコードでウィンドウハンドルを取得する場合、 参照設定のどこにもチェックを入れませんが、なぜ参照設定しなくても使えるのでしょうか? Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _ (ByVal lpClassName As String, ByVal lpWindowName As String) As Long が参照設定の代わりになるのですか?

  • アクセス2010VBA側から他のプログラムを操作

    アクセス2010VBA側から他のプログラムを操作したくて実験しています。 標準モジュールに Public Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" ( _ ByVal hwndParent As Long, _ ByVal hwndChildAfter As Long, _ ByVal lpClassName As String, _ ByVal lpWindowName As String) As Long としておき、 フォーム側に下記のコードを書いています。 Dim tw, tt As Long tw = FindWindow(vbNullString, "電卓") If tw <> 0 Then tt = FindWindowEx(tw, 0&, "5", "") If tt <> 0 Then beep End If FindWindowは取れるのですが、tt = FindWindowExが「0」で取れません。 どこに不具合があるのでしょうか? 将来的に、SendMessage(tw, ~~~)として他プログラムを制御したいのですが、 アクセス2010で可能でしょうか? http://mukkumuku.blogspot.jp/2010/11/office2010-win32api-findwindowfindwindo.html も参考にしましたが、やはり「0」しか返ってきません。

  • Excel VBAでアプリのウィンドウ名取得

    WindowsXP, Excel2007で、ExcelからIE8にキーコードを送りたいです。 ネットで拾った以下のコードにより、 Option Explicit Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" _ (ByVal lpClassName As Any, ByVal lpWindowName As Any) As Long Public Declare Function PostMessage Lib "user32" Alias "PostMessageA" _ (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long Public Declare Function SetForegroundWindow Lib "user32" (ByVal hWnd As Long) As Long Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) Function activate_win(win_name As String) As Long Dim hwindow As Long hwindow = FindWindow(vbNullString, win_name) If hwindow <> 0 Then SetForegroundWindow hwindow activate_win = hwindow End Function Call activate_win("ウィンドウ名") Sendkeys "ABC", True のような形で、メモ帳での動作は確認したのですが、 IEだとウィンドウがアクティブになってくれません。 おそらくウィンドウタイトルを間違えているのだと思われますが、 全角半角などを変えてみたりしても、どう見比べてみても間違いがわかりません。 見た目ではわからない、似た文字だが違うということではないかと思っています。 そこで、開いているアプリのウィンドウ名すべてをメモ帳に書き出すような (あるいは任意のアプリにペーストできるようにするような)コードはないでしょうか? よろしくお願いします

  • WinAPIで電卓をクリック

    現在、WinAPIを勉強しており、練習としてVBAを用いて、電卓アプリのボタンをクリックしようとしています。 キーを送るのではなく、クリックで行いたいたいと 考えています。 ボタンのハンドルを取得するところまではできましたが、sendMessageでクリックできず、EditBoxに数字が 入りません。 どのようにすればよいのかご教授ください。 よろしくお願い致します。 環境: WinXP home、 Excel2002、Win付属アプリの電卓v5.1 ---作成したプログラム---- '標準モジュールの中身 Option Explicit Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long Private Declare Function SetForegroundWindow Lib "user32.dll" (ByVal hWnd As Long) As Long Private Const WM_LBUTTONDOWN = &H201 Private Const WM_LBUTTONUP = &H202 Sub Main() Dim lngWindWnd As Long 'ウィンドウハンドル Dim ret As Long Dim hCalc As Long 'アプリケーションタイトルより、ウィンドウハンドルを得ます lngWindWnd = FindWindow(vbNullString, "電卓") '8ボタンのハンドル(確実に取れていることを確認 hCalc = FindWindowEx(lngWindWnd, 0, "Button", "8") ret = SetForegroundWindow(lngWindWnd) ret = SendMessage(hCalc, WM_LBUTTONDOWN, 0, 0) End Sub

  • VBAでIEの「ファイルのダウンロード」ダイアログを制御

    VBではなくVBAにて、IEの「ファイルのダウンロード」ダイアログを制御したいと思い、過去の同様の質問等を参考に下記のソースを作成して動かしてみましたが、「ファイルのダウンロード」画面で、「保存(S)」ボタンのハンドルを取得するところまではできましたが、sendMessageでクリックができず、次に進むことが出来ませんでした。 手動で「保存(S)」ボタンを押下して、強制的に「名前を付けて保存」画面に遷移させた後プログラムを再開すると、同画面の「保存(S)」ボタンのクリックはできました。 同じロジックで「名前を付けて保存」画面の「保存(S)」は動くのに、「ファイルのダウンロード」画面の「保存(S)」が動かないのはなぜでしょうか。 どなたかおわかりになる方がいらっしゃいましたら、ご回答をお願いします。 ***使用環境*** OS: XP pro IE: 6 OFFICE:2002 ***以下作成したソース(エラー制御は省略)*** Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long Private Declare Function GetDlgCtrlID Lib "user32" (ByVal hwnd As Long) As Long Private Sub Test() Dim ret1 As Long Dim ret2 As Long Const WM_COMMAND As Long = &H111 ret1 = FindWindow("#32770", "ファイルのダウンロード") ret2 = FindWindowEx(ret1, 0, "Button", "保存(&S)") Call SendMessage(ret1, WM_COMMAND, GetDlgCtrlID(ret2), ByVal ret2) ret1 = FindWindow("#32770", "名前を付けて保存") ret2 = FindWindowEx(ret1, 0, "Button", "保存(&S)") Call SendMessage(ret1, WM_COMMAND, GetDlgCtrlID(ret2), ByVal ret2) End Sub ***以上ソース終わり***

  • FindWindowについて

    APIにFindWindowってありますよね。 MSDNには、Windowが見つからなかったらNULLを返すとありますが、以下のソースではNULL(0)が返ってきません。この理由を教えてください。 '宣言部 Declare Function FindWindow Lib "user32" Alias "FindWindowA" _ (ByVal lpClassName As String, ByVal lpWindowName As String) As Long 'コード内 Dim ret As Long   ret = FindWindow(vbNullString, "テスト")   If ret = 0 Then     MsgBox("なし")   End If でret =767863736466669568になる。 ちなみに「テスト」というウィンドウなんてありません。 環境は、XP、VB.net2003です。 困っています。よろしくお願いいたします。

  • VBAでSetTextColorがうまくいかない

    EXCELのVBAでユーザーフォームを使ったグラフィック表示のプログラムを 作っているのですが、SetTextColorでテキスト色の設定をしようと してもうまくいきません。何故か設定しようとする色の値が無視されて 「1304008」が設定されてしまいます。(GetTextColorで確認) そしてそれ以降何を設定してもこの状態のままです。 何か考えられることがありますでしょうか。 下にそのプログラムを示します。 ちなみにSetBKColorやAngleArcなど他のグラフィック命令は問題なく 動いていてSetTextColorだけがうまくいってない状態です。 '------------------------------------------------- ' ユーザーフォーム用プログラム '------------------------------------------------- Private Declare Function GetActiveWindow Lib "user32" () As Long Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" ( _ ByVal hwndParent As Long, _ ByVal hwndChildAfter As Long, _ ByVal lpszClass As String, _ ByVal lpszWindow As String) As Long Private Declare Function GetDC Lib "user32" ( _ ByVal hWnd As Long) As Long Private Declare Function ReleaseDC Lib "user32" ( _ ByVal hWnd As Long, _ ByVal hdc As Long) As Long Private Declare Function SetTextColor Lib "gdi32" _ (ByVal hdc As Long, crColor As Long) As Long Private Declare Function TextOut Lib "gdi32" Alias "TextOutA" _ (ByVal hdc&, ByVal x&, _ ByVal y&, ByVal lpString$, ByVal nCount&) As Long Dim hWnd As Long Dim hdc As Long Public Sub UserForm_Activate() DoEvents hWnd = FindWindowEx(GetActiveWindow, 0, "F3 Server 60000000", "") hdc = GetDC(hWnd) ret = SetTextColor(hdc, RGB(255, 0, 0)) ret = TextOut(hdc, 0, 0, "abc", 3) Call ReleaseDC(hWnd, hdc) End Sub '-------------------------------------------------

  • VB.netでFindWindowExやると・・・9222812402616107008!?

    VB.netでWin32APIのFindWindowExを使うと, たとえばスタートボタンのHWNDを拾ってくるとき, 本当なら65662(6.0のSpy++で確認+10進変換)が返ってきて欲しいんですが, 9222812402616107008という,異常な数が返ってきます. Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, <MarshalAs(UnmanagedType.LPTStr)> ByVal lpsz1 As String, <MarshalAs(UnmanagedType.LPTStr)> ByVal lpsz2 As String) As Long とやってあります. VB6.0のAPIビューワからコピペして,MarshalAsをつけてみました.   (初心者なので,わけわからないまま付けましたけど; hWnd_ShellTrayWnd = FindWindowEx(0,0,"Shell_TrayWnd",vbNullString) hWnd_StartButton = FindWindowEx(hwnd_ShellTrayWnd,0,"Button",vbNullString) とやってるのですが・・・. 不思議なのは,hWnd_ShellTrayWndが9222812402616238204になっているにもかかわらず,次のFindWindowExで,hWnd_StartBtnが9222812402616107008になってるところです・・・. しかも,ありえないクラス名(KeyBoadぐちゃぐちゃ押し)を指定しても,なぜか数が返ってくるんです. FindWindowExを成功させる(きちんとした数を取る)方法,またはFindWindowEx以外でhWndを拾ってくる方法,ありましたら,教えてください.