I'm trying to write a code which locks the position of a form.
I've added a boolean property, when True then the form position would be locked, when False the form should return to normal state.
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
The code above is working when I instance the class for first time, the problem occurs when I dispose the class and I instance it again for a new Form, I don't know if the problem is the property, the assigned handle, or the windows messages, but when I try to set the LockPosition property to True for another form it does not lock nothing, this is how I'm using it:
EDIT:
I've discovered that does not matter the form passed at the New constructor, the problem is it only works if the object is instanced outside any procedure!
...So this will work, the form will be locked:
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
...But this else does not work, the form is not locked anymore!
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
Then why happens that and How I could fix it?
Here is the Full 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
The working code:
' [ 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