今XPとVB6でファイル操作のプログラムを書いているのですが
VBからエクスプローラを起動した時にエクスプローラのウィンドウの
ハンドルがなぜか取得できません^^;
CreateProcessでプロセスを作成し、そのプロセスで
EnumWindowsで検索しているのですが、ウィンドウは
作成されているのですが列挙されるプロセスの中に
一致するのがみつからないです。
ためしにエクスプローラではなく、メモ帳でやったところ
うまくいったのですが、エクスプローラウィンドウの場合は
EnumWindowsでは列挙されないのでしょうか?
参考までに以下にソースを記載します。
よろしくおねがいします
Public Declare Function EnumWindows Lib "user32" (ByVal lpEnumFunc As Long, lPalam As Long) As Long
Public Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long
Public m_Handle '取得ハンドル
Public Function EnumWindowsProc(ByVal Handle As Long, ByVal lpParam As Long) As Boolean
Dim m_Thread As Long
Dim m_Process As Long
m_Process = 0
'プロセスIDを取得する
m_Thread = GetWindowThreadProcessId(Handle, m_Process)
If m_Process = lpParam Then
m_Handle = Handle
EnumWindowsProc = False
Exit Function
End If
EnumWindowsProc = True
End Function
-------------------------------------------
一部抜粋
'セキュリティ構造体を初期化
udtProcessAttributes.nLength = Len(udtProcessAttributes)
udtThreadAttributes.nLength = Len(udtThreadAttributes)
sCurrentDri = vbNullString 'カレントディレクトリを指定
udtStartupInfo.cb = Len(udtStartupInfo)
'新しいプロセスのメインウインドウの表示状態を指定
'新しいプロセスの作成
lngResult = CreateProcess(vbNullString, _
"explorer.exe " & sComLine, _
udtProcessAttributes, _
udtThreadAttributes, _
False, _
0, _
ByVal vbNullString, _
sCurrentDri, _
udtStartupInfo, _
udtProcessInformation)
If lngResult <> 0 Then
'対象ウインドウのハンドルを検索
Ret = EnumWindows(AddressOf EnumWindowsProc, udtProcessInformation.dwProcessId)
-------------------以下省略------------------
補足ですが、起動したEXPLORERのウィンドウのプロセスIDを
別の方法で確かめてみたのですが、そのIDはCreateProcessで取得した
IDとは異なっていました。
CreateProcessでexplorerを起動する場合は何か特別な方法が
必要なのでしょうか?
エクスプローラは特殊なものです。
ファイラにもなりうるし、同時にシェルでもあります。
シェルとして起動中ファイラとして起動した場合、
ファイラとして起動したものは、シェルとして起動したエクスプローラに統合されますね?
(タスクマネージャで見ても、常にexplorerは一個以下しかないでしょう?)
ですから、CreateProcessから起動したから、それを操作できるだろうと考えるのは、ちょっとこの場合無理そうです。
> 今XPとVB6でファイル操作のプログラムを書いているのですが
> VBからエクスプローラを起動した時にエクスプローラのウィンドウの
> ハンドルがなぜか取得できません^^;
エクスプローラウインドウのハンドルを得てから、その後、
最終的に何をしたいのかにもよりますが、APIでエクスプローラの
ウィンドウハンドルを取得し、それをAPIで操作する替わりに、
エクスプローラをCreateObjectで起動し、それを操作するという
手法もあります。
# あるいは、CreateObjectで新規に起動するのではなく、
# 起動済みのエクスプローラを、ShellWindowsオブジェクトで
# 列挙して使う事もできます。
たとえば、このような事もできます。
Option Explicit
Private Sub Command1_Click()
Dim obj As Object
Dim fis As Object
Dim sfv As Object
Dim S As String
'エクスプローラを起動し、Cドライブを開く
Set obj = CreateObject("InternetExplorer.Application", "localhost")
obj.Navigate2 "C:\", CVar(&H20)
'画面左上に、画面の3/4の大きさで表示
obj.Left = 0
obj.Top = 0
obj.Width = (Screen.Width / Screen.TwipsPerPixelX) * 0.75
obj.Height = (Screen.Height / Screen.TwipsPerPixelY) * 0.75
obj.ShowBrowserBar "{EFA24E64-B078-11D0-89E4-00C04FC9E26E}", True
obj.Visible = True
Set sfv = obj.document
Set fis = sfv.Application.NameSpace("C:\").Items()
'"C:\Program Files"フォルダを選択させた状態にする
sfv.SelectItem fis.Item("Program Files"), 3&
'"C:\Documents and Settings"にフォーカスをあてる(選択はしない)
sfv.SelectItem fis.Item("Documents and Settings"), 16&
Set fis = Nothing
Set sfv = Nothing
'エクスプローラのウィンドウハンドルを取得
S = Right(String(8, "0") & Hex(obj.hWnd), 8)
'終了処理
S = "エクスプローラ(0x" & S & ")を閉じます。"
If MsgBox(S, vbOKCancel Or vbSystemModal Or vbInformation, "Sample") = vbOK Then
obj.Quit
End If
Set obj = Nothing
End Sub
遅くなってしまいました・・・アセアセ
解答ありがとうございました>たかみちえさん、魔界の仮面弁士さん
ペコリ(o_ _)o))
ツイート | ![]() |