Save/Restore Form Layout
Functions to Save (SaveLayout) and Restore (RestoreLayout) form size and position.
The function SaveLayout saves the size and position of the forms in the XML file FormLayouts.xml in %AppData%/Ipercube.Utilites (see below the variable formLayoutsBasePath).
On the XML for each form is created an entry using the Form Name and the Application Name as the key, example:
- form name=”FormShowMessage::Ipercube_Utilities“
The two functions receive the form as parameter; if the form declare the property LayoutKey (set it with a string value before calling the form), then this value is added to the key; this can be useful if an application uses the same form many times in different context and you want to have different size and position for each context. So, for example, if LayoutKey is set to “UpdateCompleted” the key will be:
- form name=”FormShowMessage::Ipercube_Utilities::UpdateCompleted“
A snippet of the xml for the same form in the same application but in different context:
<form name="FormShowMessage::Ipercube_Utilities::UpdateCompleted">
<x>1162</x>
<y>481</y>
<width>428</width>
<height>260</height>
</form>
<form name="FormShowMessage::Ipercube_Utilities::BuildMySettingsCode">
<x>1972</x>
<y>459</y>
<width>907</width>
<height>260</height>
</form>Now the required imports and private variables:
Imports System.Windows.Forms
Private ReadOnly syncObj As New Object()
Private ReadOnly formLayoutsBasePath As String = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
"Ipercube.Utilities")
Private ReadOnly formLayoutsFilePath As String = Path.Combine(formLayoutsBasePath, "FormLayouts.xml")
The Functions list:
Note: The functions in this section use the following Private functions:
' Internal Functions used by RestoreLayout, SaveLayout
Private Function LoadFormLayoutXml() As XDocument
SyncLock syncObj
If File.Exists(formLayoutsFilePath) Then
Try
Return XDocument.Load(formLayoutsFilePath)
Catch
' Se file danneggiato, sovrascrivi
End Try
End If
Return New XDocument(New XElement("applications"))
End SyncLock
End Function
Private Sub SetFormDefaultLocation(f As Form)
Dim sscreen = Screen.FromControl(f)
Dim wa = sscreen.WorkingArea
f.Top = wa.Bottom - f.Height - 10
f.Left = wa.Left + 10
End Sub
Private Function GetEffectiveFormName(f As Form, appName As String) As String
Dim baseName = If(Not String.IsNullOrWhiteSpace(f.Name), f.Name, f.GetType().Name)
Dim layoutKey As String = ""
Dim prop = f.GetType().GetProperty("LayoutKey", BindingFlags.Public Or BindingFlags.Instance)
If prop IsNot Nothing AndAlso prop.PropertyType Is GetType(String) Then
Dim val = TryCast(prop.GetValue(f), String)
If Not String.IsNullOrWhiteSpace(val) Then
layoutKey = val.Replace(" ", "").Replace(".", "").Trim()
End If
End If
If String.IsNullOrEmpty(layoutKey) Then
Return $"{baseName}::{appName}"
Else
Return $"{baseName}::{appName}::{layoutKey}"
End If
End Function
Private Function GetAppNameSafe() As String
Dim entryAsm = Assembly.GetEntryAssembly()
If entryAsm IsNot Nothing Then
Return entryAsm.GetName().Name.Replace(" ", "_").Replace(".", "_").Trim
End If
' Fallback: assembly che ha chiamato il modulo (utile in VSTO/plugin)
Return Assembly.GetCallingAssembly().GetName().Name.Replace(" ", "_").Replace(".", "_").Trim
End Function