Widow

Subversion Repositories:
Compare Path: Rev
With Path: Rev
?path1? @ 13  →  ?path2? @ 14
/trunk/Widow/Helpers.cs
@@ -48,26 +48,13 @@
return windows;
}
 
public static IEnumerable<IntPtr> EnumerateWindows()
public static string GetWindowClass(IntPtr hWnd)
{
var windows = new List<IntPtr>();
 
Natives.EnumWindows(delegate(IntPtr wnd, IntPtr param)
{
windows.Add(wnd);
return true;
}, IntPtr.Zero);
 
return windows;
var windowClass = new StringBuilder(256);
Natives.GetClassName(hWnd, windowClass, windowClass.Capacity);
return windowClass.ToString();
}
 
/// <summary> Find all windows that contain the given title text </summary>
/// <param name="titleText"> The text that the window title must contain. </param>
public static IEnumerable<IntPtr> FindWindowsWithText(string titleText)
{
return FindWindows((wnd, param) => GetWindowText(wnd).Contains(titleText));
}
 
public static string GetWindowTitle(IntPtr hWnd)
{
var length = Natives.GetWindowTextLength(hWnd) + 1;
/trunk/Widow/Natives.cs
@@ -6,6 +6,9 @@
{
public static class Natives
{
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
 
#region Public Events & Delegates
 
public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
/trunk/Widow/RuleEditForm.cs
@@ -315,6 +315,52 @@
}
}
 
private void DrawButton_Click(object sender, EventArgs e)
{
var selectedWindow = (Window) windowRulesListBox.SelectedItem;
if (selectedWindow == null)
{
return;
}
 
if (DrawOverlayForm != null)
{
return;
}
 
DrawOverlayForm = new DrawOverlayForm();
DrawOverlayForm.WindowDrawn += DrawOverlayForm_WindowDrawn;
DrawOverlayForm.Closed += DrawOverlayForm_Closed;
DrawOverlayForm.Show();
}
 
private void DrawOverlayForm_WindowDrawn(object sender, WindowDrawnEventArgs e)
{
var selectedWindow = (Window) windowRulesListBox.SelectedItem;
if (selectedWindow == null)
{
return;
}
 
WindowLeft.Text = e.Left.ToString();
WindowTop.Text = e.Top.ToString();
WindowWidth.Text = e.Width.ToString();
WindowHeight.Text = e.Height.ToString();
 
selectedWindow.Left = e.Left;
selectedWindow.Top = e.Top;
selectedWindow.Width = e.Width;
selectedWindow.Height = e.Height;
}
 
private void DrawOverlayForm_Closed(object sender, EventArgs e)
{
DrawOverlayForm.Closed -= DrawOverlayForm_Closed;
DrawOverlayForm.WindowDrawn -= DrawOverlayForm_WindowDrawn;
DrawOverlayForm.Dispose();
DrawOverlayForm = null;
}
 
#endregion
 
#region Private Methods
@@ -323,14 +369,14 @@
{
foreach (var handle in Helpers.FindWindows((wnd, param) => true))
{
var title = Helpers.GetWindowTitle(handle);
if (string.IsNullOrEmpty(title))
var windowTitle = Helpers.GetWindowTitle(handle);
if (string.IsNullOrEmpty(windowTitle))
{
continue;
}
 
var process = Helpers.GetProcessName(handle);
if (string.IsNullOrEmpty(process))
var windowClass = Helpers.GetWindowClass(handle);
if (string.IsNullOrEmpty(windowClass))
{
continue;
}
@@ -340,7 +386,7 @@
continue;
}
 
var window = new Window(process, title, rect.Top, rect.Left, rect.Right - rect.Left,
var window = new Window(windowClass, windowTitle, rect.Top, rect.Left, rect.Right - rect.Left,
rect.Bottom - rect.Top);
 
this.Execute(() =>
@@ -366,52 +412,5 @@
}
 
#endregion
 
private void DrawButton_Click(object sender, EventArgs e)
{
var selectedWindow = (Window) windowRulesListBox.SelectedItem;
if (selectedWindow == null)
{
return;
}
 
if (DrawOverlayForm != null)
{
return;
}
 
DrawOverlayForm = new DrawOverlayForm();
DrawOverlayForm.WindowDrawn += DrawOverlayForm_WindowDrawn;
DrawOverlayForm.Closed += DrawOverlayForm_Closed;
DrawOverlayForm.Show();
 
}
 
private void DrawOverlayForm_WindowDrawn(object sender, WindowDrawnEventArgs e)
{
var selectedWindow = (Window) windowRulesListBox.SelectedItem;
if (selectedWindow == null)
{
return;
}
 
WindowLeft.Text = e.Left.ToString();
WindowTop.Text = e.Top.ToString();
WindowWidth.Text = e.Width.ToString();
WindowHeight.Text = e.Height.ToString();
 
selectedWindow.Left = e.Left;
selectedWindow.Top = e.Top;
selectedWindow.Width = e.Width;
selectedWindow.Height = e.Height;
}
 
private void DrawOverlayForm_Closed(object sender, EventArgs e)
{
DrawOverlayForm.Closed -= DrawOverlayForm_Closed;
DrawOverlayForm.WindowDrawn -= DrawOverlayForm_WindowDrawn;
DrawOverlayForm.Dispose();
DrawOverlayForm = null;
}
}
}
/trunk/Widow/Widow.csproj
@@ -96,6 +96,7 @@
<Compile Include="Utilities.cs" />
<Compile Include="WindowCreatedEventArgs.cs" />
<Compile Include="WindowDestroyedEventArgs.cs" />
<Compile Include="WindowModification.cs" />
<EmbeddedResource Include="AboutForm.resx">
<DependentUpon>AboutForm.cs</DependentUpon>
</EmbeddedResource>
/trunk/Widow/WindowManipulation.cs
@@ -11,12 +11,6 @@
{
public class WindowManipulation : IDisposable
{
#region Public Events & Delegates
 
public event EventHandler<WindowManipulatedEventArgs> WindowManipulated;
 
#endregion
 
#region Public Enums, Properties and Fields
 
public bool OnWindowCreate { get; set; }
@@ -37,9 +31,9 @@
 
private Task ApplyEveryTask { get; }
 
private BufferBlock<Window> WindowsBufferBlock { get; }
private BufferBlock<WindowModification> WindowsBufferBlock { get; }
 
private ActionBlock<Window> WindowsActionBlock { get; }
private ActionBlock<WindowModification> WindowsActionBlock { get; }
 
private IDisposable WindowsLink { get; set; }
 
@@ -50,8 +44,8 @@
public WindowManipulation()
{
CancellationTokenSource = new CancellationTokenSource();
WindowsBufferBlock = new BufferBlock<Window>();
WindowsActionBlock = new ActionBlock<Window>(ManipulateWindows);
WindowsBufferBlock = new BufferBlock<WindowModification>();
WindowsActionBlock = new ActionBlock<WindowModification>(ManipulateWindows);
WindowsLink = WindowsBufferBlock.LinkTo(WindowsActionBlock);
 
ApplyEveryTask = ApplyEvery(CancellationTokenSource.Token);
@@ -104,7 +98,8 @@
return;
}
 
if (!WindowsToManipulate.TryGetWindow(e.Title, out _))
var @class = Helpers.GetWindowClass(e.Handle);
if (!WindowsToManipulate.TryGetWindow(new WindowHash(e.Title, @class), out _))
{
return;
}
@@ -118,25 +113,32 @@
 
public async Task Apply()
{
var windows = new List<Window>();
foreach (var hWnd in Helpers.EnumerateWindows())
var windows = new List<WindowModification>();
foreach (var hWnd in Helpers.FindWindows((wnd, param) => true))
{
var title = Helpers.GetWindowTitle(hWnd);
var windowTitle = Helpers.GetWindowTitle(hWnd);
 
if (string.IsNullOrEmpty(title))
if (string.IsNullOrEmpty(windowTitle))
{
continue;
}
 
if (!WindowsToManipulate.TryGetWindow(title, out var window))
var windowClass = Helpers.GetWindowClass(hWnd);
if (string.IsNullOrEmpty(windowClass))
{
continue;
}
 
windows.Add(window);
var windowHash = new WindowHash(windowTitle, windowClass);
if (!WindowsToManipulate.TryGetWindow(windowHash, out var window))
{
continue;
}
 
windows.Add(new WindowModification(hWnd, window));
}
 
await Task.WhenAll(windows.Select(window => WindowsBufferBlock.SendAsync(window)));
await Task.WhenAll(windows.Select(modification => WindowsBufferBlock.SendAsync(modification)));
}
 
#endregion
@@ -143,48 +145,43 @@
 
#region Private Methods
 
private void ManipulateWindows(Window window)
private static void ManipulateWindows(WindowModification modification)
{
foreach (var hWnd in Helpers.FindWindowsWithText(window.Title))
if (modification.Handle == IntPtr.Zero)
{
if (hWnd == IntPtr.Zero)
{
continue;
}
return;
}
 
if (!Natives.GetWindowRect(hWnd, out var rect))
{
continue;
}
if (!Natives.GetWindowRect(modification.Handle, out var rect))
{
return;
}
 
var left = window.Left;
if (window.IgnoreLeft)
{
left = rect.Left;
}
var left = modification.Window.Left;
if (modification.Window.IgnoreLeft)
{
left = rect.Left;
}
 
var top = window.Top;
if (window.IgnoreTop)
{
top = rect.Top;
}
var top = modification.Window.Top;
if (modification.Window.IgnoreTop)
{
top = rect.Top;
}
 
var width = window.Width;
if (window.IgnoreWidth)
{
width = rect.Left - rect.Right;
}
var width = modification.Window.Width;
if (modification.Window.IgnoreWidth)
{
width = rect.Left - rect.Right;
}
 
var height = window.Height;
if (window.IgnoreHeight)
{
height = rect.Top - rect.Bottom;
}
var height = modification.Window.Height;
if (modification.Window.IgnoreHeight)
{
height = rect.Top - rect.Bottom;
}
 
var success = Natives.MoveWindow(hWnd, left, top, width, height, true);
 
WindowManipulated?.Invoke(this, new WindowManipulatedEventArgs(success, window));
}
Natives.MoveWindow(modification.Handle, left, top, width, height, true);
}
 
private async Task ApplyEvery(CancellationToken cancellationToken)
/trunk/Widow/WindowModification.cs
@@ -0,0 +1,26 @@
using System;
using Windows;
 
namespace Widow
{
public class WindowModification
{
#region Public Enums, Properties and Fields
 
public Window Window { get; set; }
 
public IntPtr Handle { get; set; }
 
#endregion
 
#region Constructors, Destructors and Finalizers
 
public WindowModification(IntPtr handle, Window window)
{
this.Handle = handle;
Window = window;
}
 
#endregion
}
}
/trunk/Windows/Window.cs
@@ -11,17 +11,17 @@
#region Public Enums, Properties and Fields
 
[XmlElement(ElementName = "Process")]
public string Process
public string Class
{
get => _process;
get => _class;
set
{
if (value == _process)
if (value == _class)
{
return;
}
 
_process = value;
_class = value;
OnPropertyChanged();
}
}
@@ -174,6 +174,8 @@
 
#region Private Delegates, Events, Enums, Properties, Indexers and Fields
 
private string _class;
 
private int _height;
 
private bool _ignoreHeight;
@@ -186,8 +188,6 @@
 
private int _left;
 
private string _process;
 
private string _title;
 
private int _top;
@@ -203,9 +203,9 @@
{
}
 
public Window(string process, string title, int top, int left, int width, int height) : this()
public Window(string @class, string title, int top, int left, int width, int height) : this()
{
Process = process;
Class = @class;
Title = title;
Top = top;
Left = left;
/trunk/Windows/WindowHash.cs
@@ -0,0 +1,76 @@
using System;
 
namespace Windows
{
public class WindowHash : IEquatable<WindowHash>
{
#region Public Enums, Properties and Fields
 
public string Title { get; }
 
public string Class { get; }
 
#endregion
 
#region Constructors, Destructors and Finalizers
 
public WindowHash(string title, string @class)
{
Title = title;
Class = @class;
}
 
#endregion
 
#region Interface
 
public bool Equals(WindowHash other)
{
if (ReferenceEquals(null, other))
{
return false;
}
 
if (ReferenceEquals(this, other))
{
return true;
}
 
return string.Equals(Title, other.Title) && string.Equals(Class, other.Class);
}
 
#endregion
 
#region Public Overrides
 
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj))
{
return false;
}
 
if (ReferenceEquals(this, obj))
{
return true;
}
 
if (obj.GetType() != GetType())
{
return false;
}
 
return Equals((WindowHash) obj);
}
 
public override int GetHashCode()
{
unchecked
{
return (Title != null ? Title.GetHashCode() : 0) * 397 ^ (Class != null ? Class.GetHashCode() : 0);
}
}
 
#endregion
}
}
/trunk/Windows/Windows.cs
@@ -34,12 +34,14 @@
{
_window.Add(window);
 
if (_windows.ContainsKey(window.Title))
var windowHash = new WindowHash(window.Title, window.Class);
 
if (_windows.ContainsKey(windowHash))
{
continue;
}
 
_windows.Add(window.Title, window);
_windows.Add(windowHash, window);
}
 
_window.CollectionChanged += Window_CollectionChanged;
@@ -53,7 +55,7 @@
 
private readonly ObservableCollection<Window> _window = new ObservableCollection<Window>();
 
private readonly Dictionary<string, Window> _windows = new Dictionary<string, Window>();
private readonly Dictionary<WindowHash, Window> _windows = new Dictionary<WindowHash, Window>();
 
#endregion
 
@@ -86,9 +88,11 @@
{
foreach (var window in e.OldItems.OfType<Window>())
{
if (_windows.ContainsKey(window.Title))
var windowHash = new WindowHash(window.Title, window.Class);
 
if (_windows.ContainsKey(windowHash))
{
_windows.Remove(window.Title);
_windows.Remove(windowHash);
}
}
}
@@ -98,9 +102,11 @@
{
foreach (var window in e.NewItems.OfType<Window>())
{
if (!_windows.ContainsKey(window.Title))
var windowHash = new WindowHash(window.Title, window.Class);
 
if (!_windows.ContainsKey(windowHash))
{
_windows.Add(window.Title, window);
_windows.Add(windowHash, window);
}
}
}
@@ -110,9 +116,9 @@
 
#region Public Methods
 
public bool TryGetWindow(string title, out Window window)
public bool TryGetWindow(WindowHash hash, out Window window)
{
return _windows.TryGetValue(title, out window);
return _windows.TryGetValue(hash, out window);
}
 
#endregion
/trunk/Windows/Windows.csproj
@@ -43,6 +43,7 @@
<ItemGroup>
<Compile Include="Properties\Annotations.cs" />
<Compile Include="Window.cs" />
<Compile Include="WindowHash.cs" />
<Compile Include="Windows.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>