Skip to content

Instantly share code, notes, and snippets.

@xtu
Last active November 28, 2018 14:16
Show Gist options
  • Save xtu/c4a4c179261c4768e1eac8188448ac72 to your computer and use it in GitHub Desktop.
Save xtu/c4a4c179261c4768e1eac8188448ac72 to your computer and use it in GitHub Desktop.
A class to monitor when a WinForm form is found
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace WindowsFormsApp11
{
public class WinFormMonitor : IDisposable
{
private readonly IntPtr _eventHook;
private readonly IList<int> _detectedFormHashes = new List<int>();
public event EventHandler<Form> NewFormCreated = (sender, form) => { };
public WinFormMonitor()
{
_eventHook = SetWinEventHook(
EVENT_OBJECT_CREATE,
EVENT_OBJECT_CREATE,
IntPtr.Zero,
WinEventProc,
0,
0,
WINEVENT_OUTOFCONTEXT);
}
public void Dispose()
{
_detectedFormHashes.Clear();
UnhookWinEvent(_eventHook);
}
private void WinEventProc(IntPtr hWinEventHook, uint eventType,
IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
{
// filter out non-HWND namechanges... (eg. items within a listbox)
if (idObject != 0 || idChild != 0) return;
if (!TryFindForm(hwnd, out var foundForm)) return;
RaiseIfNewFormFound(foundForm);
}
private void RaiseIfNewFormFound(Form foundForm)
{
var formHash = foundForm.GetHashCode();
if (_detectedFormHashes.Contains(formHash)) return;
NewFormCreated(this, foundForm);
_detectedFormHashes.Add(formHash);
}
private static bool TryFindForm(IntPtr handle, out Form foundForm)
{
foreach (Form openForm in Application.OpenForms)
{
if (openForm.Handle != handle) continue;
foundForm = openForm;
return true;
}
foundForm = null;
return false;
}
private const uint EVENT_OBJECT_CREATE = 0x8000;
private const uint WINEVENT_OUTOFCONTEXT = 0;
private delegate void WinEventDelegate(IntPtr hWinEventHook, uint eventType,
IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime);
[DllImport("user32.dll")]
private static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr
hmodWinEventProc, WinEventDelegate lpfnWinEventProc, uint idProcess,
uint idThread, uint dwFlags);
[DllImport("user32.dll")]
private static extern bool UnhookWinEvent(IntPtr hWinEventHook);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment