Skip to content

Instantly share code, notes, and snippets.

@lolp1
Last active October 19, 2017 05:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lolp1/176517455e68eacd70368f0d27fa6a61 to your computer and use it in GitHub Desktop.
Save lolp1/176517455e68eacd70368f0d27fa6a61 to your computer and use it in GitHub Desktop.
overlay
public partial class OverlayWindow : Window
{
[SuppressMessage("ReSharper", "InconsistentNaming")]
private static IntPtr MA_NOACTIVATEPTR { get; } = new IntPtr(MA_NOACTIVATE);
internal IntPtr OriginalWindowLongPtr { get; set; }
internal Rectangle NormalPosition { get; set; }
internal IWindow TargetWindow { get; set; }
internal bool ClickThrough { get; set; }
public event EventHandler<DrawingContext> Draw;
internal WindowInteropHelper WindowInteropHelper { get; private set; }
internal HwndSource HwndSource { get; private set; }
internal HwndSourceHook HwndSourceHook { get; private set; }
public TimeSpan UpdateThrottleInterval { get; set; } = (1000 / 30).Milliseconds();
public OverlayWindow() : this(false)
{
}
public Canvas GetCanvas() => OverlayCanvas;
public void Update()
{
var placementNormalPosition = TargetWindow.Placement.NormalPosition;
if (NormalPosition == placementNormalPosition)
{
return;
}
NormalPosition = placementNormalPosition;
UpdateBounds();
}
public int AddElement(UIElement element) => OverlayCanvas.Children.Add(element);
public void RemoveElement(UIElement element) => OverlayCanvas.Children.Remove(element);
public UIElement AddElement(UIElement element, int index) => OverlayCanvas.Children[index] = element;
public void RemoveElement(int index) => OverlayCanvas.Children.RemoveAt(index);
public void ClearElements()
{
OverlayCanvas.Children.Clear();
}
public void SetWindow(IWindow window) => TargetWindow = window;
internal OverlayWindow(bool clickThrough)
{
ClickThrough = clickThrough;
InitializeComponent();
}
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
if (ClickThrough)
{
this.MakeWindowTransparent();
}
else
{
WindowInteropHelper = new WindowInteropHelper(this);
OriginalWindowLongPtr = Kernel32.SetWindowLongPtr(WindowInteropHelper.Handle, -8, TargetWindow.Handle);
HwndSource = HwndSource.FromHwnd(WindowInteropHelper.Handle);
HwndSourceHook = OverlayWndProc;
HwndSource?.AddHook(HwndSourceHook);
}
}
protected override void OnRender(DrawingContext drawingContext)
{
OnDraw(drawingContext);
base.OnRender(drawingContext);
}
protected virtual void OnDraw(DrawingContext e)
{
if (e == null)
{
return;
}
Draw?.Invoke(this, e);
}
[SuppressMessage("ReSharper", "InconsistentNaming")]
private static IntPtr OverlayWndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if (msg != WM_MOUSEACTIVATE)
{
return IntPtr.Zero;
}
handled = true;
return MA_NOACTIVATEPTR;
}
[SuppressMessage("ReSharper", "InconsistentNaming")] private const int WM_MOUSEACTIVATE = 0x0021;
[SuppressMessage("ReSharper", "InconsistentNaming")] private const int MA_NOACTIVATE = 3;
private void UpdateBounds()
{
Width = NormalPosition.Width;
Height = NormalPosition.Height;
Left = NormalPosition.Left;
Top = NormalPosition.Top;
}
}
}
<Window x:Class="WowNet.UI.OverlayWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title=""
Height="300"
Width="300"
ShowInTaskbar="False"
WindowStyle="None"
Topmost="True"
AllowsTransparency="True">
<Window.Background>
<SolidColorBrush Opacity="0.0" Color="Black" />
</Window.Background>
<Canvas x:Name="OverlayCanvas" HorizontalAlignment="Left" Height="300" VerticalAlignment="Top" Width="300" />
</Window>
public const int SM_CX_SCREEN = 0;
public const int SM_CY_SCREEN = 1;
public const string DESKTOP_CLASS = "#32769";
public const uint WINDOW_STYLE_DX = 0x8000000 //WS_DISABLED
| 0x10000000 //WS_VISIBLE
| 0x80000000; //WS_POPUP
public const uint WINDOW_EX_STYLE_DX = 0x8000000 //WS_EX_NOACTIVATE
| 0x80000 //WS_EX_LAYERED
| 0x80 //WS_EX_TOOLWINDOW -> Not in taskbar
| 0x8 //WS_EX_TOPMOST
| 0x20; //WS_EX_TRANSPARENT
public const int HWND_NOTOPMOST = -2;
public const int HWND_TOPMOST = -1;
public const int HWND_TOP = 0;
public const int HWND_BOTTOM = 1;
public const uint SWP_FLAGS_SHOW = 0x40;
public const uint SWP_FLAGS_HIDE = 0x80;
public const uint SW_SHOW = 5;
public const uint SW_HIDE = 0;
public const int GWL_EXSTYLE = -20;
public const int WS_EX_TRANSPARENT = 0x00000020;
public static void MakeWindowTransparent(this Window wnd)
{
if (!wnd.IsInitialized)
{
throw new WowNetException(
"The extension method MakeWindowTransparent can not be called prior to the window being initialized.");
}
var handle = new WindowInteropHelper(wnd).Handle;
var extendedStyle = Kernel32.GetWindowLongPtr(handle, GWL_EXSTYLE);
Kernel32.SetWindowLongPtr(handle, GWL_EXSTYLE, new IntPtr(extendedStyle.ToInt32() | WS_EX_TRANSPARENT));
}
Method: DrawDrawing(Drawing)
Draws the specified Drawing object.
Method: DrawEllipse(Brush, Pen, Point, AnimationClock, Double, AnimationClock, Double, AnimationClock)
Draws an ellipse with the specified Brush and Pen and applies the specified animation clocks.
Method: DrawEllipse(Brush, Pen, Point, Double, Double)
Draws an ellipse with the specified Brush and Pen.
Method: DrawGeometry(Brush, Pen, Geometry)
Draws the specified Geometry using the specified Brush and Pen.
Method: DrawGlyphRun(Brush, GlyphRun)
Draws the specified text.
Method: DrawImage(ImageSource, Rect)
Draws an image into the region defined by the specified Rect.
Method: DrawImage(ImageSource, Rect, AnimationClock)
Draws an image into the region defined by the specified Rect and applies the specified animation clock.
Method: DrawLine(Pen, Point, AnimationClock, Point, AnimationClock)
Draws a line between the specified points using the specified Pen and applies the specified animation clocks.
Method: DrawLine(Pen, Point, Point)
Draws a line between the specified points using the specified Pen.
Method: DrawRectangle(Brush, Pen, Rect)
Draws a rectangle with the specified Brush and Pen. The pen and the brush can be null.
Method: DrawRectangle(Brush, Pen, Rect, AnimationClock)
Draws a rectangle with the specified Brush and Pen and applies the specified animation clocks.
Method: DrawRoundedRectangle(Brush, Pen, Rect, AnimationClock, Double, AnimationClock, Double, AnimationClock)
Draws a rounded rectangle with the specified Brush and Pen and applies the specified animation clocks.
Method: DrawRoundedRectangle(Brush, Pen, Rect, Double, Double)
Draws a rounded rectangle with the specified Brush and Pen.
Method: DrawText(FormattedText, Point)
Draws formatted text at the specified location.
Method: DrawVideo(MediaPlayer, Rect)
Draws a video into the specified region.
Method: DrawVideo(MediaPlayer, Rect, AnimationClock)
Draws a video into the specified region and applies the specified animation clock.
Method: PushClip(Geometry)
Pushes the specified clip region onto the drawing context.
Method: PushEffect(BitmapEffect, BitmapEffectInput)
Obsolete. Pushes the specified BitmapEffect onto the drawing context.
Method: PushGuidelineSet(GuidelineSet)
Pushes the specified GuidelineSet onto the drawing context.
Method: PushOpacity(Double)
Pushes the specified opacity setting onto the drawing context.
Method: PushOpacity(Double, AnimationClock)
Pushes the specified opacity setting onto the drawing context and applies the specified animation clock.
Method: PushOpacityMask(Brush)
Pushes the specified opacity mask onto the drawing context.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment