외부 응용 프로그램이 종료되었을 때 경고를 받으려고합니다. 내 테스트를 위해 메모장의 hwnd를 검색하여 모니터에 설정했습니다. 이상하게도 메모장이 닫히지 않았는데도 메모장에서 다른 응용 프로그램을 클릭 할 때마다 시스템 이벤트가 발생합니다. 왜 아무 생각 없어?EVENT_OBJECT_DESTROY 메모장에서 초점을 잃었습니까?
몇 가지 빠른 예를 호출하는 코드 :
uint EVENT_OBJECT_DESTROY = 0x8001;
IntPtr notepadHwnd = <your pointer>
var mon = new WindowMonitor(notepadHwnd, EVENT_OBJECT_DESTROY);
mon.EventOccurred += (sender, args) => Console.WriteLine("closed");
모니터 :
public class WindowMonitor : IDisposable
{
//store delegate to prevent GC
private User32.WinEventDelegate dEvent;
private IntPtr _hook;
private readonly IntPtr _window;
private readonly List<uint> _watchedEvents = new List<uint>();
public event EventHandler<AccessibleEventTypeEventArgs> EventOccurred;
public WindowMonitor(IntPtr windowToMonitor, params User32.AccessibleEventType[] eventsToMonitor)
{
//prevent junk
if (eventsToMonitor == null || eventsToMonitor.Length == 0)
throw new ArgumentNullException("eventsToMonitor", "Must specify events to monitor");
if (windowToMonitor == IntPtr.Zero)
throw new ArgumentNullException("windowToMonitor", "Must specify a valid window handle to monitor");
_window = windowToMonitor;
//cast them now so we dont have to cast each one when evaluting events
uint lowest = (uint) User32.AccessibleEventType.EVENT_MAX;
uint highest = (uint) User32.AccessibleEventType.EVENT_MIN;
foreach (User32.AccessibleEventType eventType in eventsToMonitor)
{
var castType = (uint) eventType;
_watchedEvents.Add(castType);
//need the range of events to subscribe to
if (castType > highest)
highest = castType;
if (castType < lowest)
lowest = castType;
}
//sign up for the event
dEvent = this.winEvent;
_hook = User32.SetWinEventHook(lowest, highest, IntPtr.Zero, dEvent, 0, 0, User32.WINEVENT_OUTOFCONTEXT);
//ensure it worked
if (IntPtr.Zero.Equals(_hook)) throw new Win32Exception();
//no kill callback
GC.KeepAlive(dEvent);
}
private void winEvent(IntPtr hWinEventHook, uint eventType, IntPtr hWnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
{
//only care about the events for the specified window
if (hWnd != _window)
return;
if (_watchedEvents.Contains(eventType))
{
if (EventOccurred != null)
EventOccurred(this, new AccessibleEventTypeEventArgs((User32.AccessibleEventType) eventType));
}
}
public void Dispose()
{
//unhook the listener
if (!IntPtr.Zero.Equals(_hook))
User32.UnhookWinEvent(_hook);
//clear variables
_hook = IntPtr.Zero;
dEvent = null;
//kill any event listeners
EventOccurred = null;
GC.SuppressFinalize(this);
}
}
일부 WINAPI (내가 이벤트 consts의 목록을 생략) : 당신은
public delegate void WinEventDelegate(IntPtr hWinEventHook, uint eventType, IntPtr hwnd,
int idObject, int idChild, uint dwEventThread, uint dwmsEventTime);
[DllImport("user32.dll")]
public static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr hmodWinEventProc,
WinEventDelegate lpfnWinEventProc, uint idProcess, uint idThread, uint dwFlags);
[DllImport("user32.dll")]
public static extern bool UnhookWinEvent(IntPtr hWinEventHook);
당신은 캐럿에 대해 정확히 맞았습니다. 또한 idThread에 대한 팁을 주셔서 감사합니다. 확실히 도움이되었습니다. –