Я пытаюсь подписаться на оконные сообщения, используя .Net Core
Я могу получать исходные сообщения для создания окна (через pinvoke) и уничтожения сообщений. Но после этого мои созданные окна блокируются и не получают никаких других сообщений.
public class CustomWindow : IDisposable
{
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);
private const int ERROR_CLASS_ALREADY_EXISTS = 1410;
private bool _mDisposed;
public IntPtr Hwnd;
public List<uint> Messages { get; set; }
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (!_mDisposed)
{
if (disposing)
{
// Dispose managed resources
}
// Dispose unmanaged resources
if (Hwnd != IntPtr.Zero)
{
DestroyWindow(Hwnd);
Hwnd = IntPtr.Zero;
}
}
}
public CustomWindow()
{
Messages = new List<uint>();
var className = "InvisibleWindow";
_mWndProcDelegate = CustomWndProc;
// Create WNDCLASS
WNDCLASS windClass = new WNDCLASS
{
lpszClassName = className,
lpfnWndProc = Marshal.GetFunctionPointerForDelegate(_mWndProcDelegate)
};
UInt16 classAtom = RegisterClassW(ref windClass);
int lastError = Marshal.GetLastWin32Error();
if (classAtom == 0 && lastError != ERROR_CLASS_ALREADY_EXISTS)
{
throw new Exception("Could not register window class");
}
const UInt32 WS_OVERLAPPEDWINDOW = 0xcf0000;
const UInt32 WS_VISIBLE = 0x10000000;
// Create window
Hwnd = CreateWindowExW(
0,
className,
"My WIndow",
WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0, 0, 300, 400,
IntPtr.Zero,
IntPtr.Zero,
IntPtr.Zero,
IntPtr.Zero
);
Importer.ShowWindow(Hwnd, 1);
Importer.UpdateWindow(Hwnd);
}
private IntPtr CustomWndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
{
Messages.Add(msg);
return DefWindowProcW(hWnd, msg, wParam, lParam);
}
private WndProc _mWndProcDelegate;
}
Класс для создания пользовательского окна CustomWndProc получает сообщения. Я пока не выполняю никакой логики, просто пытаюсь заставить вещи работать.
Я пытаюсь выяснить, как я могу сделать это из отдельного потока, чтобы продолжать слушать сообщения, не блокируя при этом основной интерфейс API / GUI / консоли
Могу ли я создать этот класс в отдельном потоке и по-прежнему использовать внедрение зависимостей и иметь доступ к его данным / сообщениям / событиям по своей прихоти. Я знаю, что есть много способов сделать это в .net, но это .net Core.
Что случилось с отрицательными голосами, буквально нет ресурсов, как реализовать это в Net Core, у меня нет доступа к любой из форм / элементов управления .Net, которые упрощают это, я также предоставил полный рабочий класс, если есть Отсутствие подробностей в моем посте, оставьте комментарий. Не голосуйте случайно, без веской причины. Если есть другая ветка, которая объясняет, как это сделать, свяжите ее, а затем уменьшите эту.
private void GetMessage()
{
IntPtr hwnd = _customWindow.Hwnd;
int bRet;
while ((bRet = Importer.GetMessage(out var msg, _customWindow.GetHandle, 0, 0)) !=0 )
{
if (bRet == -1)
{
Console.WriteLine("Error");
}
else
{
Importer.TranslateMessage(ref msg);
Importer.DispatchMessage(ref msg);
Console.WriteLine(_customWindow.Messages.LastOrDefault());
}
}
}
Реализован цикл GetMessage, мое окно теперь получает все сообщения и не блокируется, но теперь блокирует основной поток. Я посмотрю, смогу ли я создать окно в отдельном потоке и запустить цикл сообщений в этом потоке.