You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用DwmGetWindowAttribute无法获取RECT窗口尺寸问题求助

问题分析与解决

你的代码里DwmGetWindowAttribute返回尺寸始终为0,主要有几个核心原因:

1. 调用时机过早

在SetParent之后立刻调用DwmGetWindowAttribute,此时cmd窗口还未完成DWM相关的初始化流程,导致无法正确读取属性值。

2. 控制台窗口不适合用DWMWA_EXTENDED_FRAME_BOUNDS

cmd属于控制台窗口,这类窗口对DWM属性的支持有限,更可靠的方式是使用GetWindowRect获取窗口整体尺寸,或GetClientRect获取客户区尺寸。

3. 未检查DwmGetWindowAttribute的返回值

该函数返回HRESULT类型值,非0则表示调用失败,你没有对返回结果做判断,无法定位具体失败原因。


修改后的代码示例

以下是调整后的代码,改用GetWindowRect获取尺寸,并增加句柄有效性检查:

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
    <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("user32.dll", EntryPoint:="GetWindowRect")>
    Private Shared Function GetWindowRect(ByVal hWnd As IntPtr, ByRef lpRect As RECT) As <MarshalAs(UnmanagedType.Bool)> Boolean
    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 proc.MainWindowHandle = IntPtr.Zero Then Return ' 确保窗口句柄有效
        If SetParent(proc.MainWindowHandle, Panel1.Handle) <> IntPtr.Zero Then
            Tmr.Stop()
            Dim WindowRect As New RECT
            ' 使用GetWindowRect获取窗口尺寸
            If GetWindowRect(proc.MainWindowHandle, WindowRect) Then
                Dim Width = WindowRect.right - WindowRect.left
                Dim Height = WindowRect.bottom - WindowRect.top
                MessageBox.Show("Height: " & Height & " Width: " & Width)
                'Me.Size = New Size(Width, Height)
                SetWindowPos(proc.MainWindowHandle, New IntPtr(HWND_BOTTOM), 0, 0, Panel1.ClientSize.Width, Panel1.ClientSize.Height, 0)
            Else
                MessageBox.Show("获取窗口尺寸失败")
            End If
        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

额外说明

如果一定要使用DwmGetWindowAttribute,需要做以下调整:

  • 确保系统启用了DWM特效(Windows Vista及以上默认启用,可通过任务管理器确认)
  • 增大Timer的Interval到500ms,给窗口足够时间完成初始化
  • 检查函数返回值,示例代码如下:
    Dim result = DwmGetWindowAttribute(proc.MainWindowHandle, DWMWA_EXTENDED_FRAME_BOUNDS, WindowRect, Marshal.SizeOf(WindowRect))
    If result = 0 Then ' S_OK表示调用成功
        Dim Width = WindowRect.right - WindowRect.left
        Dim Height = WindowRect.bottom - WindowRect.top
        MessageBox.Show("Height: " & Height & " Width: " & Width)
    Else
        MessageBox.Show("DwmGetWindowAttribute调用失败,错误码:" & result.ToString("X"))
    End If
    

内容的提问来源于stack exchange,提问作者Eric van Loon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 17:18:08