簡體   English   中英

無法使用 DwmGetWindowAttribute 找到 RECT 大小

[英]Unable to find RECT size with DwmGetWindowAttribute

我試圖找到小時候開始的 cmd.exe window 的大小。 我喜歡使用這個尺寸來相應地調整我的表單大小。 由於某種原因, DwmGetWindowAttribute 返回的大小始終為零,所以我一定是在這里做錯了,但我找不到它。 任何幫助將不勝感激。 親切的問候,埃里克

Imports System.Runtime.InteropServices
Public Class Form1
    Private WithEvents Tmr As New Timer With {.Interval = 100}
    Private Const HWND_BOTTOM As Integer = &H1
    Private WithEvents proc As New Process
    Public Const DWMWA_EXTENDED_FRAME_BOUNDS As Integer = 9
    <DllImport("user32.dll", EntryPoint:="SetParent")>
    Private Shared Function SetParent(ByVal hWndChild As IntPtr, ByVal hWndNewParent As IntPtr) As IntPtr
    End Function
    <DllImport("user32.dll", EntryPoint:="SetWindowPos")>
    Private Shared Function SetWindowPos(ByVal hWnd As IntPtr, ByVal hWndInsertAfter As IntPtr, ByVal X As Integer, ByVal Y As Integer, ByVal cx As Integer, ByVal cy As Integer, ByVal uFlags As UInteger) As <MarshalAs(UnmanagedType.Bool)> Boolean
    End Function
    <DllImport("dwmapi.dll")>
    Shared Function DwmGetWindowAttribute(ByVal hwnd As IntPtr, ByVal dwAttribute As Integer, ByRef pvAttribute As RECT, ByVal cbAttribute As Integer) As Integer
    End Function
    Public Structure RECT
        Public left, top, right, bottom As Integer
    End Structure
    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Me.Text = "My title"
        proc.EnableRaisingEvents = True
        proc.StartInfo.FileName = "cmd"
        proc.Start()
        Tmr.Start()
    End Sub
    Private Sub Tmr_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Tmr.Tick
        If SetParent(proc.MainWindowHandle, Panel1.Handle) <> IntPtr.Zero Then
            Tmr.Stop()
            Dim Width As Integer
            Dim Hight As Integer
            Dim WindowRect As New RECT
            DwmGetWindowAttribute(proc.MainWindowHandle, DWMWA_EXTENDED_FRAME_BOUNDS, WindowRect, Marshal.SizeOf(WindowRect))
            Width = WindowRect.right - WindowRect.left
            Hight = WindowRect.bottom - WindowRect.top
            MessageBox.Show("Hight: " & Hight & " Width: " & Width)
            'Me.Size = New Size(Width, Hight)
            SetWindowPos(proc.MainWindowHandle, New IntPtr(HWND_BOTTOM), 0, 0, Panel1.ClientSize.Width, Panel1.ClientSize.Height, 0)
        End If
    End Sub
    Private Sub Proc_Exited(ByVal sender As Object, ByVal e As System.EventArgs) Handles proc.Exited
        Invoke(Sub() Close())
    End Sub
End Class

在實現了@Jimi 的所有有價值的添加之后,這是有效的代碼:

Imports System.Runtime.InteropServices
Public Class Form1
    Private WithEvents proc As New Process
    Public Const WM_NCLBUTTONDOWN As Long = &HA1
    Public Const SW_SHOWMAXIMIZED As UInt32 = 3
    Public Const WM_CLOSE = &H10
    Public Const DWMWA_EXTENDED_FRAME_BOUNDS As Integer = 9
    'Function to set the parent window
    Private Declare Function SetParent Lib "user32" (ByVal hWndChild As IntPtr, ByVal hWndNewParent As IntPtr) As IntPtr
    'Function to set the child window position
    Private Declare Function SetWindowPos Lib "user32" (ByVal hWnd As IntPtr, ByVal hWndInsertAfter As IntPtr, ByVal X As Integer, ByVal Y As Integer, ByVal cx As Integer, ByVal cy As Integer, ByVal uFlags As UInteger) As <MarshalAs(UnmanagedType.Bool)> Boolean
    'Function to allow the child to be maximized
    Private Declare Function ShowWindow Lib "user32" (ByVal hwnd As IntPtr, ByVal nCmdShow As Int32) As Boolean
    'Function to retrieve the initail child size
    Private Declare Function DwmGetWindowAttribute Lib "dwmapi" (ByVal hwnd As IntPtr, ByVal dwAttribute As Integer, ByRef pvAttribute As RECT, ByVal cbAttribute As Integer) As Integer
    'Function to set focus to the child window
    Private Declare Function SetForegroundWindow Lib "user32" (ByVal hwnd As IntPtr) As Long
    'Function used to set terminate child window
    Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
    'Rectangle size, used later to resize the form
    Public Structure RECT
        Public left, top, right, bottom As Integer
    End Structure
    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Me.Text = "My title"
        proc.EnableRaisingEvents = True
        proc.StartInfo.FileName = "cmd"
        proc.Start()
    End Sub
    Private Sub Tmr_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Shown
        'Wait for 200 ms for the form to load
        proc.WaitForExit(200)
        Dim WindowRect As New RECT
        Dim Width, Hight As Integer
        'Retrieve the initial size of the child window
        DwmGetWindowAttribute(proc.MainWindowHandle, DWMWA_EXTENDED_FRAME_BOUNDS, WindowRect, Marshal.SizeOf(WindowRect))
        Width = WindowRect.right - WindowRect.left
        Hight = WindowRect.bottom - WindowRect.top + 23
        'Set the form size to the initial size of the child window
        Me.Size = New Size(Width, Hight)
        'When the child is started, move the child into the panel and maximize it
        If SetParent(proc.MainWindowHandle, Panel1.Handle) <> IntPtr.Zero Then
            SetWindowPos(proc.MainWindowHandle, IntPtr.Zero, 0, 0, Width, Height, 0)
            ShowWindow(proc.MainWindowHandle, SW_SHOWMAXIMIZED)
        End If
    End Sub
    'Exit form when child terminates
    Private Sub Proc_Exited(ByVal sender As Object, ByVal e As System.EventArgs) Handles proc.Exited
        Invoke(Sub() Close())
    End Sub
    'Set focus on child when the form is activated
    Private Sub Form1_UnFocus(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Activated
        SetForegroundWindow(proc.MainWindowHandle)
    End Sub
    'Set focus on child when the parent titlebar is clicked
    Protected Overrides Sub DefWndProc(ByRef m As System.Windows.Forms.Message)
        If CLng(m.Msg) = WM_NCLBUTTONDOWN Then
            SetForegroundWindow(proc.MainWindowHandle)
        End If
        MyBase.DefWndProc(m)
    End Sub
    'Properly terminate child when the form is closed by the user
    Private Sub Form1_Closed(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Closed
        SendMessage(proc.MainWindowHandle, WM_CLOSE, 0, 0)
    End Sub
End Class

親切的問候,埃里克

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM