-
Notifications
You must be signed in to change notification settings - Fork 1
/
MessageWindow.cs
135 lines (116 loc) · 4.18 KB
/
MessageWindow.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
using System;
using System.Reflection;
using System.Runtime.InteropServices;
namespace MSFSFlightFollowing
{
public class MessageWindow : IDisposable
{
public delegate IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
struct WNDCLASS
{
public uint style;
public IntPtr lpfnWndProc;
public int cbClsExtra;
public int cbWndExtra;
public IntPtr hInstance;
public IntPtr hIcon;
public IntPtr hCursor;
public IntPtr hbrBackground;
[MarshalAs(UnmanagedType.LPWStr)]
public string lpszMenuName;
[MarshalAs(UnmanagedType.LPWStr)]
public string lpszClassName;
}
[StructLayout(LayoutKind.Sequential)]
public struct MSG
{
public IntPtr hwnd;
public uint message;
public IntPtr wParam;
public IntPtr lParam;
public uint time;
}
[DllImport("user32.dll", SetLastError = true)]
static extern UInt16 RegisterClassW([In] ref WNDCLASS lpWndClass);
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr CreateWindowExW(
UInt32 dwExStyle,
[MarshalAs(UnmanagedType.LPWStr)] string lpClassName,
[MarshalAs(UnmanagedType.LPWStr)] string lpWindowName,
UInt32 dwStyle,
Int32 x,
Int32 y,
Int32 nWidth,
Int32 nHeight,
IntPtr hWndParent,
IntPtr hMenu,
IntPtr hInstance,
IntPtr lpParam
);
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr DefWindowProcW(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true)]
static extern bool DestroyWindow(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern sbyte GetMessage(out MSG lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax);
[DllImport("user32.dll")]
public static extern IntPtr DispatchMessage(ref MSG lpmsg);
[DllImport("user32.dll")]
public static extern bool TranslateMessage(ref MSG lpMsg);
private const int ERROR_CLASS_ALREADY_EXISTS = 1410;
private bool disposed = false;
public IntPtr Hwnd { get; private set; }
public void Dispose()
{
if (!disposed)
{
// Dispose unmanaged resources
if (Hwnd != IntPtr.Zero)
{
DestroyWindow(Hwnd);
Hwnd = IntPtr.Zero;
}
disposed = true;
}
GC.SuppressFinalize(this);
}
static MessageWindow instance = null;
public static MessageWindow GetWindow()
{
if (instance == null)
instance = new MessageWindow();
return instance;
}
private MessageWindow()
{
var className = Assembly.GetExecutingAssembly().GetName().Name;
wndProcDelegate = CustomWndProc;
WNDCLASS windClass = new WNDCLASS { lpszClassName = className, lpfnWndProc = Marshal.GetFunctionPointerForDelegate(wndProcDelegate) };
UInt16 classAtom = RegisterClassW(ref windClass);
int lastError = Marshal.GetLastWin32Error();
if (classAtom == 0 && lastError != ERROR_CLASS_ALREADY_EXISTS)
throw new System.Data.DuplicateNameException();
Hwnd = CreateWindowExW(0, className, "MessagePump", 0, 0, 0, 10, 10, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
}
private IntPtr CustomWndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
{
WndProcHandle?.Invoke(hWnd, msg, wParam, lParam);
return DefWindowProcW(hWnd, msg, wParam, lParam);
}
public static void MessageLoop()
{
var window = GetWindow(); // Ensure an instance has been created.
var msg = new MSG();
int r;
// Standard WIN32 message loop
while ((r = GetMessage(out msg, IntPtr.Zero, 0, 0)) > 0)
{
TranslateMessage(ref msg);
DispatchMessage(ref msg);
}
}
public event WndProc WndProcHandle;
private WndProc wndProcDelegate;
}
}