aboutsummaryrefslogtreecommitdiffstats
path: root/WarframeClock/OverlayWindowBase.cs
diff options
context:
space:
mode:
Diffstat (limited to 'WarframeClock/OverlayWindowBase.cs')
-rw-r--r--WarframeClock/OverlayWindowBase.cs141
1 files changed, 141 insertions, 0 deletions
diff --git a/WarframeClock/OverlayWindowBase.cs b/WarframeClock/OverlayWindowBase.cs
new file mode 100644
index 0000000..87cea8a
--- /dev/null
+++ b/WarframeClock/OverlayWindowBase.cs
@@ -0,0 +1,141 @@
+using System;
+using System.Diagnostics;
+using System.Windows;
+using System.Windows.Interop;
+
+namespace WarframeClock
+{
+ public class OverlayWindowBase : Window
+ {
+ private IntPtr _windowHandle;
+ private bool _xTopmost;
+ private IntPtr _targetWindowHandle;
+ private Native.Rect _parentBounds;
+
+ public OverlayWindowBase()
+ {
+ _xTopmost = false;
+ }
+
+ protected bool AdjustOverlay()
+ {
+ if (_windowHandle == IntPtr.Zero)
+ _windowHandle = new WindowInteropHelper(this).EnsureHandle();
+
+ if (!GetTargetWindow(out var newBounds))
+ {
+ if (IsVisible)
+ {
+ Logging("Hide overlay; target window disappeared");
+ Hide();
+ }
+ return false;
+ }
+
+ // Set top-most flag if the target window is foreground. Move to
+ // behind the current foreground window otherwise.
+ var currentActiveWindow = Native.GetForegroundWindow();
+ if (currentActiveWindow != IntPtr.Zero &&
+ (!IsVisible || currentActiveWindow == _targetWindowHandle != _xTopmost))
+ {
+ // Setting Topmost to false brings the overlay to just
+ // behind the other top-most window -- above the foreground
+ // window. This is not what we want to do here.
+ // So, let's use SetWindowPos directly instead.
+ if (currentActiveWindow == _targetWindowHandle)
+ {
+ Logging("Overlay is now top-most");
+ _xTopmost = true;
+ }
+ else
+ {
+ Logging($"Overlay is now non-top-most, behind {currentActiveWindow}");
+ _xTopmost = false;
+ }
+
+ uint flags =
+ 0x0001 /* SWP_NOSIZE */ |
+ 0x0002 /* SWP_NOMOVE */ |
+ 0x0008 /* SWP_NOREDRAW */ |
+ 0x0010 /* SWP_NOACTIVATE */ |
+ 0x0200 /* SWP_NOOWNERZORDER */ |
+ 0x0400 /* SWP_NOSENDCHANGING */;
+ Native.SetWindowPos(_windowHandle, _xTopmost ? (IntPtr)(-1) : currentActiveWindow, 0, 0, 0, 0, flags);
+ }
+
+ // Adjust window position
+ if (!IsVisible ||
+ _parentBounds.Left != newBounds.Left || _parentBounds.Right != newBounds.Right ||
+ _parentBounds.Top != newBounds.Top || _parentBounds.Bottom != newBounds.Bottom)
+ {
+ _parentBounds = newBounds;
+
+ var width = _parentBounds.Right - _parentBounds.Left;
+ var height = _parentBounds.Bottom - _parentBounds.Top;
+
+ // Do not use window.Left (and so on) because they're DPI-aware.
+ // We don't want that....
+ Logging($"Move overlay to: l={_parentBounds.Left};t={_parentBounds.Top};w={width};h={height}");
+ Native.SetWindowPos(_windowHandle, IntPtr.Zero, _parentBounds.Left, _parentBounds.Top, width, height,
+ 0x0004 /* SWP_NOZORDER */);
+ }
+ if (!IsVisible)
+ {
+ Logging("Show overlay");
+ Show();
+ }
+
+ return true;
+ }
+
+ private bool GetTargetWindow(out Native.Rect bounds)
+ {
+ if (_targetWindowHandle == IntPtr.Zero)
+ {
+ foreach (var process in Process.GetProcesses())
+ {
+ if (_targetWindowHandle == IntPtr.Zero &&
+ (process.ProcessName == "Warframe" || process.ProcessName == "Warframe.x64"))
+ {
+ try
+ {
+ _targetWindowHandle = process.MainWindowHandle;
+ if (_targetWindowHandle != IntPtr.Zero)
+ {
+ Logging($"Found a process with name={process.ProcessName}; " +
+ $"MainWindowHandle={_targetWindowHandle}");
+ }
+ }
+ catch (Exception)
+ {
+ // Ignore errors; maybe the process is just exiting. Let's retry during the next cycle.
+ }
+ }
+
+ process.Dispose();
+ }
+ }
+
+ if (_targetWindowHandle == IntPtr.Zero)
+ {
+ // Suppress compile error; caller must not use the value
+ bounds = new Native.Rect();
+ return false;
+ }
+
+ if (!Native.GetWindowRect(_targetWindowHandle, out bounds))
+ {
+ Logging("GetWindowRect failed; aborting this cycle");
+ _targetWindowHandle = IntPtr.Zero;
+ return false;
+ }
+
+ return true;
+ }
+
+ private static void Logging(string message)
+ {
+ Console.WriteLine($"OverlayWindowBase: {message}");
+ }
+ }
+}