Widow – Blame information for rev 14
?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 | |||
11 | office | 28 | private Windows.Windows WindowsToManipulate { get; } |
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 | |||
11 | office | 61 | public WindowManipulation(MainForm mainForm, Windows.Windows windowsToManipulate) : this(mainForm) |
1 | office | 62 | { |
11 | office | 63 | WindowsToManipulate = windowsToManipulate; |
1 | office | 64 | } |
65 | |||
12 | office | 66 | public WindowManipulation(MainForm mainForm, Windows.Windows windowsToManipulate, Settings settings) : this( |
67 | mainForm, |
||
11 | office | 68 | windowsToManipulate) |
9 | office | 69 | { |
70 | OnWindowCreate = settings.OnWindowCreate; |
||
71 | ApplyEveryTimeEnabled = settings.ApplyEveryTimeEnabled; |
||
72 | if (int.TryParse(settings.ApplyEveryTime, out var time)) |
||
73 | { |
||
74 | ApplyEveryTime = time; |
||
75 | } |
||
76 | } |
||
77 | |||
1 | office | 78 | public void Dispose() |
79 | { |
||
11 | office | 80 | WindowsLink?.Dispose(); |
81 | WindowsLink = null; |
||
82 | |||
1 | office | 83 | Form.WindowCreated -= Form_WindowCreated; |
8 | office | 84 | CancellationTokenSource.Cancel(); |
85 | ApplyEveryTask.Wait(); |
||
86 | CancellationTokenSource.Dispose(); |
||
87 | CancellationTokenSource = null; |
||
1 | office | 88 | } |
89 | |||
90 | #endregion |
||
91 | |||
92 | #region Event Handlers |
||
93 | |||
11 | office | 94 | private async void Form_WindowCreated(object sender, WindowCreatedEventArgs e) |
1 | office | 95 | { |
96 | if (!OnWindowCreate) |
||
97 | { |
||
98 | return; |
||
99 | } |
||
100 | |||
14 | office | 101 | var @class = Helpers.GetWindowClass(e.Handle); |
102 | if (!WindowsToManipulate.TryGetWindow(new WindowHash(e.Title, @class), out _)) |
||
1 | office | 103 | { |
9 | office | 104 | return; |
105 | } |
||
1 | office | 106 | |
11 | office | 107 | await Apply(); |
1 | office | 108 | } |
109 | |||
110 | #endregion |
||
7 | office | 111 | |
112 | #region Public Methods |
||
113 | |||
11 | office | 114 | public async Task Apply() |
7 | office | 115 | { |
14 | office | 116 | var windows = new List<WindowModification>(); |
117 | foreach (var hWnd in Helpers.FindWindows((wnd, param) => true)) |
||
12 | office | 118 | { |
14 | office | 119 | var windowTitle = Helpers.GetWindowTitle(hWnd); |
12 | office | 120 | |
14 | office | 121 | if (string.IsNullOrEmpty(windowTitle)) |
12 | office | 122 | { |
123 | continue; |
||
124 | } |
||
125 | |||
14 | office | 126 | var windowClass = Helpers.GetWindowClass(hWnd); |
127 | if (string.IsNullOrEmpty(windowClass)) |
||
12 | office | 128 | { |
129 | continue; |
||
130 | } |
||
131 | |||
14 | office | 132 | var windowHash = new WindowHash(windowTitle, windowClass); |
133 | if (!WindowsToManipulate.TryGetWindow(windowHash, out var window)) |
||
134 | { |
||
135 | continue; |
||
136 | } |
||
137 | |||
138 | windows.Add(new WindowModification(hWnd, window)); |
||
12 | office | 139 | } |
140 | |||
14 | office | 141 | await Task.WhenAll(windows.Select(modification => WindowsBufferBlock.SendAsync(modification))); |
11 | office | 142 | } |
143 | |||
144 | #endregion |
||
145 | |||
146 | #region Private Methods |
||
147 | |||
14 | office | 148 | private static void ManipulateWindows(WindowModification modification) |
11 | office | 149 | { |
14 | office | 150 | if (modification.Handle == IntPtr.Zero) |
7 | office | 151 | { |
14 | office | 152 | return; |
153 | } |
||
7 | office | 154 | |
14 | office | 155 | if (!Natives.GetWindowRect(modification.Handle, out var rect)) |
156 | { |
||
157 | return; |
||
158 | } |
||
9 | office | 159 | |
14 | office | 160 | var left = modification.Window.Left; |
161 | if (modification.Window.IgnoreLeft) |
||
162 | { |
||
163 | left = rect.Left; |
||
164 | } |
||
9 | office | 165 | |
14 | office | 166 | var top = modification.Window.Top; |
167 | if (modification.Window.IgnoreTop) |
||
168 | { |
||
169 | top = rect.Top; |
||
170 | } |
||
9 | office | 171 | |
14 | office | 172 | var width = modification.Window.Width; |
173 | if (modification.Window.IgnoreWidth) |
||
174 | { |
||
175 | width = rect.Left - rect.Right; |
||
176 | } |
||
9 | office | 177 | |
14 | office | 178 | var height = modification.Window.Height; |
179 | if (modification.Window.IgnoreHeight) |
||
180 | { |
||
181 | height = rect.Top - rect.Bottom; |
||
182 | } |
||
9 | office | 183 | |
14 | office | 184 | Natives.MoveWindow(modification.Handle, left, top, width, height, true); |
7 | office | 185 | } |
186 | |||
8 | office | 187 | private async Task ApplyEvery(CancellationToken cancellationToken) |
188 | { |
||
189 | do |
||
190 | { |
||
191 | if (!ApplyEveryTimeEnabled) |
||
192 | { |
||
193 | await Task.Delay(1000, cancellationToken); |
||
194 | continue; |
||
195 | } |
||
196 | |||
197 | await Task.Delay(ApplyEveryTime, cancellationToken); |
||
198 | |||
11 | office | 199 | await Apply(); |
8 | office | 200 | } while (!cancellationToken.IsCancellationRequested); |
201 | } |
||
202 | |||
203 | #endregion |
||
1 | office | 204 | } |
205 | } |