[英]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.