Skip to content

Instantly share code, notes, and snippets.

@jimbuck
Last active May 3, 2016 20:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jimbuck/a59b23de17eca2de95766ad6ef8e66ad to your computer and use it in GitHub Desktop.
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.
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
}
}
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