Существует ли какое-либо событие static , которое запускается при создании дескриптора для элемента управления Winforms или при его первой загрузке?
Это надуманный пример:
using (Form f1 = new Form())
{
f1.HandleCreated += (sender, args) => { MessageBox.Show("hi"); };
f1.ShowDialog();
}
using (Form f2 = new Form())
{
f2.HandleCreated += (sender, args) => { MessageBox.Show("hi"); };
f2.ShowDialog();
}
И вот что я хочу:
Form.StaticHandleCreated += (sender, args) => { MessageBox.Show("hi"); };
using (Form f1 = new Form())
{
f1.ShowDialog();
}
using (Form f2 = new Form())
{
f2.ShowDialog();
}
(Я хочу это, потому что у меня есть несколько сотен элементов управления, и мне нужно настроить поведение по умолчанию для стороннего элемента управления, а поставщик не предоставляет лучшего способа. Они специально говорят, что нужно обрабатывать событие OnLoad для выполнения настройки , но это огромная нагрузка.)
Благодаря xtu, вот рабочая версия, которая не держит формы дольше, чем необходимо, чтобы избежать утечек памяти.
public class WinFormMonitor : IDisposable
{
private readonly IntPtr _eventHook;
private List<Form> _detectedForms = new List<Form>();
public event Action<Form> NewFormDetected;
private WinEventDelegate _winEventDelegate;
public WinFormMonitor()
{
_winEventDelegate = WinEventProc;
_eventHook = SetWinEventHook(
EVENT_OBJECT_CREATE,
EVENT_OBJECT_CREATE,
IntPtr.Zero,
_winEventDelegate,
0,
0,
WINEVENT_OUTOFCONTEXT);
}
public void Dispose()
{
_detectedForms.Clear();
UnhookWinEvent(_eventHook);
}
private void WinEventProc(IntPtr hWinEventHook, uint eventType,
IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
{
if (idObject != 0 || idChild != 0) return;
var currentForms = Application.OpenForms.OfType<Form>().ToList();
var newForms = currentForms.Except(_detectedForms);
foreach (var f in newForms)
{
NewFormDetected?.Invoke(f);
}
_detectedForms = currentForms;
}
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);
}