3

COMPILED アプリケーションに対して Aero がアクティブ化されているときに、VBNET または C# コードを使用して非クライアント領域のサイズを正しく決定する方法は? (はい、この問題は、IDE からアプリを起動するときではなく、コンパイルされたアプリケーションを実行するときにのみ発生します)

フォームのサイズを変更したり、フォームの高さ/幅に関連する操作を行ったりすると、期待した結果が得られません。

たとえば、これは 2 つの形式の単純なドッキングのコードの一部です。

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 がアクティブ化されていない場合に完全に実行されます。

ここに画像の説明を入力

...しかし、Aero が有効になっている場合は、次のようになります。

ここに画像の説明を入力

右側のフォームが左側のフォームの非クライアント境界線の下にあることに注意してください。

...または、左のフォームが右のフォームの非クライアント境界線の下にある別の画像を次に示します。

ここに画像の説明を入力

私の質問は、これを解決する方法はどれですか?

アップデート:

フレーム ソリューションの拡張が機能していません。

フォーム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

結果:

ここに画像の説明を入力

また、覚えておきたい のは、この問題は、IDE からアプリを起動するときではなく、コンパイルされたアプリケーションを実行するときにのみ発生することです。

**

アップデート:

**

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

**

アップデート:

**

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

ここに画像の説明を入力

注意: この問題は、IDE からアプリを起動するときではなく、win7/Vista でコンパイルされたアプリケーションを実行するときにのみ発生します。

4

3 に答える 3

2

私はこれを個人的にテストしていませんが、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

アップデート

フォームの境界線スタイルをなしに設定し、ボタンを使用して閉じる/最小化を制御することを考えたことはありますか? あなたの後に結果を得るかもしれない他のオプションがあります -FixedSingleそしてFixedToolWindow

ボーダースタイル

更新 2

問題を再現し、次のコードで解決することができました。デバッグ時にウィンドウの位置がずれますが、コンパイルされた exe を実行すると、ウィンドウの位置は正しくなります。

Dim BorderWidth = (Me.Width - Me.ClientSize.Width)
Me.Location = New Point((Form1.Location.X + (Form1.Width + BorderWidth)), Form1.Location.Y)
于 2013-04-23T16:42:22.513 に答える
0

最後に、メイン フォームの右側にセカンダリ フォームをドッキングするためのスニペットを作成しました。これは、Aero が有効になっていて、デバッグからアプリを実行していない場合でも機能します。仮想マシンで AERO を有効にしてアプリをドッキングできるようになりました。 (AERO) Windows :D.

  ' Instructions :
  ' Change Manually the "StartPosition" property of "Form2" to "Manual", don't change it with code.

    Public Moving_From_Secondary_Form As Boolean = False

    ' Move Event Main Form
    Private Sub Form1_Move(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Move
        If Not Moving_From_Secondary_Form Then
            If Debugger.IsAttached Then
                Form2.Location = New Point(Me.Right, Me.Top)
            Else
                Form2.Location = New Point((Me.Location.X + (Me.Width + (Me.Width - Me.ClientSize.Width))), Me.Location.Y)
            End If
        End If
    End Sub

    ' Move Event Secondary Form
    Private Sub Form2_Move(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Move
        Form1.Moving_From_Secondary_Form = True
        If Debugger.IsAttached Then
            Form1.Location = New Point(Me.Left - Form1.Width, Me.Top)
        Else
            Form1.Location = New Point((Me.Location.X - (Form1.Width + (Form1.Width - Form1.ClientSize.Width))), Me.Location.Y)
        End If
        Form1.Moving_From_Secondary_Form = False
    End Sub

...そしてこの機能も:

#Region " Get Non-Client Area Width "

    ' [ Get Non-Client Area Width Function ]
    '
    ' Examples :
    ' MsgBox(Get_NonClientArea_Width(Form1))
    ' Me.Location = New Point((Form1.Location.X + (Form1.Width + Get_NonClientArea_Width(Form1))), Form1.Location.Y) 

    Public Function Get_NonClientArea_Width(ByVal Form Form) As Int32
        Return (Form.Width - Form.ClientSize.Width)
    End Function

#End Region
于 2013-04-27T00:42:36.040 に答える