Last active
May 3, 2016 20:49
-
-
Save jimbuck/a59b23de17eca2de95766ad6ef8e66ad to your computer and use it in GitHub Desktop.
Simple class that maintains the position and size of console windows when debugging in VS. Makes rapid debug cycles a little less frustrating.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Diagnostics; | |
using System.IO; | |
using System.Reflection; | |
using System.Runtime.InteropServices; | |
using System.Threading.Tasks; | |
using System.Timers; | |
namespace CodeGear.Utilities | |
{ | |
public class WindowKeeper | |
{ | |
#region Interop | |
private const uint SWP_NOZORDER = 4; | |
[DllImport("user32.dll")] | |
private static extern bool GetWindowRect(IntPtr hwnd, ref Rect rectangle); | |
[DllImport("user32.dll", EntryPoint = "SetWindowPos")] | |
private static extern IntPtr SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int Y, int cx, int cy, uint wFlags); | |
public struct Rect | |
{ | |
public int Left { get; set; } | |
public int Top { get; set; } | |
public int Right { get; set; } | |
public int Bottom { get; set; } | |
public bool HasChanged(Rect that) | |
{ | |
return this.Left != that.Left || | |
this.Right != that.Right || | |
this.Top != that.Top || | |
this.Bottom != that.Bottom; | |
} | |
} | |
#endregion | |
#region Constants | |
private const string APP_FOLDER = "WindowKeeper"; | |
private const string FILE_EXTENSION = ".xml"; | |
private static readonly string APP_DATA = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); | |
#endregion | |
#region Fields | |
private static WindowKeeper _instance; | |
private int _pollTime; | |
private readonly IntPtr _window; | |
private readonly FileInfo _dataFile; | |
private readonly Timer _timer; | |
private Rect _prevSize; | |
#endregion | |
#region Constructors | |
public WindowKeeper(int pollTime = 3000, string appName = null) | |
{ | |
try | |
{ | |
Process process = Process.GetCurrentProcess(); | |
_window = process.MainWindowHandle; | |
if (String.IsNullOrWhiteSpace(appName)) | |
{ | |
appName = Assembly.GetCallingAssembly().GetName().Name; | |
} | |
_dataFile = new FileInfo(Path.Combine(APP_DATA, APP_FOLDER, appName + FILE_EXTENSION)); | |
Restore(); | |
_timer = new Timer(_pollTime); | |
_timer.Elapsed += OnTimerElapsed; | |
_timer.Start(); | |
} | |
catch (Exception) { /* Don't do anything... */ } | |
} | |
#endregion | |
#region Public Methods | |
public static void Register(int pollTime = 3000, string appName = null) | |
{ | |
try | |
{ | |
if (_instance != null) | |
{ | |
_instance.Stop(); | |
_instance = null; | |
} | |
if (String.IsNullOrWhiteSpace(appName)) | |
{ | |
appName = Assembly.GetCallingAssembly().GetName().Name; | |
} | |
_instance = new WindowKeeper(pollTime, appName); | |
} | |
catch (Exception) { /* Don't do anything... */ } | |
} | |
public void Stop() | |
{ | |
_timer?.Stop(); | |
} | |
public void Restart() | |
{ | |
_timer?.Start(); | |
} | |
#endregion | |
#region Private Methods | |
private void OnTimerElapsed(object sender, ElapsedEventArgs args) | |
{ | |
Task.Run(() => Persist()); | |
} | |
private void Restore() | |
{ | |
try | |
{ | |
if (_dataFile == null || !_dataFile.Exists) return; | |
using (StreamReader reader = _dataFile.OpenText()) | |
{ | |
string xml = reader.ReadToEnd(); | |
Rect windowState = XmlHelpers.FromXml<Rect>(xml); | |
SetWindowPos(_window, | |
0, | |
windowState.Left, | |
windowState.Top, | |
windowState.Right - windowState.Left, | |
windowState.Bottom - windowState.Top, | |
SWP_NOZORDER); | |
} | |
} | |
catch (Exception) { /* Don't do anything... */ } | |
} | |
private void Persist() | |
{ | |
try | |
{ | |
if (_dataFile == null) return; | |
Rect rect = new Rect(); | |
GetWindowRect(_window, ref rect); | |
if (!_prevSize.HasChanged(rect)) return; | |
_prevSize = rect; | |
string xml = XmlHelpers.ToXml(rect, format: true); | |
_dataFile.Directory?.Create(); | |
using (StreamWriter writer = _dataFile.CreateText()) | |
{ | |
writer.Write(xml); | |
} | |
} | |
catch (Exception) { /* Don't do anything... */ } | |
} | |
#endregion | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using CodeGear.Utilities; | |
public class ExampleProgram | |
{ | |
public static void Main() | |
{ | |
WindowKeeper.Register(); | |
Console.WriteLine("Move the window around, then close and re-run!"); | |
Console.ReadLine(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment