C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[1]: 保存のダイアログボックスの位置を取得


(過去ログ 163 を表示中)

[トピック内 6 記事 (1 - 6 表示)]  << 0 >>

■94283 / inTopicNo.1)  保存のダイアログボックスの位置を取得
  
□投稿者/ うげつ (4回)-(2020/03/30(Mon) 14:30:12)

分類:[VB.NET/VB2005 以降] 

あるソフトから自動で開く「名前を付け保存」等のダイアログボックスがあります。
そこで質問なのですがもし可能であれば、VBからそのダイアログボックス内にある「保存(S)」の位置(XY座標)を取得したく思っています。
開くダイアログボックスの位置、大きさはその都度変わります。

引用返信 編集キー/
■94284 / inTopicNo.2)  Re[1]: 保存のダイアログボックスの位置を取得
□投稿者/ 774RR (778回)-(2020/03/30(Mon) 16:38:09)
取得して何をしたいのか? で話は違うような気がする。具体的には何をするの?
微妙に XY 問題ないしは青年とラクダかも。
引用返信 編集キー/
■94291 / inTopicNo.3)  Re[2]: 保存のダイアログボックスの位置を取得
□投稿者/ うげつ (5回)-(2020/03/31(Tue) 12:26:54)
No94284 (774RR さん) に返信
> 取得して何をしたいのか? で話は違うような気がする。具体的には何をするの?
> 微妙に XY 問題ないしは青年とラクダかも。

先ずは出来るか出来ないか。
それも比較的簡単に。
それによって応用も考えます。

引用返信 編集キー/
■94292 / inTopicNo.4)  Re[3]: 保存のダイアログボックスの位置を取得
□投稿者/ とっちゃん (664回)-(2020/03/31(Tue) 13:14:10)
No94291 (うげつ さん) に返信
> ■No94284 (774RR さん) に返信
>>取得して何をしたいのか? で話は違うような気がする。具体的には何をするの?
>>微妙に XY 問題ないしは青年とラクダかも。
>
> 先ずは出来るか出来ないか。
> それも比較的簡単に。
> それによって応用も考えます。
>
できるかできないかなら、出来ます。
Codeer の Frendly とか実際にやってますし。

比較的簡単か?となると、前提条件があやふやなので何とも言えません。

引用返信 編集キー/
■94294 / inTopicNo.5)  Re[1]: 保存のダイアログボックスの位置を取得
□投稿者/ KOZ (106回)-(2020/03/31(Tue) 17:34:35)
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

引用返信 編集キー/
■94295 / inTopicNo.6)  Re[3]: 保存のダイアログボックスの位置を取得
□投稿者/ Azulean (1137回)-(2020/03/31(Tue) 21:32:07)
No94291 (うげつ さん) に返信
> 先ずは出来るか出来ないか。
> それも比較的簡単に。

考え方が逆に感じられました。
「やりたいことがあって」(目的)、「それを実現する数ある手段の中の 1 つ」について尋ねられています。

今回尋ねられていることは、少し面倒くさいことに類します。
本来やりたかったことが、「保存(S)を押す操作をしたい」であれば、「キー入力を送り込む」という別の手段の方が簡単かもしれません。

このため、応用という話ではなく、やりたいことは何か?という風に目的・背景・理由を尋ねる質問があったわけです。
それでも 1 つの手段にこだわられるのであれば、止める理由はありませんが…。(その場合、手段が目的になってしまっているように感じられます)
引用返信 編集キー/


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

このトピックに書きこむ

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

管理者用

- Child Tree -