GlowEdge.cs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586
  1. using System;
  2. using System.Runtime.InteropServices;
  3. using System.Windows.Controls;
  4. using System.Windows.Interop;
  5. using System.Windows.Media;
  6. using HandyControl.Controls;
  7. using HandyControl.Tools.Interop;
  8. namespace HandyControl.Data;
  9. internal class GlowEdge : HwndWrapper
  10. {
  11. private const string GlowEdgeClassName = "HandyControlGlowEdge";
  12. private const int GlowDepth = 9;
  13. private const int CornerGripThickness = 18;
  14. private static ushort _sharedWindowClassAtom;
  15. // ReSharper disable once NotAccessedField.Local
  16. private static InteropValues.WndProc _sharedWndProc;
  17. private readonly GlowBitmap[] _activeGlowBitmaps = new GlowBitmap[16];
  18. private readonly GlowBitmap[] _inactiveGlowBitmaps = new GlowBitmap[16];
  19. private readonly Dock _orientation;
  20. private readonly GlowWindow _targetWindow;
  21. private Color _activeGlowColor = Colors.Transparent;
  22. private int _height;
  23. private Color _inactiveGlowColor = Colors.Transparent;
  24. private FieldInvalidationTypes _invalidatedValues;
  25. private bool _isActive;
  26. private bool _isVisible;
  27. private int _left;
  28. private bool _pendingDelayRender;
  29. private int _top;
  30. private int _width;
  31. internal static long CreatedGlowEdges { get; private set; }
  32. internal static long DisposedGlowEdges { get; private set; }
  33. internal GlowEdge(GlowWindow owner, Dock orientation)
  34. {
  35. _targetWindow = owner ?? throw new ArgumentNullException(nameof(owner));
  36. _orientation = orientation;
  37. CreatedGlowEdges += 1L;
  38. }
  39. private bool IsDeferringChanges => _targetWindow.DeferGlowChangesCount > 0;
  40. private static ushort SharedWindowClassAtom
  41. {
  42. get
  43. {
  44. if (_sharedWindowClassAtom == 0)
  45. {
  46. var wndclass = default(InteropValues.WNDCLASS);
  47. wndclass.cbClsExtra = 0;
  48. wndclass.cbWndExtra = 0;
  49. wndclass.hbrBackground = IntPtr.Zero;
  50. wndclass.hCursor = IntPtr.Zero;
  51. wndclass.hIcon = IntPtr.Zero;
  52. wndclass.lpfnWndProc = _sharedWndProc = InteropMethods.DefWindowProc;
  53. wndclass.lpszClassName = GlowEdgeClassName;
  54. wndclass.lpszMenuName = null;
  55. wndclass.style = 0u;
  56. _sharedWindowClassAtom = InteropMethods.RegisterClass(ref wndclass);
  57. }
  58. return _sharedWindowClassAtom;
  59. }
  60. }
  61. internal bool IsVisible
  62. {
  63. get => _isVisible;
  64. set => UpdateProperty(ref _isVisible, value, FieldInvalidationTypes.Render | FieldInvalidationTypes.Visibility);
  65. }
  66. internal int Left
  67. {
  68. get => _left;
  69. set => UpdateProperty(ref _left, value, FieldInvalidationTypes.Location);
  70. }
  71. internal int Top
  72. {
  73. get => _top;
  74. set => UpdateProperty(ref _top, value, FieldInvalidationTypes.Location);
  75. }
  76. internal int Width
  77. {
  78. get => _width;
  79. set => UpdateProperty(ref _width, value, FieldInvalidationTypes.Size | FieldInvalidationTypes.Render);
  80. }
  81. internal int Height
  82. {
  83. get => _height;
  84. set => UpdateProperty(ref _height, value, FieldInvalidationTypes.Size | FieldInvalidationTypes.Render);
  85. }
  86. internal bool IsActive
  87. {
  88. get => _isActive;
  89. set => UpdateProperty(ref _isActive, value, FieldInvalidationTypes.Render);
  90. }
  91. internal Color ActiveGlowColor
  92. {
  93. get => _activeGlowColor;
  94. set => UpdateProperty(ref _activeGlowColor, value, FieldInvalidationTypes.ActiveColor | FieldInvalidationTypes.Render);
  95. }
  96. internal Color InactiveGlowColor
  97. {
  98. get => _inactiveGlowColor;
  99. set => UpdateProperty(ref _inactiveGlowColor, value, FieldInvalidationTypes.InactiveColor | FieldInvalidationTypes.Render);
  100. }
  101. private IntPtr TargetWindowHandle => new WindowInteropHelper(_targetWindow).Handle;
  102. protected override bool IsWindowSubclassed => true;
  103. private bool IsPositionValid => (_invalidatedValues & (FieldInvalidationTypes.Location | FieldInvalidationTypes.Size | FieldInvalidationTypes.Visibility)) == FieldInvalidationTypes.None;
  104. private void UpdateProperty<T>(ref T field, T value, FieldInvalidationTypes invalidatedValues) where T : struct
  105. {
  106. if (!field.Equals(value))
  107. {
  108. field = value;
  109. _invalidatedValues |= invalidatedValues;
  110. if (!IsDeferringChanges) CommitChanges();
  111. }
  112. }
  113. protected override ushort CreateWindowClassCore() => SharedWindowClassAtom;
  114. protected override void DestroyWindowClassCore()
  115. {
  116. }
  117. protected override IntPtr CreateWindowCore()
  118. {
  119. return InteropMethods.CreateWindowEx(
  120. 524416,
  121. new IntPtr(WindowClassAtom),
  122. string.Empty,
  123. -2046820352,
  124. 0,
  125. 0,
  126. 0,
  127. 0,
  128. new WindowInteropHelper(_targetWindow).Owner,
  129. IntPtr.Zero,
  130. IntPtr.Zero,
  131. IntPtr.Zero);
  132. }
  133. internal void ChangeOwner(IntPtr newOwner) => InteropMethods.SetWindowLongPtr(Handle, InteropValues.GWLP.HWNDPARENT, newOwner);
  134. protected override IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam)
  135. {
  136. if (msg <= 70)
  137. {
  138. if (msg == 6) return IntPtr.Zero;
  139. if (msg == 70)
  140. {
  141. var windowpos = (InteropValues.WINDOWPOS) Marshal.PtrToStructure(lParam, typeof(InteropValues.WINDOWPOS));
  142. windowpos.flags |= 16u;
  143. Marshal.StructureToPtr(windowpos, lParam, true);
  144. }
  145. }
  146. else
  147. {
  148. if (msg != 126)
  149. {
  150. if (msg == 132) return new IntPtr(WmNcHitTest(lParam));
  151. switch (msg)
  152. {
  153. case 161:
  154. case 163:
  155. case 164:
  156. case 166:
  157. case 167:
  158. case 169:
  159. case 171:
  160. case 173:
  161. {
  162. var targetWindowHandle = TargetWindowHandle;
  163. InteropMethods.SendMessage(targetWindowHandle, 6, new IntPtr(2), IntPtr.Zero);
  164. InteropMethods.SendMessage(targetWindowHandle, msg, wParam, IntPtr.Zero);
  165. return IntPtr.Zero;
  166. }
  167. }
  168. }
  169. else
  170. {
  171. if (IsVisible) RenderLayeredWindow();
  172. }
  173. }
  174. return base.WndProc(hwnd, msg, wParam, lParam);
  175. }
  176. private int WmNcHitTest(IntPtr lParam)
  177. {
  178. var xLParam = InteropMethods.GetXLParam(lParam.ToInt32());
  179. var yLParam = InteropMethods.GetYLParam(lParam.ToInt32());
  180. InteropMethods.GetWindowRect(Handle, out var rect);
  181. switch (_orientation)
  182. {
  183. case Dock.Left:
  184. if (yLParam - CornerGripThickness < rect.Top) return 13;
  185. if (yLParam + CornerGripThickness > rect.Bottom) return 16;
  186. return 10;
  187. case Dock.Top:
  188. if (xLParam - CornerGripThickness < rect.Left) return 13;
  189. if (xLParam + CornerGripThickness > rect.Right) return 14;
  190. return 12;
  191. case Dock.Right:
  192. if (yLParam - CornerGripThickness < rect.Top) return 14;
  193. if (yLParam + CornerGripThickness > rect.Bottom) return 17;
  194. return 11;
  195. default:
  196. if (xLParam - CornerGripThickness < rect.Left) return 16;
  197. if (xLParam + CornerGripThickness > rect.Right) return 17;
  198. return 15;
  199. }
  200. }
  201. internal void CommitChanges()
  202. {
  203. InvalidateCachedBitmaps();
  204. UpdateWindowPosCore();
  205. UpdateLayeredWindowCore();
  206. _invalidatedValues = FieldInvalidationTypes.None;
  207. }
  208. private void InvalidateCachedBitmaps()
  209. {
  210. if (_invalidatedValues.HasFlag(FieldInvalidationTypes.ActiveColor)) ClearCache(_activeGlowBitmaps);
  211. if (_invalidatedValues.HasFlag(FieldInvalidationTypes.InactiveColor)) ClearCache(_inactiveGlowBitmaps);
  212. }
  213. private void UpdateWindowPosCore()
  214. {
  215. if (_invalidatedValues.HasFlag(FieldInvalidationTypes.Location) ||
  216. _invalidatedValues.HasFlag(FieldInvalidationTypes.Size) ||
  217. _invalidatedValues.HasFlag(FieldInvalidationTypes.Visibility))
  218. {
  219. var num = 532;
  220. if (_invalidatedValues.HasFlag(FieldInvalidationTypes.Visibility))
  221. {
  222. if (IsVisible)
  223. num |= 64;
  224. else
  225. num |= 131;
  226. }
  227. if (!_invalidatedValues.HasFlag(FieldInvalidationTypes.Location)) num |= 2;
  228. if (!_invalidatedValues.HasFlag(FieldInvalidationTypes.Size)) num |= 1;
  229. InteropMethods.SetWindowPos(Handle, IntPtr.Zero, Left, Top, Width, Height, num);
  230. }
  231. }
  232. private void UpdateLayeredWindowCore()
  233. {
  234. if (IsVisible && _invalidatedValues.HasFlag(FieldInvalidationTypes.Render))
  235. {
  236. if (IsPositionValid)
  237. {
  238. BeginDelayedRender();
  239. return;
  240. }
  241. CancelDelayedRender();
  242. RenderLayeredWindow();
  243. }
  244. }
  245. private void BeginDelayedRender()
  246. {
  247. if (!_pendingDelayRender)
  248. {
  249. _pendingDelayRender = true;
  250. CompositionTarget.Rendering += CommitDelayedRender;
  251. }
  252. }
  253. private void CancelDelayedRender()
  254. {
  255. if (_pendingDelayRender)
  256. {
  257. _pendingDelayRender = false;
  258. CompositionTarget.Rendering -= CommitDelayedRender;
  259. }
  260. }
  261. private void CommitDelayedRender(object sender, EventArgs e)
  262. {
  263. CancelDelayedRender();
  264. if (IsVisible) RenderLayeredWindow();
  265. }
  266. private void RenderLayeredWindow()
  267. {
  268. using var glowDrawingContext = new GlowDrawingContext(Width, Height);
  269. if (glowDrawingContext.IsInitialized)
  270. {
  271. switch (_orientation)
  272. {
  273. case Dock.Left:
  274. DrawLeft(glowDrawingContext);
  275. break;
  276. case Dock.Top:
  277. DrawTop(glowDrawingContext);
  278. break;
  279. case Dock.Right:
  280. DrawRight(glowDrawingContext);
  281. break;
  282. default:
  283. DrawBottom(glowDrawingContext);
  284. break;
  285. }
  286. var point = new InteropValues.POINT
  287. {
  288. X = Left,
  289. Y = Top
  290. };
  291. var size = new InteropValues.SIZE
  292. {
  293. cx = Width,
  294. cy = Height
  295. };
  296. var point2 = new InteropValues.POINT
  297. {
  298. X = 0,
  299. Y = 0
  300. };
  301. InteropMethods.UpdateLayeredWindow(
  302. Handle,
  303. glowDrawingContext.ScreenDC,
  304. ref point,
  305. ref size,
  306. glowDrawingContext.WindowDC,
  307. ref point2,
  308. 0u,
  309. ref glowDrawingContext.Blend,
  310. 2u);
  311. }
  312. }
  313. private GlowBitmap GetOrCreateBitmap(GlowDrawingContext drawingContext, GlowBitmapPart bitmapPart)
  314. {
  315. GlowBitmap[] array;
  316. Color color;
  317. if (IsActive)
  318. {
  319. array = _activeGlowBitmaps;
  320. color = ActiveGlowColor;
  321. }
  322. else
  323. {
  324. array = _inactiveGlowBitmaps;
  325. color = InactiveGlowColor;
  326. }
  327. return array[(int) bitmapPart] ?? (array[(int) bitmapPart] = GlowBitmap.Create(drawingContext, bitmapPart, color));
  328. }
  329. private void ClearCache(GlowBitmap[] cache)
  330. {
  331. for (var i = 0; i < cache.Length; i++)
  332. using (cache[i])
  333. {
  334. cache[i] = null;
  335. }
  336. }
  337. protected override void DisposeManagedResources()
  338. {
  339. ClearCache(_activeGlowBitmaps);
  340. ClearCache(_inactiveGlowBitmaps);
  341. }
  342. protected override void DisposeNativeResources()
  343. {
  344. base.DisposeNativeResources();
  345. DisposedGlowEdges += 1L;
  346. }
  347. private void DrawLeft(GlowDrawingContext drawingContext)
  348. {
  349. var orCreateBitmap = GetOrCreateBitmap(drawingContext, GlowBitmapPart.CornerTopLeft);
  350. var orCreateBitmap2 = GetOrCreateBitmap(drawingContext, GlowBitmapPart.LeftTop);
  351. var orCreateBitmap3 = GetOrCreateBitmap(drawingContext, GlowBitmapPart.Left);
  352. var orCreateBitmap4 = GetOrCreateBitmap(drawingContext, GlowBitmapPart.LeftBottom);
  353. var orCreateBitmap5 = GetOrCreateBitmap(drawingContext, GlowBitmapPart.CornerBottomLeft);
  354. var height = orCreateBitmap.Height;
  355. var num = height + orCreateBitmap2.Height;
  356. var num2 = drawingContext.Height - orCreateBitmap5.Height;
  357. var num3 = num2 - orCreateBitmap4.Height;
  358. var num4 = num3 - num;
  359. InteropMethods.SelectObject(drawingContext.BackgroundDC, orCreateBitmap.Handle);
  360. InteropMethods.AlphaBlend(drawingContext.WindowDC, 0, 0, orCreateBitmap.Width, orCreateBitmap.Height,
  361. drawingContext.BackgroundDC, 0, 0, orCreateBitmap.Width, orCreateBitmap.Height,
  362. drawingContext.Blend);
  363. InteropMethods.SelectObject(drawingContext.BackgroundDC, orCreateBitmap2.Handle);
  364. InteropMethods.AlphaBlend(drawingContext.WindowDC, 0, height, orCreateBitmap2.Width,
  365. orCreateBitmap2.Height, drawingContext.BackgroundDC, 0, 0, orCreateBitmap2.Width,
  366. orCreateBitmap2.Height, drawingContext.Blend);
  367. if (num4 > 0)
  368. {
  369. InteropMethods.SelectObject(drawingContext.BackgroundDC, orCreateBitmap3.Handle);
  370. InteropMethods.AlphaBlend(drawingContext.WindowDC, 0, num, orCreateBitmap3.Width, num4,
  371. drawingContext.BackgroundDC, 0, 0, orCreateBitmap3.Width, orCreateBitmap3.Height,
  372. drawingContext.Blend);
  373. }
  374. InteropMethods.SelectObject(drawingContext.BackgroundDC, orCreateBitmap4.Handle);
  375. InteropMethods.AlphaBlend(drawingContext.WindowDC, 0, num3, orCreateBitmap4.Width,
  376. orCreateBitmap4.Height, drawingContext.BackgroundDC, 0, 0, orCreateBitmap4.Width,
  377. orCreateBitmap4.Height, drawingContext.Blend);
  378. InteropMethods.SelectObject(drawingContext.BackgroundDC, orCreateBitmap5.Handle);
  379. InteropMethods.AlphaBlend(drawingContext.WindowDC, 0, num2, orCreateBitmap5.Width,
  380. orCreateBitmap5.Height, drawingContext.BackgroundDC, 0, 0, orCreateBitmap5.Width,
  381. orCreateBitmap5.Height, drawingContext.Blend);
  382. }
  383. private void DrawRight(GlowDrawingContext drawingContext)
  384. {
  385. var orCreateBitmap = GetOrCreateBitmap(drawingContext, GlowBitmapPart.CornerTopRight);
  386. var orCreateBitmap2 = GetOrCreateBitmap(drawingContext, GlowBitmapPart.RightTop);
  387. var orCreateBitmap3 = GetOrCreateBitmap(drawingContext, GlowBitmapPart.Right);
  388. var orCreateBitmap4 = GetOrCreateBitmap(drawingContext, GlowBitmapPart.RightBottom);
  389. var orCreateBitmap5 = GetOrCreateBitmap(drawingContext, GlowBitmapPart.CornerBottomRight);
  390. var height = orCreateBitmap.Height;
  391. var num = height + orCreateBitmap2.Height;
  392. var num2 = drawingContext.Height - orCreateBitmap5.Height;
  393. var num3 = num2 - orCreateBitmap4.Height;
  394. var num4 = num3 - num;
  395. InteropMethods.SelectObject(drawingContext.BackgroundDC, orCreateBitmap.Handle);
  396. InteropMethods.AlphaBlend(drawingContext.WindowDC, 0, 0, orCreateBitmap.Width, orCreateBitmap.Height,
  397. drawingContext.BackgroundDC, 0, 0, orCreateBitmap.Width, orCreateBitmap.Height,
  398. drawingContext.Blend);
  399. InteropMethods.SelectObject(drawingContext.BackgroundDC, orCreateBitmap2.Handle);
  400. InteropMethods.AlphaBlend(drawingContext.WindowDC, 0, height, orCreateBitmap2.Width,
  401. orCreateBitmap2.Height, drawingContext.BackgroundDC, 0, 0, orCreateBitmap2.Width,
  402. orCreateBitmap2.Height, drawingContext.Blend);
  403. if (num4 > 0)
  404. {
  405. InteropMethods.SelectObject(drawingContext.BackgroundDC, orCreateBitmap3.Handle);
  406. InteropMethods.AlphaBlend(drawingContext.WindowDC, 0, num, orCreateBitmap3.Width, num4,
  407. drawingContext.BackgroundDC, 0, 0, orCreateBitmap3.Width, orCreateBitmap3.Height,
  408. drawingContext.Blend);
  409. }
  410. InteropMethods.SelectObject(drawingContext.BackgroundDC, orCreateBitmap4.Handle);
  411. InteropMethods.AlphaBlend(drawingContext.WindowDC, 0, num3, orCreateBitmap4.Width,
  412. orCreateBitmap4.Height, drawingContext.BackgroundDC, 0, 0, orCreateBitmap4.Width,
  413. orCreateBitmap4.Height, drawingContext.Blend);
  414. InteropMethods.SelectObject(drawingContext.BackgroundDC, orCreateBitmap5.Handle);
  415. InteropMethods.AlphaBlend(drawingContext.WindowDC, 0, num2, orCreateBitmap5.Width,
  416. orCreateBitmap5.Height, drawingContext.BackgroundDC, 0, 0, orCreateBitmap5.Width,
  417. orCreateBitmap5.Height, drawingContext.Blend);
  418. }
  419. private void DrawTop(GlowDrawingContext drawingContext)
  420. {
  421. var orCreateBitmap = GetOrCreateBitmap(drawingContext, GlowBitmapPart.TopLeft);
  422. var orCreateBitmap2 = GetOrCreateBitmap(drawingContext, GlowBitmapPart.Top);
  423. var orCreateBitmap3 = GetOrCreateBitmap(drawingContext, GlowBitmapPart.TopRight);
  424. var num2 = GlowDepth + orCreateBitmap.Width;
  425. var num3 = drawingContext.Width - GlowDepth - orCreateBitmap3.Width;
  426. var num4 = num3 - num2;
  427. InteropMethods.SelectObject(drawingContext.BackgroundDC, orCreateBitmap.Handle);
  428. InteropMethods.AlphaBlend(drawingContext.WindowDC, GlowDepth, 0, orCreateBitmap.Width, orCreateBitmap.Height,
  429. drawingContext.BackgroundDC, 0, 0, orCreateBitmap.Width, orCreateBitmap.Height,
  430. drawingContext.Blend);
  431. if (num4 > 0)
  432. {
  433. InteropMethods.SelectObject(drawingContext.BackgroundDC, orCreateBitmap2.Handle);
  434. InteropMethods.AlphaBlend(drawingContext.WindowDC, num2, 0, num4, orCreateBitmap2.Height,
  435. drawingContext.BackgroundDC, 0, 0, orCreateBitmap2.Width, orCreateBitmap2.Height,
  436. drawingContext.Blend);
  437. }
  438. InteropMethods.SelectObject(drawingContext.BackgroundDC, orCreateBitmap3.Handle);
  439. InteropMethods.AlphaBlend(drawingContext.WindowDC, num3, 0, orCreateBitmap3.Width,
  440. orCreateBitmap3.Height, drawingContext.BackgroundDC, 0, 0, orCreateBitmap3.Width,
  441. orCreateBitmap3.Height, drawingContext.Blend);
  442. }
  443. private void DrawBottom(GlowDrawingContext drawingContext)
  444. {
  445. var orCreateBitmap = GetOrCreateBitmap(drawingContext, GlowBitmapPart.BottomLeft);
  446. var orCreateBitmap2 = GetOrCreateBitmap(drawingContext, GlowBitmapPart.Bottom);
  447. var orCreateBitmap3 = GetOrCreateBitmap(drawingContext, GlowBitmapPart.BottomRight);
  448. var num2 = GlowDepth + orCreateBitmap.Width;
  449. var num3 = drawingContext.Width - GlowDepth - orCreateBitmap3.Width;
  450. var num4 = num3 - num2;
  451. InteropMethods.SelectObject(drawingContext.BackgroundDC, orCreateBitmap.Handle);
  452. InteropMethods.AlphaBlend(drawingContext.WindowDC, GlowDepth, 0, orCreateBitmap.Width, orCreateBitmap.Height,
  453. drawingContext.BackgroundDC, 0, 0, orCreateBitmap.Width, orCreateBitmap.Height,
  454. drawingContext.Blend);
  455. if (num4 > 0)
  456. {
  457. InteropMethods.SelectObject(drawingContext.BackgroundDC, orCreateBitmap2.Handle);
  458. InteropMethods.AlphaBlend(drawingContext.WindowDC, num2, 0, num4, orCreateBitmap2.Height,
  459. drawingContext.BackgroundDC, 0, 0, orCreateBitmap2.Width, orCreateBitmap2.Height,
  460. drawingContext.Blend);
  461. }
  462. InteropMethods.SelectObject(drawingContext.BackgroundDC, orCreateBitmap3.Handle);
  463. InteropMethods.AlphaBlend(drawingContext.WindowDC, num3, 0, orCreateBitmap3.Width,
  464. orCreateBitmap3.Height, drawingContext.BackgroundDC, 0, 0, orCreateBitmap3.Width,
  465. orCreateBitmap3.Height, drawingContext.Blend);
  466. }
  467. internal void UpdateWindowPos()
  468. {
  469. var targetWindowHandle = TargetWindowHandle;
  470. InteropMethods.GetWindowRect(targetWindowHandle, out var rect);
  471. InteropMethods.GetWindowPlacement(targetWindowHandle);
  472. if (IsVisible)
  473. switch (_orientation)
  474. {
  475. case Dock.Left:
  476. Left = rect.Left - GlowDepth;
  477. Top = rect.Top - GlowDepth;
  478. Width = GlowDepth;
  479. Height = rect.Height + CornerGripThickness;
  480. return;
  481. case Dock.Top:
  482. Left = rect.Left - GlowDepth;
  483. Top = rect.Top - GlowDepth;
  484. Width = rect.Width + CornerGripThickness;
  485. Height = GlowDepth;
  486. return;
  487. case Dock.Right:
  488. Left = rect.Right;
  489. Top = rect.Top - GlowDepth;
  490. Width = GlowDepth;
  491. Height = rect.Height + CornerGripThickness;
  492. return;
  493. default:
  494. Left = rect.Left - GlowDepth;
  495. Top = rect.Bottom;
  496. Width = rect.Width + CornerGripThickness;
  497. Height = GlowDepth;
  498. break;
  499. }
  500. }
  501. [Flags]
  502. private enum FieldInvalidationTypes
  503. {
  504. None = 0,
  505. Location = 1,
  506. Size = 2,
  507. ActiveColor = 4,
  508. InactiveColor = 8,
  509. Render = 16,
  510. Visibility = 32
  511. }
  512. }