我正在尝试编写一个锁定表单位置的代码。
我添加了一个布尔属性,当 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