Widow – Blame information for rev 18
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | using System; |
12 | office | 2 | using System.Collections.Generic; |
11 | office | 3 | using System.Linq; |
8 | office | 4 | using System.Threading; |
5 | using System.Threading.Tasks; |
||
11 | office | 6 | using System.Threading.Tasks.Dataflow; |
7 | using Windows; |
||
9 | office | 8 | using Widow.Properties; |
1 | office | 9 | |
10 | namespace Widow |
||
11 | { |
||
9 | office | 12 | public class WindowManipulation : IDisposable |
1 | office | 13 | { |
14 | #region Public Enums, Properties and Fields |
||
15 | |||
16 | public bool OnWindowCreate { get; set; } |
||
17 | |||
8 | office | 18 | public int ApplyEveryTime { get; set; } |
1 | office | 19 | |
8 | office | 20 | public bool ApplyEveryTimeEnabled { get; set; } |
21 | |||
1 | office | 22 | #endregion |
23 | |||
24 | #region Private Delegates, Events, Enums, Properties, Indexers and Fields |
||
25 | |||
8 | office | 26 | private MainForm Form { get; } |
27 | |||
18 | office | 28 | private Windows.Windows WindowsToManipulate { get; set; } |
1 | office | 29 | |
8 | office | 30 | private CancellationTokenSource CancellationTokenSource { get; set; } |
31 | |||
32 | private Task ApplyEveryTask { get; } |
||
33 | |||
14 | office | 34 | private BufferBlock<WindowModification> WindowsBufferBlock { get; } |
11 | office | 35 | |
14 | office | 36 | private ActionBlock<WindowModification> WindowsActionBlock { get; } |
11 | office | 37 | |
38 | private IDisposable WindowsLink { get; set; } |
||
39 | |||
1 | office | 40 | #endregion |
41 | |||
42 | #region Constructors, Destructors and Finalizers |
||
43 | |||
9 | office | 44 | public WindowManipulation() |
1 | office | 45 | { |
8 | office | 46 | CancellationTokenSource = new CancellationTokenSource(); |
14 | office | 47 | WindowsBufferBlock = new BufferBlock<WindowModification>(); |
48 | WindowsActionBlock = new ActionBlock<WindowModification>(ManipulateWindows); |
||
11 | office | 49 | WindowsLink = WindowsBufferBlock.LinkTo(WindowsActionBlock); |
50 | |||
8 | office | 51 | ApplyEveryTask = ApplyEvery(CancellationTokenSource.Token); |
1 | office | 52 | } |
53 | |||
9 | office | 54 | public WindowManipulation(MainForm mainForm) : this() |
1 | office | 55 | { |
6 | office | 56 | Form = mainForm; |
1 | office | 57 | |
58 | Form.WindowCreated += Form_WindowCreated; |
||
59 | } |
||
60 | |||
18 | office | 61 | public WindowManipulation(Settings settings, MainForm mainForm) : this(mainForm) |
1 | office | 62 | { |
9 | office | 63 | OnWindowCreate = settings.OnWindowCreate; |
64 | ApplyEveryTimeEnabled = settings.ApplyEveryTimeEnabled; |
||
65 | if (int.TryParse(settings.ApplyEveryTime, out var time)) |
||
66 | { |
||
67 | ApplyEveryTime = time; |
||
68 | } |
||
69 | } |
||
70 | |||
1 | office | 71 | public void Dispose() |
72 | { |
||
11 | office | 73 | WindowsLink?.Dispose(); |
74 | WindowsLink = null; |
||
75 | |||
1 | office | 76 | Form.WindowCreated -= Form_WindowCreated; |
8 | office | 77 | CancellationTokenSource.Cancel(); |
78 | ApplyEveryTask.Wait(); |
||
79 | CancellationTokenSource.Dispose(); |
||
80 | CancellationTokenSource = null; |
||
1 | office | 81 | } |
82 | |||
83 | #endregion |
||
84 | |||
85 | #region Event Handlers |
||
86 | |||
11 | office | 87 | private async void Form_WindowCreated(object sender, WindowCreatedEventArgs e) |
1 | office | 88 | { |
89 | if (!OnWindowCreate) |
||
90 | { |
||
91 | return; |
||
92 | } |
||
93 | |||
18 | office | 94 | if (WindowsToManipulate == null) |
95 | { |
||
96 | return; |
||
97 | } |
||
98 | |||
14 | office | 99 | var @class = Helpers.GetWindowClass(e.Handle); |
100 | if (!WindowsToManipulate.TryGetWindow(new WindowHash(e.Title, @class), out _)) |
||
1 | office | 101 | { |
9 | office | 102 | return; |
103 | } |
||
1 | office | 104 | |
11 | office | 105 | await Apply(); |
1 | office | 106 | } |
107 | |||
108 | #endregion |
||
7 | office | 109 | |
110 | #region Public Methods |
||
111 | |||
18 | office | 112 | public void AddWindows(Windows.Windows windows) |
113 | { |
||
114 | WindowsToManipulate = windows; |
||
115 | } |
||
116 | |||
11 | office | 117 | public async Task Apply() |
7 | office | 118 | { |
18 | office | 119 | if (WindowsToManipulate == null) |
120 | { |
||
121 | return; |
||
122 | } |
||
123 | |||
14 | office | 124 | var windows = new List<WindowModification>(); |
125 | foreach (var hWnd in Helpers.FindWindows((wnd, param) => true)) |
||
12 | office | 126 | { |
14 | office | 127 | var windowTitle = Helpers.GetWindowTitle(hWnd); |
12 | office | 128 | |
14 | office | 129 | if (string.IsNullOrEmpty(windowTitle)) |
12 | office | 130 | { |
131 | continue; |
||
132 | } |
||
133 | |||
14 | office | 134 | var windowClass = Helpers.GetWindowClass(hWnd); |
135 | if (string.IsNullOrEmpty(windowClass)) |
||
12 | office | 136 | { |
137 | continue; |
||
138 | } |
||
139 | |||
14 | office | 140 | var windowHash = new WindowHash(windowTitle, windowClass); |
141 | if (!WindowsToManipulate.TryGetWindow(windowHash, out var window)) |
||
142 | { |
||
143 | continue; |
||
144 | } |
||
145 | |||
146 | windows.Add(new WindowModification(hWnd, window)); |
||
12 | office | 147 | } |
148 | |||
14 | office | 149 | await Task.WhenAll(windows.Select(modification => WindowsBufferBlock.SendAsync(modification))); |
11 | office | 150 | } |
151 | |||
152 | #endregion |
||
153 | |||
154 | #region Private Methods |
||
155 | |||
14 | office | 156 | private static void ManipulateWindows(WindowModification modification) |
11 | office | 157 | { |
14 | office | 158 | if (modification.Handle == IntPtr.Zero) |
7 | office | 159 | { |
14 | office | 160 | return; |
161 | } |
||
7 | office | 162 | |
14 | office | 163 | if (!Natives.GetWindowRect(modification.Handle, out var rect)) |
164 | { |
||
165 | return; |
||
166 | } |
||
9 | office | 167 | |
14 | office | 168 | var left = modification.Window.Left; |
169 | if (modification.Window.IgnoreLeft) |
||
170 | { |
||
171 | left = rect.Left; |
||
172 | } |
||
9 | office | 173 | |
14 | office | 174 | var top = modification.Window.Top; |
175 | if (modification.Window.IgnoreTop) |
||
176 | { |
||
177 | top = rect.Top; |
||
178 | } |
||
9 | office | 179 | |
14 | office | 180 | var width = modification.Window.Width; |
181 | if (modification.Window.IgnoreWidth) |
||
182 | { |
||
183 | width = rect.Left - rect.Right; |
||
184 | } |
||
9 | office | 185 | |
14 | office | 186 | var height = modification.Window.Height; |
187 | if (modification.Window.IgnoreHeight) |
||
188 | { |
||
189 | height = rect.Top - rect.Bottom; |
||
190 | } |
||
9 | office | 191 | |
14 | office | 192 | Natives.MoveWindow(modification.Handle, left, top, width, height, true); |
7 | office | 193 | } |
194 | |||
8 | office | 195 | private async Task ApplyEvery(CancellationToken cancellationToken) |
196 | { |
||
197 | do |
||
198 | { |
||
199 | if (!ApplyEveryTimeEnabled) |
||
200 | { |
||
201 | await Task.Delay(1000, cancellationToken); |
||
202 | continue; |
||
203 | } |
||
204 | |||
205 | await Task.Delay(ApplyEveryTime, cancellationToken); |
||
206 | |||
11 | office | 207 | await Apply(); |
8 | office | 208 | } while (!cancellationToken.IsCancellationRequested); |
209 | } |
||
210 | |||
211 | #endregion |
||
1 | office | 212 | } |
213 | } |