|
■No94283 (うげつ さん) に返信
> そこで質問なのですがもし可能であれば、VBからそのダイアログボックス内にある「保存(S)」の位置(XY座標)を取得したく思っています。
UIスレッドを複数持てば別ですが、ダイアログということなら、アプリケーションに一つだけと仮定できるので、プロセスを特定できればなんとかなりそうです。
Imports System
Imports System.Linq
Imports System.Diagnostics
Imports System.Runtime.InteropServices
Imports System.Text
Module Program
Private Const USER32 As String = "user32.dll"
Structure RECT
Public Left As Integer, Top As Integer, Right As Integer, Bottom As Integer
End Structure
<DllImport(USER32)>
Private Function GetWindowText(ByVal hwnd As Integer, ByVal lpString As StringBuilder, ByVal cch As Integer) As Integer
End Function
<DllImport(USER32)>
Private Function GetWindowRect(ByVal hWnd As IntPtr, ByRef lpRect As RECT) As Boolean
End Function
<DllImport(USER32)>
Private Function GetWindowThreadProcessId(ByVal hwnd As IntPtr, ByRef lpdwProcessId As Integer) As Integer
End Function
<DllImport(USER32)>
Private Function GetClassName(ByVal hWnd As IntPtr, ByVal lpClassName As StringBuilder, ByVal nMaxCount As Integer) As Integer
End Function
Private Class info
Public pid As Integer
Public Handle As IntPtr = IntPtr.Zero
Public FindText As String
End Class
Private Delegate Function EnumDialogProc(ByVal hWnd As IntPtr, ByVal lParam As info) As Boolean
<DllImport(USER32, SetLastError:=True, CharSet:=CharSet.Auto)>
Private Function EnumWindows(ByVal lpEnumFunc As EnumDialogProc, ByVal lParam As info) As Boolean
End Function
<DllImport(USER32, CharSet:=CharSet.Auto)>
Private Function EnumChildWindows(ByVal hWndParent As IntPtr, ByVal lpEnumFunc As EnumDialogProc, ByVal info As info) As Boolean
End Function
Sub Main()
Dim p As Process = Process.GetProcessesByName("notepad").FirstOrDefault
Dim target As IntPtr = GetSaveButton(p)
If target <> IntPtr.Zero Then
Dim rc As New RECT()
GetWindowRect(target, rc)
MsgBox(String.Format("ターゲットの座標は ({0},{1}) です。", rc.Left, rc.Top))
Else
MsgBox("みつかりませんでした")
End If
End Sub
Private Function GetSaveButton(ByVal p As Process) As IntPtr
Dim info As New info
info.pid = p.Id
info.FindText = "保存(&S)"
EnumWindows(AddressOf EnumDialog, info)
GC.KeepAlive(info)
Return info.Handle
End Function
Private Function EnumDialog(ByVal hwnd As IntPtr, ByVal info As info) As Boolean
Dim sb As New StringBuilder(1024)
Const DialogClass As String = "#32770"
GetClassName(hwnd, sb, sb.Capacity)
If sb.ToString() = DialogClass Then
Dim pid As Integer
GetWindowThreadProcessId(hwnd, pid)
If pid = info.pid Then
If Not EnumChildWindows(hwnd, AddressOf EnumCHildren, info) Then
Return False
End If
End If
End If
Return True
End Function
Private Function EnumCHildren(ByVal hWnd As IntPtr, ByVal info As info) As Boolean
Dim sb As New StringBuilder(1024)
GetWindowText(hWnd, sb, sb.Capacity)
If sb.ToString() = info.FindText Then
info.Handle = hWnd
Return False
End If
Return True
End Function
End Module
|