• 0

[C#] attach event to window exit


Question

I launch an application through another application. I can get the window handle of the application, and I want to add an event to it when it is closed.

When it is closed, I want to do something in my applcation... so I'm looking to attach to a window I guess, and when its Exited, throw an event and do something.

Any ideas?

Link to comment
https://www.neowin.net/forum/topic/616922-c-attach-event-to-window-exit/
Share on other sites

7 answers to this question

Recommended Posts

  • 0

Something along the lines of this?

using System.Windows.Forms;

class ClassName : Form
{
	//some class variables, methods, delegates, etc. ?
	ClassName ()
	{
		//some other things?
		this.FormClosing += new FormClosingEventHandler(formClosing);
	}

	void formClosing (object sender, FormClosingEventArgs)
	{
		//If you are using multithreaded programming, make sure to notify the threads that the app is
		//	closing somehow. Otherwise, you'll get exceptions (in the console if compiled as a console app)

		// THROW YOUR EVENT SOMEWHERE IN HERE
	}

	public static void Main (string[] args)
	{
		Application.Run(new ClassName());
	}
}

  • 0

My title and post are unclear...

I basically only have the Window handle, an IntPtr of the application of which I want to attach events to. Whenever this external window is closed, I want an event to be called in my application.

I understand events and the simplicity... .Exited or whatever, but I ONLY have the IntPtr handle to the window.

  • 0

You'll want to hook into Windows and monitor the WM_Close (WM_CLOSE = 0x0010) event and check the handle you have against the handle of the window being closed. You do this by overriding the WndProc event. Or you can set up a system wide hook The following is what I use to set this up. Just copy this into a .cs file (ex. Hook.cs) and create a reference to this in your form.

using System;
using System.ComponentModel;
using System.Runtime.InteropServices;

namespace Hook
{
	public delegate void OnForegroundWindowChangedDelegate(IntPtr hWnd);
	public delegate void OnWindowMinimizeStartDelegate(IntPtr hWnd);
	public delegate void OnWindowMinimizeEndDelegate(IntPtr hWnd);
	public delegate void OnWindowDestroyDelegate(IntPtr hWnd);

	public sealed class Hooks
	{
		#region Windows API

		private enum SystemEvents : uint
		{
			EVENT_SYSTEM_DESTROY = 0x8001,
			EVENT_SYSTEM_MINIMIZESTART = 0x0016,
			EVENT_SYSTEM_MINIMIZEEND = 0x0017,
			EVENT_SYSTEM_FOREGROUND = 0x0003
		}

		private const uint WINEVENT_OUTOFCONTEXT = 0x0000;

		private delegate void WinEventDelegate(
			IntPtr hWinEventHook,
			uint eventType,
			IntPtr hWnd,
			int idObject,
			int idChild,
			uint dwEventThread,
			uint dwmsEventTime);

		[DllImport("User32.dll", SetLastError = true)]
		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
			);

		#endregion

		private WinEventDelegate dEvent;
		private IntPtr pHook;
		public OnForegroundWindowChangedDelegate OnForegroundWindowChanged;
		public OnWindowMinimizeStartDelegate OnWindowMinimizeStart;
		public OnWindowMinimizeEndDelegate OnWindowMinimizeEnd;
		public OnWindowDestroyDelegate OnWindowDestroy;

		public Hooks()
		{
			dEvent = this.WinEvent;
			pHook = SetWinEventHook(
				(uint)SystemEvents.EVENT_SYSTEM_DESTROY ,
				(uint)SystemEvents.EVENT_SYSTEM_DESTROY ,
				IntPtr.Zero,
				dEvent,
				0,
				0,
				WINEVENT_OUTOFCONTEXT
				);

			if (IntPtr.Zero.Equals(pHook)) throw new Win32Exception();

			GC.KeepAlive(dEvent);
		}

		private void WinEvent(IntPtr hWinEventHook, uint eventType, IntPtr hWnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
		{
			switch (eventType)
			{
				case (uint)SystemEvents.EVENT_SYSTEM_DESTROY:
					if (OnWindowDestroy != null) OnWindowDestroy(hWnd);
					break;

				//extend here when required
			}
		}

		~Hooks()
		{
			if (!IntPtr.Zero.Equals(pHook)) UnhookWinEvent(pHook);
			pHook = IntPtr.Zero;
			dEvent = null;

			OnWindowDestroy = null;
		}
	}
}

Then to use this, insert this into your form:

Hook hook = new Hook();

And then in your form's loading event insert this to set up an event for the hook:

hook.OnWindowDestroy += OnWindowDestroyDelegate(window_Destroyed);

private void window_Destroyed(IntPtr hWnd)
{
	 if (hWnd == {the handle you're looking for})
	 {
		  //Do whatever you need here!
	 }
}

Hope it helps.

  • 0

This is great... one problem... (I'm awful with delegates, I really need a book).

The hook setup gives me an error:

hook.OnWindowDestroy += OnWindowDestroyDelegate(window_Destroyed);

project.OnWindowDestroyDelegate' is a 'type' but is used like a 'variable'

I copied your code exactly, but just changed the namespace to my project.. I think that's correct...

  • 0
  zackiv31 said:
This is great... one problem... (I'm awful with delegates, I really need a book).

The hook setup gives me an error:

hook.OnWindowDestroy += OnWindowDestroyDelegate(window_Destroyed);

project.OnWindowDestroyDelegate' is a 'type' but is used like a 'variable'

I copied your code exactly, but just changed the namespace to my project.. I think that's correct...

Sorry, I forgot to type 'new' in there. The correct line should be:

hook.OnWindowDestroy += new OnWindowDestroyDelegate(window_Destroyed);

  • 0
  zackiv31 said:
This is great... one problem... (I'm awful with delegates, I really need a book).

The hook setup gives me an error:

hook.OnWindowDestroy += OnWindowDestroyDelegate(window_Destroyed);

project.OnWindowDestroyDelegate' is a 'type' but is used like a 'variable'

I copied your code exactly, but just changed the namespace to my project.. I think that's correct...

This is really very helpful post.

One question: I want to handle other message, like WM_PAINT, WM_MOVE, etc. in this case how can I get the message codes?

I tried declaring EVENT_SYSTEM_PAINT = 0x000F but this is not working.

Kindly suggest.

This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Posts

    • This was cool back in the day when done properly - loved having icons of specific devices.
    • Microsoft quietly burying a massive Windows 7 hardware driver feature as Windows 11 kills it by Sayan Sen Last month Microsoft announced a big update for Windows hardware drivers. The company declared that it was killing Windows Device metadata and the Windows Metadata and Internet Services (WMIS). For those wondering what it is, device metadata, as the name suggests, is the collection of additional, user-facing information that an original equipment manufacturer (OEM) provides about a hardware device. The feature was introduced with Windows 7 and can include stuff like icons, logos, descriptive texts, among other things, that help the Windows UI display details about such devices in places like Task Manager or Device Manager. This was a huge deal back in the day when Windows 7 debuted. The company called the feature "Device Stage" and Microsoft described it as a "new visual interface" that essentially worked like a "multi-function version of Autoplay where it displays all the applications, services, and information related to your device." It is often considered synonymous with the Windows "Devices and Printers" Control Panel applet. Neowin did an in-depth overview of the feature when it first launched which you can find in its dedicated article here. The Windows OS was able to obtain the device experience metadata from the WMIS, but now that the feature is being deprecated, Microsoft has begun removing information about Device Stage from its official support documents. Neowin noticed while browsing that a support article regarding automatic Windows hardware drivers was updated for Windows 11 and 10 sometime last year after the release of Windows 11 24H2. Previously, this article was geared for Windows 7 and was much longer. It also contained information about Device Stage, which, as mentioned above, was a headlining feature on Windows 7. In the said article, the section "If Windows can't find information about your device in Device Stage" has been deleted. You can find the archived version of the support page here. Aside from shortening the amount of information on the page, Microsoft has also added some more details on it. The company has now tried to define what the Microsoft Basic Display Adapter is, how updating drivers through Device Manager works, as well as a thorough and detailed troubleshooting section for common hardware driver errors on Windows, including one for USB-C. You can find all the new details on the updated support page here on Microsoft's website.
    • Sounds creepy to say the least. Don't need nor want AI having access to my history. They're claiming it to be an "offline" model now, but how can we guarantee they don't go behind our backs and change that?
    • Exactly! Without those fundamentals you've mentioned, Democracy is literally just Demonstration of Crazy, nothing to be proud of in such system.
  • Recent Achievements

    • Veteran
      Yonah went up a rank
      Veteran
    • First Post
      viraltui earned a badge
      First Post
    • Reacting Well
      viraltui earned a badge
      Reacting Well
    • Week One Done
      LunaFerret earned a badge
      Week One Done
    • Week One Done
      Ricky Chan earned a badge
      Week One Done
  • Popular Contributors

    1. 1
      +primortal
      481
    2. 2
      +FloatingFatMan
      264
    3. 3
      snowy owl
      238
    4. 4
      ATLien_0
      232
    5. 5
      Edouard
      176
  • Tell a friend

    Love Neowin? Tell a friend!