It seems that saving window positions and sizes (including the application's main window location)
should be easy enough. But even now, after so many years of Windows programming, people get it wrong.
We need to remember about changing screen resolutions, switching from multiple to single monitors,
connecting to a projector, etc. Saving the current window's location just ain't gonna do the trick...
The key to the solution is the pair of Windows API functions:
GetWindowPlacement and
SetWindowPlacement.
Something like this - saving and restoring a Window's placement
(GetSetting/SetSetting are functions that load/save settings through some utility class;
LEFT_ID, etc. are just string constants used to define keys under which settings are saved):
Public Sub LoadWindowPlacement(ByVal key As String, ByVal window As Window)
Dim windowPlacement As WindowPlacement = GetWindowPlacement(window)
Dim restoredPosition As New IntegerRect(
GetSetting(Of Integer)(key + LEFT_ID, windowPlacement.NormalPosition.Left),
GetSetting(Of Integer)(key + TOP_ID, windowPlacement.NormalPosition.Top),
GetSetting(Of Integer)(key + WIDTH_ID, windowPlacement.NormalPosition.Width),
GetSetting(Of Integer)(key + HEIGHT_ID, windowPlacement.NormalPosition.Height))
windowPlacement.NormalPosition = restoredPosition
windowPlacement.ShowCommand =
GetSetting(Of Integer)(key + SHOW_COMMAND_ID, SHOW_MAXIMIZED)
SetWindowPlacement(window, windowPlacement)
End Sub
Public Sub SaveWindowPlacement(ByVal key As String, ByVal window As Window)
Dim windowPlacement As WindowPlacement = GetWindowPlacement(window)
SetSetting(Of Integer)(key + HEIGHT_ID, windowPlacement.NormalPosition.Height)
SetSetting(Of Integer)(key + WIDTH_ID, windowPlacement.NormalPosition.Width)
SetSetting(Of Integer)(key + TOP_ID, windowPlacement.NormalPosition.Top)
SetSetting(Of Integer)(key + LEFT_ID, windowPlacement.NormalPosition.Left)
SetSetting(Of Integer)(key + SHOW_COMMAND_ID, windowPlacement.ShowCommand)
End Sub
Note that, in the above, we set save/load the NormalPosition (the location of the window in restored state),
and handle minimization / maximization separately.
What needs to be done still is we need methods to interface with the Windows API;
first, several structures:
<StructLayout(LayoutKind.Sequential)>
Public Structure IntegerPoint
Public Property X As Integer
Public Property Y As Integer
End Structure
<StructLayout(LayoutKind.Sequential)>
Public Structure IntegerRect
Public Property Left As Integer
Public Property Top As Integer
Public Property Width As Integer
Public Property Height As Integer
End Structure
<StructLayout(LayoutKind.Sequential)>
Public Structure WindowPlacement
Public Property Length As Integer
Public Property Flags As Integer
Public Property ShowCommand As Integer
Public Property MinPosition As IntegerPoint
Public Property MaxPosition As IntegerPoint
Public Property NormalPosition As IntegerRect
End Structure
The last structure is the important one - you'll find the description
here.
Next, for the functions:
Public NotInheritable Class WindowUtilities
Private Sub New()
End Sub
Public Const SHOW_NORMAL As Integer = 1
Public Const SHOW_MINIMIZED As Integer = 2
Public Const SHOW_MAXIMIZED As Integer = 3
Public Shared Function GetWindowPlacement(
ByVal window As Window) As WindowPlacement
Dim placement As WindowPlacement
SafeNativeMethods.GetWindowPlacement(
New WindowInteropHelper(window).Handle, placement)
Return placement
End Function
Public Shared Sub SetWindowPlacement(
ByVal window As Window, ByVal placement As WindowPlacement)
SafeNativeMethods.SetWindowPlacement(
New WindowInteropHelper(window).Handle, placement)
End Sub
End Class
Friend NotInheritable Class SafeNativeMethods
Private Sub New()
End Sub
<DllImport("user32.dll")>
Public Shared Function GetWindowPlacement(
ByVal handle As IntPtr, ByRef placement As WindowPlacement)
As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
<DllImport("user32.dll")>
Public Shared Function SetWindowPlacement(
ByVal handle As IntPtr, ByRef placement As WindowPlacement)
As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
End Class
And this is quite enough for the application to behave correctly between sessions,
regardless what happens with the screen's resolution, Window's task bar's position, or multi-monitor setup.
HTH
Top
|