forked from shayne/PowerDimmer
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathWindowShade.cs
142 lines (123 loc) · 5.29 KB
/
WindowShade.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Interop;
using System.Windows.Media;
namespace PowerDimmer
{
public partial class WindowShade : Window
{
public IntPtr Handle;
IntPtr _targetHandle;
static Win32.WinEventDelegate eventMovedDelegate = null;
private Win32.RECT rect;
static GCHandle GCSafetyHandle;
private IntPtr eventHook;
public IntPtr TargetHandle { get { return _targetHandle; } }
private bool isLocalPos = false;
private double _left;
private double _top;
private double _width;
private double _height;
public WindowShade(IntPtr targetHandle)
{
_targetHandle = targetHandle;
ShowInTaskbar = false;
AllowsTransparency = true;
Background = Brushes.Black;
WindowStyle = WindowStyle.None;
ResizeMode = ResizeMode.NoResize;
//Allocating the delegate to a GCHandle example from here. This prevents it from getting garbage collected and windows throwing a message error.
//https://stackoverflow.com/questions/48767318/move-window-when-external-applications-window-moves
eventMovedDelegate = new Win32.WinEventDelegate(WinEventMovedProc);
GCSafetyHandle = GCHandle.Alloc(eventMovedDelegate);
if (_targetHandle != IntPtr.Zero)
{
rect = Win32.GetWindowRectangle(targetHandle);
SetPosAndHeight(rect);
Left = rect.Left;
Top = rect.Top;
Width = rect.Right - rect.Left;
Height = rect.Bottom - rect.Top;
uint pid = Win32.GetProcessId(_targetHandle);
uint targetThreadId = Win32.GetWindowThreadProcessId(_targetHandle, IntPtr.Zero);
eventHook = Win32.SetWinEventHook((uint)Win32.SWEH_Events.EVENT_OBJECT_LOCATIONCHANGE, (uint)Win32.SWEH_Events.EVENT_OBJECT_LOCATIONCHANGE,
_targetHandle, eventMovedDelegate, pid, targetThreadId, Win32.WINEVENT_OUTOFCONTEXT);
}
}
public WindowShade(IntPtr targetHandle, double left, double top, double width, double height)
{
_targetHandle = targetHandle;
ShowInTaskbar = false;
AllowsTransparency = true;
Background = Brushes.Black;
WindowStyle = WindowStyle.None;
ResizeMode = ResizeMode.NoResize;
_left = left;
_top = top;
_width = width;
_height = height;
isLocalPos = true;
eventMovedDelegate = new Win32.WinEventDelegate(WinEventMovedProc);
GCSafetyHandle = GCHandle.Alloc(eventMovedDelegate);
if (_targetHandle != IntPtr.Zero)
{
rect = Win32.GetWindowRectangle(targetHandle);
Left = rect.Left + left;
Top = rect.Top + top;
Width = width ;
Height = height;
uint pid = Win32.GetProcessId(_targetHandle);
uint targetThreadId = Win32.GetWindowThreadProcessId(_targetHandle, IntPtr.Zero);
eventHook = Win32.SetWinEventHook((uint)Win32.SWEH_Events.EVENT_OBJECT_LOCATIONCHANGE, (uint)Win32.SWEH_Events.EVENT_OBJECT_LOCATIONCHANGE,
_targetHandle, eventMovedDelegate, pid, targetThreadId, Win32.WINEVENT_OUTOFCONTEXT);
}
}
public void WinEventMovedProc(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
{
if (hwnd != _targetHandle)
return;
rect = Win32.GetWindowRectangle(_targetHandle);
SetPosAndHeight(rect);
}
private void SetPosAndHeight(Win32.RECT rect)
{
if(!isLocalPos)
Win32.MoveWindow(Handle, rect.Left, rect.Top, rect.Right - rect.Left, rect.Bottom - rect.Top, false);
else
{
int left = (int)(rect.Left + _left);
int top = (int)(rect.Top + _top);
int width = (int)(_width);
int height = (int)(_height);
Win32.MoveWindow(Handle, left, top, width, height, false);
}
}
protected override void OnSourceInitialized(EventArgs e)
{
Handle = new WindowInteropHelper(this).EnsureHandle();
var style = Win32.GetWindowLong(Handle, Win32.GWL_EXSTYLE);
Win32.SetWindowLong(Handle, Win32.GWL_EXSTYLE, style | Win32.WS_EX_LAYERED | Win32.WS_EX_TRANSPARENT | Win32.WS_EX_NOACTIVATE);
Win32.ShowWindow(Handle, Win32.SW_SHOWNORMAL);
base.OnSourceInitialized(e);
}
protected override void OnClosing(CancelEventArgs e)
{
base.OnClosing(e);
if(!e.Cancel)
{
if(GCSafetyHandle.IsAllocated)
{
GCSafetyHandle.Free();
}
Win32.UnhookWinEvent(eventHook);
}
}
}
}