c# - 如何正确确定Aero的非客户区大小?

标签 c# .net vb.net aero nonclient-area

当为 COMPILED 应用程序激活 Aero 时,如何使用 VBNET 或 C# 代码正确确定非客户区大小? (是的,此问题仅在运行已编译的应用程序时出现,而不是在从 IDE 启动应用程序时出现)

当我调整表单大小时或执行与表单高度/宽度相关的任何操作时,我从未得到预期的结果。

例如,这是两种形式的简单对接代码的一部分:

VB-NET:

Me.Location = New Point((form1.Location.X + form1.Width), form1.Location.Y)

C#:

this.Location = new Point((form1.Location.X + form1.Width), form1.Location.Y);

举个例子,我将展示我的一个程序。

上面的代码在 Aero 未激活时运行完美:

enter image description here

...但是如果 Aero 被激活,那么结果是这样的:

enter image description here

注意右边的表单是如何位于左边表单的 Non-Client 边框之下的。

...或者这是其他图像,其中左侧表单位于右侧表单的非客户端边框下方:

enter image description here

我的问题是解决这个问题的方法是什么?

UPDATE:

扩展框架解决方案不起作用。

表格 1:

Imports System.Runtime.InteropServices

Public Class Form1
    Public Moving_From_Secondary_Form As Boolean = False

    <DllImport("dwmapi.dll")> _
    Private Shared Function DwmExtendFrameIntoClientArea(ByVal hwnd As IntPtr, ByRef margins As MARGINS) As Integer
    End Function

    <StructLayout(LayoutKind.Sequential)> _
    Public Structure MARGINS
        Public leftWidth As Integer
        Public rightWidth As Integer
        Public topHeight As Integer
        Public bottomHeight As Integer
    End Structure

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Dim margins As New MARGINS()
        margins.leftWidth = -1
        margins.rightWidth = -1
        margins.topHeight = -1
        margins.bottomHeight = -1
        DwmExtendFrameIntoClientArea(Me.Handle, margins)
        Form2.Show()
    End Sub

    Private Sub Form1_Move(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Move
        If Not Moving_From_Secondary_Form Then Form2.Location = New Point(Me.Right, Me.Top)
    End Sub

End Class

表格 2:

Public Class Form2

    Private Sub Form2_Move(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Move
        Form1.Moving_From_Secondary_Form = True
        Form1.Location = New Point(Me.Left - Form1.Width, Me.Top)
        Form1.Moving_From_Secondary_Form = False
    End Sub

End Class

结果:

enter image description here

我还想记住: 此问题仅在运行已编译的应用程序时出现,而不是在从 IDE 启动应用程序时出现

**

UPDATE:

**

测试了 GetWindowRect 解决方案并始终返回 0,对我不起作用,也许我做错了什么:

Imports System.Runtime.InteropServices

Public Class Form1

    Private Declare Function GetWindowRect Lib "user32" (ByVal Handle As IntPtr, Rect As RECT) As Long
    Private Declare Function CopyRect Lib "user32" (DestRect As RECT, SourceRect As RECT) As Long

    <StructLayout(LayoutKind.Sequential)> _
    Structure RECT
        Public Left As Int32
        Public Top As Int32
        Public Right As Int32
        Public Bottom As Int32
    End Structure

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Form2.Show()
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim rectWindow As RECT, rectCopy As RECT

        'Get the bounding rectangle of this window
        GetWindowRect(Me.Handle, rectWindow)
        'Copy the rectangle
        CopyRect(rectCopy, rectWindow)

        MsgBox("This form's width:" & (rectCopy.Right - rectCopy.Left).ToString & " pixels")
        Form2.Location = New Point(rectCopy.Right, rectCopy.Top)
    End Sub

End Class

**

UPDATE:

**

再次尝试GetWindowRect,这次代码写​​对了,但是没有解决问题:

Imports System.Runtime.InteropServices

Public Class Form1
    <StructLayout(LayoutKind.Sequential)> _
    Private Structure RECT
        Public Left As Int32
        Public Top As Int32
        Public Right As Int32
        Public Bottom As Int32
    End Structure

    Private Declare Function GetWindowRect Lib "user32" (ByVal HWND As Integer, ByRef lpRect As RECT) As Integer

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim rc As RECT
        GetWindowRect(MyBase.Handle, rc)
        Dim width As Integer = rc.Right - rc.Left
        Form2.Show()
        Form2.Location = New Point(rc.Right, rc.Top)
    End Sub

End Class

enter image description here

我要记住:这个问题只出现在 win7/Vista 上运行已编译的应用程序时,不会出现在从 IDE 启动应用程序时

最佳答案

虽然我没有亲自测试过,但您可以使用 DwmExtendFrameIntoClientArea 并传递 -1 将框架扩展到客户区。

理论上这应该意味着您指定的大小/位置将包括框架。

C# 签名

[DllImport("dwmapi.dll", PreserveSig = true)]
static extern int DwmExtendFrameIntoClientArea(IntPtr hwnd, ref MARGINS margins);

[DllImport("dwmapi.dll", PreserveSig = false)]
static extern void DwmExtendFrameIntoClientArea(IntPtr hwnd, ref MARGINS margins);

VB.NET 签名:

<DllImport("dwmapi.dll")> _
Private Shared Function DwmExtendFrameIntoClientArea(ByVal hwnd As IntPtr, ByRef margins As MARGINS) As Integer
End Sub

更新

您是否考虑过将表单边框样式设置为无,然后使用按钮来控制关闭/最小化?还有其他选项也可能让您得到结果 - FixedSingleFixedToolWindow

Border Style

更新 2

我设法重现了您的问题并使用以下代码解决了它。调试时窗口位置倾斜,但运行编译后的 exe 时窗口位置正确。

Dim BorderWidth = (Me.Width - Me.ClientSize.Width)
Me.Location = New Point((Form1.Location.X + (Form1.Width + BorderWidth)), Form1.Location.Y)

关于c# - 如何正确确定Aero的非客户区大小?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16111595/

相关文章:

c# - 将安全问题转移到数据访问层

c# - 我可以使用反射在 ASP.NET 中查找 bin/[Configuration] 文件夹而不是 asp 临时文件夹吗

c# - 将图像列表发送到 azure 函数以将图像上传到 .Net 中的 blob

.net - CSS 布局、Vis Studio 2005 和 AJAX 选项卡容器

.net - 如何在配置 Jenkins 作业时排除/忽略项目(Dot Net)

VB.Net 对象超出范围?

c# - Asp.net 比较验证器以验证日期

c# - 控制 ushort 数组中的位

c# - 用户在 GridView.DataBind 调用期间单击会导致 ArgumentException

vb.net - System.Net.IPAddress 返回奇怪的地址