2

我正在尝试编写一个锁定表单位置的代码。

我添加了一个布尔属性,当 True 时表单位置将被锁定,当 False 时表单应返回正常状态。

public class blahblah blah
    Inherits NativeWindow
    Implements IDisposable

Public Property LockPosition As Boolean = False

Private WithEvents form As Form = Nothing

Public Sub New(ByVal form As Form)
    Me.form = form
End Sub

Private Sub OnHandleCreated() _
Handles form.HandleCreated

    Me.AssignHandle(Me.form.Handle)

End Sub

Private Sub OnHandleDestroyed() _
Handles form.HandleDestroyed

    Me.ReleaseHandle()

End Sub

Protected Overrides Sub WndProc(ByRef m As Message)

    If Me.LockPosition Then

        Select Case m.Msg

            Case &HA1
                ' Cancels any attempt to drag the window by it's caption.
                If m.WParam.ToInt32 = &H2 Then Return

            Case &H112
                ' Cancels any clicks on the Move system menu item.
                If (m.WParam.ToInt32 And &HFFF0) = &HF010& Then Return

        End Select

    End If

    ' Return control to base message handler.
    MyBase.WndProc(m)

End Sub

Private disposedValue As Boolean ' To detect redundant calls

' IDisposable
Protected Overridable Sub Dispose(disposing As Boolean)
    If Not Me.disposedValue Then
        If disposing Then


            Me.LockPosition = False


        End If
    End If
    Me.disposedValue = True
End Sub

Public Sub Dispose() Implements IDisposable.Dispose
    Dispose(True)
    GC.SuppressFinalize(Me)
End Sub

end class

上面的代码在我第一次实例化类时工作,当我处理类并再次为新表单实例化它时出现问题,我不知道问题是属性,分配的句柄还是windows 消息,但是当我尝试将 LockPosition 属性设置为 True 以用于另一个表单时,它不会锁定任何内容,这就是我使用它的方式:

编辑:

我发现在 New 构造函数中传递的表单无关紧要,问题是它只有在对象在任何过程之外实例化时才有效!

...所以这将起作用,表单将被锁定:

Public Class Form1

    Private _formdock As New FormDock(Me) With {.LockPosition = True}

    Private Shadows Sub Shown() Handles MyBase.Shown
        _formdock.Dock(FormDock.DockPosition.WorkingArea_BottomRight)
    End Sub

End Class

...但是这个 else 不起作用,表格不再被锁定!

Public Class Form1

    Private Shadows Sub Shown() Handles MyBase.Shown
        Dim _formdock As New FormDock(Me) With {.LockPosition = True}
        _formdock.Dock(FormDock.DockPosition.WorkingArea_BottomRight)
    End Sub

End Class

那么为什么会发生这种情况以及我该如何解决呢?


这是完整的课程:

' [ Form Dock ]
'
' // By Elektro H@cker

#Region " Usage Examples "

' Dim _formdock As New FormDock(Me) With {.LockPosition = True}
'
' Private Shadows Sub shown() Handles MyBase.Shown
'
'    _formdock.Dock(FormDock.DockPosition.WorkingArea_BottomRight)
'
' End Sub

#End Region

#Region " Form Dock "

Public Class FormDock
    Inherits NativeWindow
    Implements IDisposable

#Region " Variables, Properties and Enumerations "

    ''' <summary>
    ''' While the property still Enabled it will locks the formulary position.
    ''' </summary>
    Public Property LockPosition As Boolean = False

    ''' <summary>
    ''' Stores the formulary to Dock.
    ''' </summary>
    Private WithEvents form As Form = Nothing

    ''' <summary>
    ''' Stores the size of the formulary to Dock.
    ''' </summary>
    Private UI_Size As Size = Nothing

    ''' <summary>
    ''' Stores the Dock positions.
    ''' </summary>
    Private Dock_Positions As Dictionary(Of DockPosition, Point)

    ''' <summary>
    ''' Dock Positions.
    ''' </summary>
    Public Enum DockPosition As Short
        Bounds_BottomLeft = 1
        Bounds_BottomRight = 2
        Bounds_TopLeft = 3
        Bounds_TopRight = 4
        WorkingArea_BottomLeft = 5
        WorkingArea_BottomRight = 6
        WorkingArea_TopLeft = 7
        WorkingArea_TopRight = 8
    End Enum

#End Region

#Region " New Constructor "

    Public Sub New(ByVal form As Form)

        Me.form = form

    End Sub

#End Region

#Region " Public Procedures "

    ''' <summary>
    ''' Docks the form.
    ''' </summary>
    Public Sub Dock(ByVal Position As DockPosition)

        If Dock_Positions Is Nothing Then
            Renew_Positions(form)
        End If

        form.Location = Dock_Positions(Position)

    End Sub

#End Region

#Region " Miscellaneous Procedures "

    ''' <summary>
    ''' Renews the Dock positions according to the the current form Size.
    ''' </summary>
    Private Sub Renew_Positions(ByVal form As Form)

        UI_Size = form.Size

        Dock_Positions = New Dictionary(Of DockPosition, Point) _
        From {
                 {DockPosition.Bounds_BottomLeft,
                               New Point(Screen.PrimaryScreen.Bounds.X,
                                         Screen.PrimaryScreen.Bounds.Height - UI_Size.Height)},
                 {DockPosition.Bounds_BottomRight,
                           New Point(Screen.PrimaryScreen.Bounds.Width - UI_Size.Width,
                                     Screen.PrimaryScreen.Bounds.Height - UI_Size.Height)},
                 {DockPosition.Bounds_TopLeft,
                               New Point(Screen.PrimaryScreen.Bounds.X,
                                         Screen.PrimaryScreen.Bounds.Y)},
                 {DockPosition.Bounds_TopRight,
                               New Point(Screen.PrimaryScreen.Bounds.Width - UI_Size.Width,
                                         Screen.PrimaryScreen.Bounds.Y)},
                 {DockPosition.WorkingArea_BottomLeft,
                               New Point(Screen.PrimaryScreen.WorkingArea.X,
                                         Screen.PrimaryScreen.WorkingArea.Height - UI_Size.Height)},
                 {DockPosition.WorkingArea_BottomRight,
                               New Point(Screen.PrimaryScreen.WorkingArea.Width - UI_Size.Width,
                                         Screen.PrimaryScreen.WorkingArea.Height - UI_Size.Height)},
                 {DockPosition.WorkingArea_TopLeft,
                               New Point(Screen.PrimaryScreen.WorkingArea.X,
                                         Screen.PrimaryScreen.WorkingArea.Y)},
                 {DockPosition.WorkingArea_TopRight,
                               New Point(Screen.PrimaryScreen.WorkingArea.Width - UI_Size.Width,
                                         Screen.PrimaryScreen.WorkingArea.Y)}
            }

    End Sub

#End Region

#Region " Form EventHandlers "

    ''' <summary>
    ''' Renews the Dock positions according to the the current form Size,
    ''' when Form is Shown.
    ''' </summary>
    Private Sub OnShown() _
    Handles form.Shown

        If Not UI_Size.Equals(Me.form.Size) Then
            Renew_Positions(Me.form)
        End If

    End Sub

    ''' <summary>
    ''' Renews the Dock positions according to the the current form Size,
    ''' When Form is resized.
    ''' </summary>
    Private Sub OnResizeEnd() _
    Handles form.ResizeEnd

        If Not UI_Size.Equals(Me.form.Size) Then
            Renew_Positions(Me.form)
        End If

    End Sub

    ''' <summary>
    ''' OnHandleCreated
    ''' Assign the handle of this NativeWindow to the form handle,
    ''' necessary to override WndProc.
    ''' </summary>
    Private Sub OnHandleCreated() _
    Handles form.HandleCreated

        Me.AssignHandle(Me.form.Handle)

    End Sub

    ''' <summary>
    ''' Releases the Handle.
    ''' </summary>
    Private Sub OnHandleDestroyed() _
    Handles form.HandleDestroyed

        Me.ReleaseHandle()

    End Sub

#End Region

#Region " Windows Messages "

    ''' <summary>
    ''' WndProc Message Interception.
    ''' </summary>
    Protected Overrides Sub WndProc(ByRef m As Message)

        If Me.LockPosition Then

            Select Case m.Msg

                Case &HA1
                    ' Cancels any attempt to drag the window by it's caption.
                    If m.WParam.ToInt32 = &H2 Then Return

                Case &H112
                    ' Cancels any clicks on the Move system menu item.
                    If (m.WParam.ToInt32 And &HFFF0) = &HF010& Then Return

            End Select

        End If

        ' Return control to base message handler.
        MyBase.WndProc(m)

    End Sub

#End Region

#Region "IDisposable Support"

    Private disposedValue As Boolean ' To detect redundant calls

    ' IDisposable
    Protected Overridable Sub Dispose(disposing As Boolean)
        If Not Me.disposedValue Then
            If disposing Then
                Me.LockPosition = False
            End If

            ' TODO: free unmanaged resources (unmanaged objects) and override Finalize() below.
            ' TODO: set large fields to null.
        End If
        Me.disposedValue = True
    End Sub

    Public Sub Dispose() Implements IDisposable.Dispose
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub

#End Region

End Class

#End Region
4

1 回答 1

0

工作代码:

' [ Form Docking ]
'
' // By Elektro H@cker

#Region " Usage Examples "

' Private _FormDocking As New FormDocking(Me) With {.LockPosition = True}
'
' Private Shadows Sub Shown() Handles MyBase.Shown
'
'   _FormDocking.Dock(FormDocking.DockPosition.WorkingArea_BottomRight)
'
' End Sub

#End Region

#Region " Form Docking "

Public Class FormDocking
    Inherits NativeWindow
    Implements IDisposable

#Region " Variables, Properties and Enumerations "

    ''' <summary>
    ''' While the property still Enabled it will locks the formulary position.
    ''' </summary>
    Public Property LockPosition As Boolean = False

    ''' <summary>
    ''' Stores the formulary to Dock.
    ''' </summary>
    Private WithEvents form As Form = Nothing

    ''' <summary>
    ''' Stores the size of the formulary to Dock.
    ''' </summary>
    Private UI_Size As Size = Nothing

    ''' <summary>
    ''' Stores the Dock positions.
    ''' </summary>
    Private Positions As Dictionary(Of DockPosition, Point)

    ''' <summary>
    ''' Dock Positions.
    ''' </summary>
    Public Enum DockPosition As Short
        Center_Screen = 0
        Bounds_BottomLeft = 1
        Bounds_BottomRight = 2
        Bounds_TopLeft = 3
        Bounds_TopRight = 4
        WorkingArea_BottomLeft = 5
        WorkingArea_BottomRight = 6
        WorkingArea_TopLeft = 7
        WorkingArea_TopRight = 8
    End Enum

#End Region

#Region " Constructor "

    Public Sub New(ByVal form As Form)

        Me.form = form
        SetHandle()

    End Sub

#End Region

#Region " Public Methods "

    ''' <summary>
    ''' Docks the form.
    ''' </summary>
    Public Sub Dock(ByVal Position As DockPosition)

        DisposedCheck()

        If Positions Is Nothing Then
            Renew_Positions(form)
        End If

        form.Location = Positions(Position)

    End Sub

#End Region

#Region " Miscellaneous Methods "

    ''' <summary>
    ''' Renews the Dock positions according to the the current form Size.
    ''' </summary>
    Private Sub Renew_Positions(ByVal form As Form)

        UI_Size = form.Size

        Positions = New Dictionary(Of DockPosition, Point) _
        From {
                 {DockPosition.Center_Screen,
                               New Point((Screen.PrimaryScreen.Bounds.Width - UI_Size.Width) \ 2,
                                         (Screen.PrimaryScreen.Bounds.Height - UI_Size.Height) \ 2)},
                 {DockPosition.Bounds_BottomLeft,
                               New Point(Screen.PrimaryScreen.Bounds.X,
                                         Screen.PrimaryScreen.Bounds.Height - UI_Size.Height)},
                 {DockPosition.Bounds_BottomRight,
                           New Point(Screen.PrimaryScreen.Bounds.Width - UI_Size.Width,
                                     Screen.PrimaryScreen.Bounds.Height - UI_Size.Height)},
                 {DockPosition.Bounds_TopLeft,
                               New Point(Screen.PrimaryScreen.Bounds.X,
                                         Screen.PrimaryScreen.Bounds.Y)},
                 {DockPosition.Bounds_TopRight,
                               New Point(Screen.PrimaryScreen.Bounds.Width - UI_Size.Width,
                                         Screen.PrimaryScreen.Bounds.Y)},
                 {DockPosition.WorkingArea_BottomLeft,
                               New Point(Screen.PrimaryScreen.WorkingArea.X,
                                         Screen.PrimaryScreen.WorkingArea.Height - UI_Size.Height)},
                 {DockPosition.WorkingArea_BottomRight,
                               New Point(Screen.PrimaryScreen.WorkingArea.Width - UI_Size.Width,
                                         Screen.PrimaryScreen.WorkingArea.Height - UI_Size.Height)},
                 {DockPosition.WorkingArea_TopLeft,
                               New Point(Screen.PrimaryScreen.WorkingArea.X,
                                         Screen.PrimaryScreen.WorkingArea.Y)},
                 {DockPosition.WorkingArea_TopRight,
                               New Point(Screen.PrimaryScreen.WorkingArea.Width - UI_Size.Width,
                                         Screen.PrimaryScreen.WorkingArea.Y)}
            }

    End Sub

#End Region

#Region " Event Handlers "

    ''' <summary>
    ''' Renews the Dock positions according to the the current form Size,
    ''' when Form is Shown.
    ''' </summary>
    Private Sub OnShown() _
    Handles form.Shown

        If Not UI_Size.Equals(Me.form.Size) Then
            Renew_Positions(Me.form)
        End If

    End Sub

    ''' <summary>
    ''' Renews the Dock positions according to the the current form Size,
    ''' When Form is resized.
    ''' </summary>
    Private Sub OnResizeEnd() _
    Handles form.ResizeEnd

        If Not UI_Size.Equals(Me.form.Size) Then
            Renew_Positions(Me.form)
        End If

    End Sub

    ''' <summary>
    ''' SetHandle
    ''' Assign the handle of the target form to this NativeWindow,
    ''' necessary to override WndProc.
    ''' </summary>
    Private Sub SetHandle() Handles _
        form.HandleCreated,
        form.Load,
        form.Shown

        Try
            If Not Me.Handle.Equals(Me.form.Handle) Then
                Me.AssignHandle(Me.form.Handle)
            End If
        Catch ex As InvalidOperationException
        End Try

    End Sub

    ''' <summary>
    ''' Releases the Handle.
    ''' </summary>
    Private Sub OnHandleDestroyed() _
    Handles form.HandleDestroyed

        Me.ReleaseHandle()

    End Sub

#End Region

#Region " Windows Messages "

    ''' <summary>
    ''' WndProc Message Interception.
    ''' </summary>
    Protected Overrides Sub WndProc(ByRef m As Message)

        If Me.LockPosition Then

            Select Case m.Msg

                Case &HA1
                    ' Cancels any attempt to drag the window by it's caption.
                    If m.WParam.ToInt32 = &H2 Then Return

                Case &H112
                    ' Cancels any clicks on the Move system menu item.
                    If (m.WParam.ToInt32 And &HFFF0) = &HF010& Then Return

            End Select

        End If

        ' Return control to base message handler.
        MyBase.WndProc(m)

    End Sub

#End Region

#Region " IDisposable "

    ''' <summary>
    ''' To detect redundant calls when disposing.
    ''' </summary>
    Private IsDisposed As Boolean = False

    ''' <summary>
    ''' Prevents calls to methods after disposing.
    ''' </summary>
    Private Sub DisposedCheck()
        If Me.IsDisposed Then
            Throw New ObjectDisposedException(Me.GetType().FullName)
        End If
    End Sub

    ''' <summary>
    ''' Disposes the objects generated by this instance.
    ''' </summary>
    Public Sub Dispose() Implements IDisposable.Dispose
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub

    ' IDisposable
    Protected Overridable Sub Dispose(IsDisposing As Boolean)

        If Not Me.IsDisposed Then

            If IsDisposing Then
            Me.LockPosition = False
            Me.form = Nothing
            Me.ReleaseHandle()
            Me.DestroyHandle()
            End If

        End If

        Me.IsDisposed = True

    End Sub

#End Region

End Class

#End Region
于 2013-11-21T14:37:48.717 回答