VB.NET GetClientRect() ничего не возвращает для дочернего процесса в WinForm

Написание проекта WinForm в VB.NET на VS 2017, и я открываю экземпляр FreeRDP в SplitContainer2.Panel1, Это прекрасно работает, но я бы хотел масштабировать форму, чтобы она изначально соответствовала окну FreeRDP. Для этого мне сначала нужно узнать размер экземпляра FreeRDP.

К сожалению, все мои попытки ничего не дают. Я пытаюсь использовать GetClientRect() из Windows API, но все, что я когда-либо получаю, это 0 (или ничего, я полагаю). Я впервые играю с вызовами API, поэтому не уверен, что делаю неправильно. Я подтвердил, что у меня правильная ручка с перерывом в VS

(Прошу прощения, если эти масштабы плохо. Трудно судить по 4k)

введите описание изображения здесь

по сравнению со Spy++

введите описание изображения здесь

Итак, я подтвердил, что у меня есть правильный дескриптор hWnd, но когда я вызываю GetClientRect()Я ничего не получаю обратно.

Вот соответствующий код:

Dim rdpWnd As New IntPtr
Dim proc As New Process

Private Declare Auto Function GetClientRect Lib "user32.dll" ( _
    ByVal hWnd As IntPtr, ByVal lpRect As RECT) As Boolean

<StructLayout(LayoutKind.Sequential)>
Private Structure RECT
    Private Left As Short
    Private Top As Short
    Private Right As Short
    Private Bottom As Short
End Structure

Private Sub Form_Load( _
    sender As Object, e As EventArgs) Handles MyBase.Load

    Dim startInfo As New ProcessStartInfo With {
        .FileName = """" & appPath & "\console\wfreerdp.exe""",
        .Arguments = "/parent-window:" & SplitContainer2.Panel1.Handle.ToString() & " /t:" & vmId
    }
    proc = Process.Start(startInfo)

    rdpWnd = getWindowHandle(Me.Text, vmId)
End Sub

Private Function getWindowHandle(caption As String, Guid As String) As IntPtr

    Dim hWnd As IntPtr = FindWindow(Nothing, caption)
    If hWnd.Equals(IntPtr.Zero) Then
        Return Nothing
    End If

    .......

    Dim hWndRdp As IntPtr = FindWindowEx(hWndChild4, IntPtr.Zero, Nothing, Guid)
    If hWndRdp.Equals(IntPtr.Zero) Then
        Return Nothing
    End If

    Return hWndRdp
End Function

На данный момент, я смотрю на консольное окно Hyper-V VM в моей форме, но когда я нажимаю на общеизвестную Button1...

Private Sub Button1_MouseClick( _
    sender As Object, e As MouseEventArgs) Handles Button1.MouseClick

    Dim myRect As New RECT
    GetClientRect(rdpWnd, myRect)
    Dim rdpWndWidth As Short = myRect.Right - myRect.Left
    Dim rdpWndHeight As Short = myRect.Bottom - myRect.Top
    MsgBox("Width: " & rdpWndWidth & vbCrLf & 
           "Height: " & rdpWndHeight)
End Sub

MsgBox() возвращает:

введите описание изображения здесь

и переменные в VS:

введите описание изображения здесь

Что я делаю неправильно? Почему я не могу получить размер клиента, когда я ясно вижу, что Spy++ может? Я потратил много часов, пытаясь понять это, и я был бы признателен за помощь в проверке этой вехи. Собираюсь перейти на что-то еще и вернуться позже, если я не смогу получить это в ближайшее время.

1 ответ

Решение

Вы передаете RECT структурировать по значению GetClientRect, Это создает копию структуры. В результате оригинал RECT значение никогда не изменяется при вызове метода, поэтому все его поля будут иметь значения по умолчанию (т. е. ноль).

Измените подпись вашего метода на

Private Declare Auto Function GetClientRect Lib "user32.dll" ( _
    ByVal hWnd As IntPtr, ByRef lpRect As RECT) As Boolean

(Обратите внимание ByRef ключевое слово).

Другие вопросы по тегам