Advertisement
fortsoft

PersistWindowState

Sep 1st, 2020 (edited)
1,620
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 31.49 KB | Source Code | 0 0
  1. /**
  2.  * This is open-source software licensed under the terms of the MIT License.
  3.  *
  4.  * Copyright (c) 2009-2023 Petr Červinka - FortSoft <[email protected]>
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a copy
  7.  * of this software and associated documentation files (the "Software"), to deal
  8.  * in the Software without restriction, including without limitation the rights
  9.  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10.  * copies of the Software, and to permit persons to whom the Software is
  11.  * furnished to do so, subject to the following conditions:
  12.  *
  13.  * The above copyright notice and this permission notice shall be included in all
  14.  * copies or substantial portions of the Software.
  15.  *
  16.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19.  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21.  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  22.  * SOFTWARE.
  23.  **
  24.  * Version 2.3.4.0
  25.  */
  26.  
  27. using Microsoft.Win32;
  28. using System;
  29. using System.ComponentModel;
  30. using System.Diagnostics;
  31. using System.Drawing;
  32. using System.IO;
  33. using System.Linq;
  34. using System.Runtime.InteropServices;
  35. using System.Security;
  36. using System.Windows.Forms;
  37.  
  38. namespace FortSoft.Tools {
  39.  
  40.     /// <summary>
  41.     /// Implements saving of the state of the window (Windows Form) in the
  42.     /// Windows registry and its resetting according to previously saved values.
  43.     /// Uses Windows registry and Windows API.
  44.     /// </summary>
  45.     public sealed class PersistWindowState : Component {
  46.  
  47.         /// <summary>
  48.         /// Windows API constants.
  49.         /// </summary>
  50.         private const int GW_HWNDNEXT = 2;
  51.         private const int SW_RESTORE = 9;
  52.  
  53.         /// <summary>
  54.         /// Constants.
  55.         /// </summary>
  56.         private const string Location = "Location";
  57.         private const string Size = "Size";
  58.         private const string Software = "Software";
  59.         private const string State = "State";
  60.  
  61.         /// <summary>
  62.         /// Imports.
  63.         /// </summary>
  64.         [DllImport("user32.dll")]
  65.         private static extern bool IsWindowVisible(IntPtr hWnd);
  66.  
  67.         [DllImport("user32.dll")]
  68.         private static extern int IsIconic(IntPtr hWnd);
  69.  
  70.         [DllImport("user32.dll")]
  71.         private static extern int SetForegroundWindow(IntPtr hWnd);
  72.  
  73.         [DllImport("user32.dll")]
  74.         private static extern int ShowWindow(IntPtr hWnd, int nCmdShow);
  75.  
  76.         [DllImport("user32.dll")]
  77.         private static extern int ShowWindowAsync(IntPtr hWnd, int nCmdShow);
  78.  
  79.         [DllImport("user32.dll")]
  80.         private static extern IntPtr GetDesktopWindow();
  81.  
  82.         [DllImport("user32.dll")]
  83.         private static extern IntPtr GetTopWindow(IntPtr hWnd);
  84.  
  85.         [DllImport("user32.dll")]
  86.         private static extern IntPtr GetWindow(IntPtr hWnd, int uCmd);
  87.  
  88.         /// <summary>
  89.         /// Fields.
  90.         /// </summary>
  91.         private bool topMost;
  92.         private Form parent;
  93.         private FormWindowState windowState;
  94.         private IntPtr parentHandle;
  95.         private Point nLocation;
  96.         private Size nSize;
  97.         private string initialTitle;
  98.  
  99.         /// <summary>
  100.         /// Occurs on error accessing the Windows registry.
  101.         /// </summary>
  102.         public event EventHandler<PersistWindowStateEventArgs> Error;
  103.  
  104.         /// <summary>
  105.         /// Occurs on successful reset the parent form to its previous state
  106.         /// according to the values stored in the Windows registry or this class.
  107.         /// </summary>
  108.         public event EventHandler<PersistWindowStateEventArgs> Loaded;
  109.  
  110.         /// <summary>
  111.         /// Occurs on successful saving the values into the Windows registry.
  112.         /// </summary>
  113.         public event EventHandler<PersistWindowStateEventArgs> Saved;
  114.  
  115.         /// <summary>
  116.         /// Initializes a new instance of the <see cref="PersistWindowState"/>
  117.         /// class.
  118.         /// </summary>
  119.         public PersistWindowState() {
  120.             SavingOptions = PersistWindowStateSavingOptions.Registry;
  121.             RegistryPath = Path.Combine(Software, Application.CompanyName, Application.ProductName);
  122.         }
  123.  
  124.         /// <summary>
  125.         /// Allows saving minimized parent form.
  126.         /// </summary>
  127.         public bool AllowSaveMinimized { get; set; }
  128.  
  129.         /// <summary>
  130.         /// Allows saving TopMost property of the parent form.
  131.         /// </summary>
  132.         public bool AllowSaveTopMost { get; set; }
  133.  
  134.         /// <summary>
  135.         /// Other opened windows detection options.
  136.         /// </summary>
  137.         public WindowDetectionOptions DetectionOptions { get; set; }
  138.  
  139.         /// <summary>
  140.         /// Disables saving height od the parent form.
  141.         /// </summary>
  142.         public bool DisableSaveHeight { get; set; }
  143.  
  144.         /// <summary>
  145.         /// Disables saving position od the parent form.
  146.         /// </summary>
  147.         public bool DisableSavePosition { get; set; }
  148.  
  149.         /// <summary>
  150.         /// Disables saving size od the parent form.
  151.         /// </summary>
  152.         public bool DisableSaveSize { get; set; }
  153.  
  154.         /// <summary>
  155.         /// Disables saving width od the parent form.
  156.         /// </summary>
  157.         public bool DisableSaveWidth { get; set; }
  158.  
  159.         /// <summary>
  160.         /// Disables saving WindowState property od the parent form.
  161.         /// </summary>
  162.         public bool DisableSaveWindowState { get; set; }
  163.  
  164.         /// <summary>
  165.         /// Ensures a fixed height of the parent form.
  166.         /// </summary>
  167.         public bool FixHeight { get; set; }
  168.  
  169.         /// <summary>
  170.         /// Ensures a fixed width of the parent form.
  171.         /// </summary>
  172.         public bool FixWidth { get; set; }
  173.  
  174.         /// <summary>
  175.         /// Gets / sets parent form whose state will be saved.
  176.         /// </summary>
  177.         public Form Parent {
  178.             get {
  179.                 return parent;
  180.             }
  181.             set {
  182.                 parent = value;
  183.                 parent.Load += new EventHandler(OnLoad);
  184.                 parent.FormClosed += new FormClosedEventHandler((sender, e) => Save());
  185.                 initialTitle = parent.Text;
  186.             }
  187.         }
  188.  
  189.         /// <summary>
  190.         /// Ensures the placement of the parent form on the screen after load.
  191.         /// </summary>
  192.         public bool PlaceOnScreenAfterLoad { get; set; } = true;
  193.  
  194.         /// <summary>
  195.         /// Gets / sets Windows registry subtree path. Default value is set after
  196.         /// instantiation.
  197.         /// </summary>
  198.         public string RegistryPath { get; set; }
  199.  
  200.         /// <summary>
  201.         /// Gets / sets saving options. (That means if the state of the parent
  202.         /// form will be saved only within the scope of the running instance of
  203.         /// the software application or if it will be saved permanently in the
  204.         /// Windows registry.)
  205.         /// </summary>
  206.         public PersistWindowStateSavingOptions SavingOptions { get; set; }
  207.  
  208.         /// <summary>
  209.         /// Checks if another same window of the application is already running
  210.         /// to prevent multiple windows from having the same initial position.
  211.         /// </summary>
  212.         /// <returns>
  213.         /// True if another same window is already running; otherwise false.
  214.         /// </returns>
  215.         private bool AlreadyRunning() {
  216.             if (DetectionOptions.Equals(WindowDetectionOptions.NoDetection)) {
  217.                 return false;
  218.             }
  219.             Process process = Process.GetCurrentProcess();
  220.             FileSystemInfo processFileInfo = new FileInfo(process.MainModule.FileName);
  221.             foreach (Process p in Process.GetProcessesByName(process.ProcessName)
  222.                     .Where(new Func<Process, bool>(p => p.SessionId.Equals(process.SessionId)))
  223.                     .ToArray()) {
  224.  
  225.                 if (!p.Id.Equals(process.Id)
  226.                         && !p.MainWindowHandle.Equals(IntPtr.Zero)
  227.                         && processFileInfo.Name.Equals(new FileInfo(p.MainModule.FileName).Name)) {
  228.  
  229.                     switch (DetectionOptions) {
  230.                         case WindowDetectionOptions.TitleContains:
  231.                             if (p.MainWindowTitle.Contains(initialTitle)) {
  232.                                 return true;
  233.                             }
  234.                             break;
  235.                         case WindowDetectionOptions.TitleStartsWith:
  236.                             if (p.MainWindowTitle.StartsWith(initialTitle)) {
  237.                                 return true;
  238.                             }
  239.                             break;
  240.                         case WindowDetectionOptions.TitleEndsWith:
  241.                             if (p.MainWindowTitle.EndsWith(initialTitle)) {
  242.                                 return true;
  243.                             }
  244.                             break;
  245.                         case WindowDetectionOptions.TitleEquals:
  246.                             if (p.MainWindowTitle.Equals(initialTitle)) {
  247.                                 return true;
  248.                             }
  249.                             break;
  250.                         default:
  251.                             return true;
  252.                     }
  253.                 }
  254.             }
  255.             return false;
  256.         }
  257.  
  258.         /// <summary>
  259.         /// Thread-safe brings the parent form to the front of the z-order. This
  260.         /// method is the replacement of unreliable Control.BringToFront().
  261.         /// </summary>
  262.         public void BringToFront() {
  263.             if (!parentHandle.Equals(IntPtr.Zero)) {
  264.                 SetForegroundWindow(parentHandle);
  265.             }
  266.         }
  267.  
  268.         /// <summary>
  269.         /// Checks if the parent form immediately follows the reference form in z-order.
  270.         /// </summary>
  271.         /// <param name="hWnd">Reference form window handle.</param>
  272.         /// <param name="skip">An array of form handles to be skipped.</param>
  273.         private bool IsNextWindow(IntPtr hWnd, IntPtr[] skip) {
  274.             IntPtr window = GetTopWindow(GetDesktopWindow());
  275.             int thisWindow = -1, i = 0;
  276.  
  277.             do {
  278.                 if (thisWindow > -1 && thisWindow + 1 < i) {
  279.                     break;
  280.                 }
  281.                 if (!IsWindowVisible(window) || skip != null && skip.Contains(window)) {
  282.                     continue;
  283.                 }
  284.                 if (thisWindow > 0 && window.Equals(parentHandle)) {
  285.                     return true;
  286.                 }
  287.                 if (window.Equals(hWnd)) {
  288.                     thisWindow = i;
  289.                 }
  290.                 i++;
  291.             } while (!(window = GetWindow(window, GW_HWNDNEXT)).Equals(IntPtr.Zero));
  292.  
  293.             return false;
  294.         }
  295.  
  296.         /// <summary>
  297.         /// Handles the Load event of the parent form.
  298.         /// </summary>
  299.         private void OnLoad(object sender, EventArgs e) {
  300.             parentHandle = parent.Handle;
  301.  
  302.             if (SavingOptions.Equals(PersistWindowStateSavingOptions.None) || string.IsNullOrEmpty(RegistryPath)) {
  303.                 if (!nLocation.IsEmpty || !nSize.IsEmpty) {
  304.                     if (AllowSaveTopMost) {
  305.                         parent.TopMost = topMost;
  306.                     }
  307.                     if (!DisableSaveSize && (parent.FormBorderStyle.Equals(FormBorderStyle.Sizable)
  308.                             || parent.FormBorderStyle.Equals(FormBorderStyle.SizableToolWindow))) {
  309.  
  310.                         if (!FixWidth && !DisableSaveWidth && nSize.Width > 0) {
  311.                             parent.Width = nSize.Width;
  312.                         }
  313.                         if (!FixHeight && !DisableSaveHeight && nSize.Height > 0) {
  314.                             parent.Height = nSize.Height;
  315.                         }
  316.                     }
  317.                     if (!AlreadyRunning()) {
  318.                         if (PlaceOnScreenAfterLoad && !DisableSavePosition) {
  319.                             parent.Location = AdjustLocation(nLocation, parent.Size);
  320.                         } else if (!DisableSavePosition) {
  321.                             parent.Location = nLocation;
  322.                         }
  323.                     }
  324.                     if (parent.WindowState.Equals(FormWindowState.Normal)) {
  325.                         nSize = parent.Size;
  326.                     }
  327.                     if (!DisableSaveWindowState && parent.ControlBox && (parent.MinimizeBox || parent.MaximizeBox)) {
  328.                         parent.WindowState = AllowSaveMinimized || !parent.WindowState.Equals(FormWindowState.Minimized)
  329.                             ? windowState
  330.                             : FormWindowState.Normal;
  331.                     }
  332.                 } else {
  333.                     if (parent.WindowState.Equals(FormWindowState.Normal)) {
  334.                         nLocation = parent.Location;
  335.                     }
  336.                     if (!AlreadyRunning()) {
  337.                         if (PlaceOnScreenAfterLoad && !DisableSavePosition) {
  338.                             parent.Location = AdjustLocation(nLocation, parent.Size);
  339.                         } else if (!DisableSavePosition) {
  340.                             parent.Location = nLocation;
  341.                         }
  342.                     }
  343.                 }
  344.                 Loaded?.Invoke(this, new PersistWindowStateEventArgs());
  345.             }
  346.  
  347.             if (SavingOptions.Equals(PersistWindowStateSavingOptions.Registry) && !string.IsNullOrEmpty(RegistryPath)) {
  348.                 RegistryKey registryKey = null;
  349.                 try {
  350.                     registryKey = Registry.CurrentUser.OpenSubKey(RegistryPath);
  351.                 } catch (IOException exception) {
  352.                     Debug.WriteLine(exception);
  353.                     Error?.Invoke(this, new PersistWindowStateEventArgs(registryKey, exception));
  354.                 } catch (SecurityException exception) {
  355.                     Debug.WriteLine(exception);
  356.                     Error?.Invoke(this, new PersistWindowStateEventArgs(registryKey, exception));
  357.                 } catch (Exception exception) {
  358.                     Debug.WriteLine(exception);
  359.                 }
  360.                 if (registryKey == null) {
  361.                     if (parent.WindowState.Equals(FormWindowState.Normal)) {
  362.                         nLocation = parent.Location;
  363.                     }
  364.                     if (!AlreadyRunning()) {
  365.                         if (PlaceOnScreenAfterLoad && !DisableSavePosition) {
  366.                             parent.Location = AdjustLocation(nLocation, parent.Size);
  367.                         } else if (!DisableSavePosition) {
  368.                             parent.Location = nLocation;
  369.                         }
  370.                     }
  371.                 } else {
  372.                     nLocation = IntToPoint((int)registryKey.GetValue(parent.Name + Location, PointToInt(parent.Location)));
  373.                     if (!DisableSaveSize && (parent.FormBorderStyle.Equals(FormBorderStyle.Sizable)
  374.                             || parent.FormBorderStyle.Equals(FormBorderStyle.SizableToolWindow))) {
  375.  
  376.                         Size size = IntToSize((int)registryKey.GetValue(parent.Name + Size, SizeToInt(parent.Size)));
  377.                         if (!FixWidth && !DisableSaveWidth && size.Width > 0) {
  378.                             parent.Width = size.Width;
  379.                         }
  380.                         if (!FixHeight && !DisableSaveHeight && size.Height > 0) {
  381.                             parent.Height = size.Height;
  382.                         }
  383.                     }
  384.                     if (!AlreadyRunning()) {
  385.                         if (PlaceOnScreenAfterLoad && !DisableSavePosition) {
  386.                             parent.Location = AdjustLocation(nLocation, parent.Size);
  387.                         } else if (!DisableSavePosition) {
  388.                             parent.Location = nLocation;
  389.                         }
  390.                     }
  391.                     if (parent.WindowState.Equals(FormWindowState.Normal)) {
  392.                         nSize = parent.Size;
  393.                     }
  394.                     if (!DisableSaveWindowState && parent.ControlBox && (parent.MinimizeBox || parent.MaximizeBox)
  395.                             || AllowSaveTopMost) {
  396.  
  397.                         windowState = IntToWindowState((int)registryKey.GetValue(parent.Name
  398.                             + State, WindowStateToInt(parent.WindowState, parent.TopMost)), out topMost);
  399.                         if (!AllowSaveMinimized && windowState.Equals(FormWindowState.Minimized)) {
  400.                             windowState = FormWindowState.Normal;
  401.                         }
  402.                         parent.WindowState = windowState;
  403.                         if (AllowSaveTopMost) {
  404.                             parent.TopMost = topMost;
  405.                         }
  406.                     }
  407.                 }
  408.                 Loaded?.Invoke(this, new PersistWindowStateEventArgs(registryKey));
  409.             }
  410.  
  411.             if (FixWidth && FixHeight) {
  412.                 parent.MaximumSize = parent.Size;
  413.                 parent.MinimumSize = parent.Size;
  414.             } else if (FixWidth) {
  415.                 parent.MaximumSize = new Size(
  416.                     parent.Width,
  417.                     parent.MaximumSize.Height > 0 ? parent.MaximumSize.Height : int.MaxValue);
  418.                 parent.MinimumSize = new Size(
  419.                     parent.Width,
  420.                     parent.MinimumSize.Height);
  421.             } else if (FixHeight) {
  422.                 parent.MaximumSize = new Size(
  423.                     parent.MaximumSize.Width > 0 ? parent.MaximumSize.Width : int.MaxValue,
  424.                     parent.Height);
  425.                 parent.MinimumSize = new Size(
  426.                     parent.MinimumSize.Width,
  427.                     parent.Height);
  428.             }
  429.  
  430.             parent.Resize += new EventHandler(OnResize);
  431.             parent.Move += new EventHandler(OnMove);
  432.         }
  433.  
  434.         /// <summary>
  435.         /// Handles the Move event of the parent form.
  436.         /// </summary>
  437.         private void OnMove(object sender, EventArgs e) {
  438.             if (parent.WindowState.Equals(FormWindowState.Normal)) {
  439.                 nLocation = parent.Location;
  440.             }
  441.             if (AllowSaveMinimized || !parent.WindowState.Equals(FormWindowState.Minimized)) {
  442.                 windowState = parent.WindowState;
  443.             }
  444.         }
  445.  
  446.         /// <summary>
  447.         /// Handles the Resize event of the parent form.
  448.         /// </summary>
  449.         private void OnResize(object sender, EventArgs e) {
  450.             if (parent.WindowState.Equals(FormWindowState.Normal)) {
  451.                 nSize = parent.Size;
  452.             }
  453.             if (AllowSaveMinimized || !parent.WindowState.Equals(FormWindowState.Minimized)) {
  454.                 windowState = parent.WindowState;
  455.             }
  456.         }
  457.  
  458.         /// <summary>
  459.         /// Thread-safe restores the parent form to its the previous WindowState.
  460.         /// </summary>
  461.         public void Restore() {
  462.             if (!parentHandle.Equals(IntPtr.Zero) && !IsIconic(parentHandle).Equals(0)) {
  463.                 ShowWindowAsync(parentHandle, SW_RESTORE);
  464.             }
  465.         }
  466.  
  467.         /// <summary>
  468.         /// Saves the state of the parent form into the Windows registry.
  469.         /// </summary>
  470.         public void Save() {
  471.             if (SavingOptions.Equals(PersistWindowStateSavingOptions.None) || string.IsNullOrEmpty(RegistryPath)) {
  472.                 if (AllowSaveTopMost) {
  473.                     topMost = parent.TopMost;
  474.                 }
  475.                 Saved?.Invoke(this, new PersistWindowStateEventArgs());
  476.             }
  477.  
  478.             if (SavingOptions.Equals(PersistWindowStateSavingOptions.Registry) && !string.IsNullOrEmpty(RegistryPath)) {
  479.                 RegistryKey registryKey = null;
  480.                 try {
  481.                     registryKey = Registry.CurrentUser.CreateSubKey(RegistryPath);
  482.                 } catch (IOException exception) {
  483.                     Debug.WriteLine(exception);
  484.                     Error?.Invoke(this, new PersistWindowStateEventArgs(registryKey, exception));
  485.                 } catch (SecurityException exception) {
  486.                     Debug.WriteLine(exception);
  487.                     Error?.Invoke(this, new PersistWindowStateEventArgs(registryKey, exception));
  488.                 } catch (UnauthorizedAccessException exception) {
  489.                     Debug.WriteLine(exception);
  490.                     Error?.Invoke(this, new PersistWindowStateEventArgs(registryKey, exception));
  491.                 } catch (Exception exception) {
  492.                     Debug.WriteLine(exception);
  493.                 }
  494.                 if (registryKey == null) {
  495.                     return;
  496.                 }
  497.                 if (!DisableSavePosition) {
  498.                     registryKey.SetValue(parent.Name + Location, PointToInt(nLocation));
  499.                 }
  500.                 if (!DisableSaveSize
  501.                         && !(DisableSaveWidth && DisableSaveHeight)
  502.                         && (parent.FormBorderStyle.Equals(FormBorderStyle.Sizable)
  503.                             || parent.FormBorderStyle.Equals(FormBorderStyle.SizableToolWindow))) {
  504.  
  505.                     registryKey.SetValue(parent.Name + Size, SizeToInt(nSize));
  506.                 }
  507.                 if (!DisableSaveWindowState && parent.ControlBox && (parent.MinimizeBox || parent.MaximizeBox)
  508.                         || AllowSaveTopMost) {
  509.  
  510.                     if (AllowSaveTopMost) {
  511.                         topMost = parent.TopMost;
  512.                     }
  513.                     if (AllowSaveMinimized || !parent.WindowState.Equals(FormWindowState.Minimized)) {
  514.                         registryKey.SetValue(parent.Name + State, WindowStateToInt(parent.WindowState, topMost));
  515.                     } else {
  516.                         registryKey.SetValue(parent.Name + State, WindowStateToInt(windowState, topMost));
  517.                     }
  518.                 }
  519.                 Saved?.Invoke(this, new PersistWindowStateEventArgs(registryKey));
  520.             }
  521.         }
  522.  
  523.         /// <summary>
  524.         /// Thread-safe sets the parent form visible for the user and brings it
  525.         /// to the front before other windows on the user's desktop except the
  526.         /// reference form.
  527.         /// </summary>
  528.         /// <param name="hWnd">Reference form window handle.</param>
  529.         public void SetVisible(IntPtr hWnd) => SetVisible(hWnd, null);
  530.  
  531.         /// <summary>
  532.         /// Thread-safe sets the parent form visible for the user and brings it
  533.         /// to the front before other windows on the user's desktop except the
  534.         /// reference form and except the provided forms.
  535.         /// </summary>
  536.         /// <param name="hWnd">Reference form window handle.</param>
  537.         /// <param name="skip">An array of form handles to be skipped.</param>
  538.         public void SetVisible(IntPtr hWnd, IntPtr[] skip) {
  539.             if (!parentHandle.Equals(IntPtr.Zero)) {
  540.                 if (!IsIconic(parentHandle).Equals(0)) {
  541.                     ShowWindow(parentHandle, SW_RESTORE);
  542.                     SetForegroundWindow(hWnd);
  543.                 } else if (!IsNextWindow(hWnd, skip)) {
  544.                     SetForegroundWindow(parentHandle);
  545.                     SetForegroundWindow(hWnd);
  546.                 }
  547.             }
  548.         }
  549.  
  550.         /// <summary>
  551.         /// Calculates the new location for the parent form to be visible on the
  552.         /// screen.
  553.         /// </summary>
  554.         /// <param name="location">Current location of the parent form.</param>
  555.         /// <param name="size">Current size of the parent form.</param>
  556.         /// <returns>Adjusted location for the parent form.</returns>
  557.         private static Point AdjustLocation(Point location, Size size) {
  558.             Point point = new Point(location.X, location.Y);
  559.             if (point.X < SystemInformation.VirtualScreen.Left) {
  560.                 point.X = SystemInformation.VirtualScreen.Left;
  561.             } else if (point.X + size.Width > SystemInformation.VirtualScreen.Width) {
  562.                 point.X = SystemInformation.VirtualScreen.Width - size.Width;
  563.             }
  564.             if (point.Y < SystemInformation.VirtualScreen.Top) {
  565.                 point.Y = SystemInformation.VirtualScreen.Top;
  566.             } else if (point.Y + size.Height > SystemInformation.VirtualScreen.Height) {
  567.                 point.Y = SystemInformation.VirtualScreen.Height - size.Height;
  568.             }
  569.             return point;
  570.         }
  571.  
  572.         /// <summary>
  573.         /// Converts System.Int32 to System.Drawing.Point.
  574.         /// </summary>
  575.         /// <param name="val">An integer value stored in the registry.</param>
  576.         private static Point IntToPoint(int val) {
  577.             byte[] bytes = BitConverter.GetBytes(val);
  578.             return new Point(
  579.                 BitConverter.ToInt16(bytes, BitConverter.IsLittleEndian ? 0 : 2),
  580.                 BitConverter.ToInt16(bytes, BitConverter.IsLittleEndian ? 2 : 0));
  581.         }
  582.  
  583.         /// <summary>
  584.         /// Converts System.Int32 to System.Drawing.Size.
  585.         /// </summary>
  586.         /// <param name="val">An integer value stored in the registry.</param>
  587.         private static Size IntToSize(int val) {
  588.             byte[] bytes = BitConverter.GetBytes(val);
  589.             return new Size(
  590.                 BitConverter.ToUInt16(bytes, BitConverter.IsLittleEndian ? 0 : 2),
  591.                 BitConverter.ToUInt16(bytes, BitConverter.IsLittleEndian ? 2 : 0));
  592.         }
  593.  
  594.         /// <summary>
  595.         /// Converts System.Int32 to System.Windows.Forms.FormWindowState and to
  596.         /// System.Boolean.
  597.         /// </summary>
  598.         /// <param name="val">An integer value stored in the registry.</param>
  599.         private static FormWindowState IntToWindowState(int val, out bool topMost) {
  600.             byte[] bytes = BitConverter.GetBytes(val);
  601.             topMost = BitConverter.ToInt16(bytes, BitConverter.IsLittleEndian ? 2 : 0) > 0;
  602.             short windowState = BitConverter.ToInt16(bytes, BitConverter.IsLittleEndian ? 0 : 2);
  603.             return windowState.Equals(1) || windowState.Equals(2) ? (FormWindowState)windowState : FormWindowState.Normal;
  604.         }
  605.  
  606.         /// <summary>
  607.         /// Converts System.Drawing.Point to System.Int32.
  608.         /// </summary>
  609.         /// <param name="point">Location of the form to be saved.</param>
  610.         /// <returns>An integer value to store in the Windows registry.</returns>
  611.         private static int PointToInt(Point point) {
  612.             byte[] bytes = new byte[4];
  613.             Array.Copy(
  614.                 BitConverter.GetBytes(point.X),
  615.                 BitConverter.IsLittleEndian ? 0 : 2,
  616.                 bytes,
  617.                 BitConverter.IsLittleEndian ? 0 : 2,
  618.                 2);
  619.             Array.Copy(
  620.                 BitConverter.GetBytes(point.Y),
  621.                 BitConverter.IsLittleEndian ? 0 : 2,
  622.                 bytes,
  623.                 BitConverter.IsLittleEndian ? 2 : 0,
  624.                 2);
  625.             return BitConverter.ToInt32(bytes, 0);
  626.         }
  627.  
  628.         /// <summary>
  629.         /// Converts System.Drawing.Size to System.Int32.
  630.         /// </summary>
  631.         /// <param name="size">Size of the form to be saved.</param>
  632.         /// <returns>An integer value to store in the Windows registry.</returns>
  633.         private static int SizeToInt(Size size) {
  634.             byte[] bytes = new byte[4];
  635.             Array.Copy(
  636.                 BitConverter.GetBytes(size.Width),
  637.                 BitConverter.IsLittleEndian ? 0 : 2,
  638.                 bytes,
  639.                 BitConverter.IsLittleEndian ? 0 : 2,
  640.                 2);
  641.             Array.Copy(
  642.                 BitConverter.GetBytes(size.Height),
  643.                 BitConverter.IsLittleEndian ? 0 : 2,
  644.                 bytes,
  645.                 BitConverter.IsLittleEndian ? 2 : 0,
  646.                 2);
  647.             return BitConverter.ToInt32(bytes, 0);
  648.         }
  649.  
  650.         /// <summary>
  651.         /// Converts System.Windows.Forms.FormWindowState and System.Boolean to
  652.         /// System.Int32.
  653.         /// </summary>
  654.         /// <param name="formWindowState">FormWindowState to be saved.</param>
  655.         /// <param name="topMost">A boolean value to be saved.</param>
  656.         /// <returns>An integer value to store in the Windows registry.</returns>
  657.         private static int WindowStateToInt(FormWindowState formWindowState, bool topMost) {
  658.             byte[] bytes = new byte[4];
  659.             Array.Copy(
  660.                 BitConverter.GetBytes((short)formWindowState),
  661.                 0,
  662.                 bytes,
  663.                 BitConverter.IsLittleEndian ? 0 : 2,
  664.                 2);
  665.             Array.Copy(
  666.                 BitConverter.GetBytes(Convert.ToInt16(topMost)),
  667.                 0,
  668.                 bytes,
  669.                 BitConverter.IsLittleEndian ? 2 : 0,
  670.                 2);
  671.             return BitConverter.ToInt32(bytes, 0);
  672.         }
  673.  
  674.         /// <summary>
  675.         /// Other opened windows detection options.
  676.         /// </summary>
  677.         public enum WindowDetectionOptions {
  678.             /// <summary>
  679.             /// The default detection method by process file name.
  680.             /// </summary>
  681.             Default,
  682.             /// <summary>
  683.             /// The already opened window will be determined by title comparison.
  684.             /// </summary>
  685.             TitleContains,
  686.             /// <summary>
  687.             /// The already opened window will be determined by title comparison.
  688.             /// </summary>
  689.             TitleStartsWith,
  690.             /// <summary>
  691.             /// The already opened window will be determined by title comparison.
  692.             /// </summary>
  693.             TitleEndsWith,
  694.             /// <summary>
  695.             /// The already opened window will be determined by title comparison.
  696.             /// </summary>
  697.             TitleEquals,
  698.             /// <summary>
  699.             /// No detection of other form instances will be performed. Use this
  700.             /// option only for one instance forms.
  701.             /// </summary>
  702.             NoDetection
  703.         }
  704.  
  705.         /// <summary>
  706.         /// PersistWindowState saving options.
  707.         /// </summary>
  708.         public enum PersistWindowStateSavingOptions {
  709.             /// <summary>
  710.             /// The state of the parent form will be saved only within the scope
  711.             /// of the running instance of the software application.
  712.             /// </summary>
  713.             None,
  714.             /// <summary>
  715.             /// The state of the parent form will be saved permanently in the
  716.             /// Windows registry.
  717.             /// </summary>
  718.             Registry
  719.         }
  720.     }
  721.  
  722.     /// <summary>
  723.     /// Implements custom event args used by PersistWindowState class.
  724.     /// </summary>
  725.     public sealed class PersistWindowStateEventArgs : EventArgs {
  726.  
  727.         /// <summary>
  728.         /// The Exception property.
  729.         /// </summary>
  730.         public Exception Exception { get; private set; }
  731.  
  732.         /// <summary>
  733.         /// The RegistryKey property.
  734.         /// </summary>
  735.         public RegistryKey RegistryKey { get; private set; }
  736.  
  737.         /// <summary>
  738.         /// Initializes a new instance of the
  739.         /// <see cref="PersistWindowStateEventArgs"/> class.
  740.         /// </summary>
  741.         public PersistWindowStateEventArgs(RegistryKey registryKey = null, Exception exception = null) {
  742.             Exception = exception;
  743.             RegistryKey = registryKey;
  744.         }
  745.     }
  746. }
  747.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement