| もっとシンプルでフォーカスあてただけでも全部表示されるっぽい
その場合簡単になるのでこちらで
モジュール OpenFileDialogEx.vb
'----- ここから
Imports System.Runtime.InteropServices
Imports System.Text
Module OpenFileDialogEx
Private Delegate Function WNDENUMPROC(ByVal hWnd As IntPtr, ByVallparam As IntPtr) As Boolean
<DllImport("user32.dll")>
Private Function EnumWindows(lpEnumFunc As WNDENUMPROC, lparam As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
<DllImport("user32.dll")>
Private Function EnumChildWindows(ByVal hwndParent As Integer, ByVal lpEnumFunc As WNDENUMPROC, ByVal lParam As Integer) As Integer
End Function
<DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)>
Private Function GetWindowText(hWnd As IntPtr, lpString As StringBuilder, nMaxCount As Integer) As Integer
End Function
<DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)>
Private Function GetWindowTextLength(hWnd As IntPtr) As Integer
End Function
<DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)>
Private Function GetClassName(hWnd As IntPtr, lpClassName As StringBuilder, nMaxCount As Integer) As Integer
End Function
<DllImport("user32.dll")>
Private Function SetForegroundWindow(hWnd As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
Private isCancel As Boolean = False
Private DialogTitle As String = ""
Public Function ShowDialogEx(target As OpenFileDialog) As DialogResult
'ダイアログの非同期取得
isCancel = False
If target.Title.Length = 0 Then
DialogTitle = "開く"
Else
DialogTitle = target.Title
End If
Dim taskShowDialog = Task.Run(
Sub()
Do Until isCancel
Application.DoEvents()
System.Threading.Thread.Sleep(500)
EnumWindows(New WNDENUMPROC(AddressOf EnumWindowsProc), IntPtr.Zero)
Loop
End Sub
)
'ダイアログの表示
Dim result As DialogResult = target.ShowDialog()
'ダイアログの非同期取得を終了させる
Do Until taskShowDialog.IsCompleted
isCancel = True
Application.DoEvents()
System.Threading.Thread.Sleep(250)
Loop
Return result
End Function
Private Function EnumWindowsProc(ByVal hWnd As IntPtr, ByVal lparam As IntPtr) As Boolean
If isCancel = False Then
'ウィンドウのタイトルの長さを取得する
Dim textLen As Integer = GetWindowTextLength(hWnd)
If textLen > 0 Then
'ウィンドウのクラス名を取得する
Dim csb As New StringBuilder(256)
GetClassName(hWnd, csb, csb.Capacity)
If csb.ToString() = "#32770" Then
'ウィンドウのタイトル名を取得する
Dim tsb As New StringBuilder(textLen + 1)
GetWindowText(hWnd, tsb, tsb.Capacity)
If tsb.ToString() = DialogTitle Then
EnumChildWindows(hWnd, New WNDENUMPROC(AddressOf EnumChildProc), IntPtr.Zero)
End If
End If
End If
End If
'すべてのウィンドウを列挙する
Return True
End Function
Private Function EnumChildProc(ByVal hWnd As IntPtr, ByVal lparam As IntPtr) As Boolean
If isCancel = False Then
'クラス名取得
Dim csb As New StringBuilder(256)
GetClassName(hWnd, csb, csb.Capacity)
If csb.ToString() = "ComboBoxEx32" Then
SetForegroundWindow(hWnd)
isCancel = True
End If
End If
Return True
End Function
End Module
'----- ここまで
|