我们可以使用系统API GetWindowRect,通过窗体句柄来获取指定窗体位于屏幕中的位置及大小。
然而在最新的操作系统中(Vista之后),通过 GetWindowRect 获取的窗体范围数据,其实是包含窗体阴影部分的,因此其数据并不准确,如果涉及窗体坐标操控的话,会导致窗体偏移,无法移动到正确的位置。
如果你不想计算阴影部分,仅仅想获得窗体自身的坐标,就必须要使用 DwmGetWindowAttribute 这个新的API来达成目的。

代码如下:
Declare Function GetWindowRect Lib "user32.dll" (ByVal hwnd As IntPtr, ByRef lpRect As Rect) As Boolean
Declare Function DwmGetWindowAttribute Lib "dwmapi.dll" (ByVal hwnd As IntPtr, ByVal dwAttribute As Integer, ByRef pvAttribute As Rect, ByVal cbAttribute As Integer) As Integer

<Flags()> Public Enum DwmWindowAttribute As UInteger
    DWMWA_NCRENDERING_ENABLED = 1
    DWMWA_NCRENDERING_POLICY
    DWMWA_TRANSITIONS_FORCEDISABLED
    DWMWA_ALLOW_NCPAINT
    DWMWA_CAPTION_BUTTON_BOUNDS
    DWMWA_NONCLIENT_RTL_LAYOUT
    DWMWA_FORCE_ICONIC_REPRESENTATION
    DWMWA_FLIP3D_POLICY
    DWMWA_EXTENDED_FRAME_BOUNDS
    DWMWA_HAS_ICONIC_BITMAP
    DWMWA_DISALLOW_PEEK
    DWMWA_EXCLUDED_FROM_PEEK
    DWMWA_CLOAK
    DWMWA_CLOAKED
    DWMWA_FREEZE_REPRESENTATION
    DWMWA_LAST
End Enum

<Serializable(), StructLayout(LayoutKind.Sequential)> Public Structure Rect
    Public Left As Integer
    Public Top As Integer
    Public Right As Integer
    Public Bottom As Integer

    Public Function ToRectangle() As Rectangle
        Return Rectangle.FromLTRB(Left, Top, Right, Bottom)
    End Function
End Structure


Public Shared Function GetWindowRectangle(ByVal handle As IntPtr) As Rectangle
    Dim rect As New Rect()

    If Environment.OSVersion.Version.Major >= 6 Then
        Dim size As Integer = Marshal.SizeOf(GetType(Rect))
        DwmGetWindowAttribute(handle, DwmWindowAttribute.DWMWA_EXTENDED_FRAME_BOUNDS, rect, size)
    End If

    If Environment.OSVersion.Version.Major < 6 OrElse rect.ToRectangle().Width = 0 Then
        GetWindowRect(handle, rect)
    End If

    Return rect.ToRectangle()
End Function
Environment.OSVersion.Version.Major 用于判断操作系统版本,低于Vista的系统是没有 DwmGetWindowAttribute 这个API的,可以直接用 GetWindowRect 获取窗体坐标数据。


参考来源
https://stackoverflow.com/questions/38685405/dwmgetwindowattribute-returns-0-with-pinvoke