• 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

    • How to take HDR screenshots on your iPhone running iOS 26, and other new features by Aditya Tiwari Apple has leveled up the screenshots game on its latest iPhone software update, iOS 26. Alongside the updated Photos app, Compact mode in Safari, and new wallpapers, iOS 26 comes with a redesigned screenshot editor, featuring the controversial Liquid Glass system design. The iOS 26 update brings new features and changes that let you customize your screenshot experience in a better way. For starters, it displays the captured screenshot with rounded corners, shifting away from the rectangle on iOS 18. Turn on HDR screenshots on iOS 26 A highlight of the updated screenshots features on iOS 26 is that you can take screenshots in HDR (High Dynamic Range). Apple has added a new Screen Capture page in the Settings app that lets you do that. You can follow these steps to enable HDR screenshots on iOS 26: Open the Settings app on iOS 26. Go to General > Screen Capture. Now, select the HDR option under the Format section. Press the Home + Volume Up button combination to take a screenshot. Next time you take a screenshot on your iPhone, it will be captured with full dynamic range and stored in HEIF format. In other words, if you take a screenshot of a photo and video available in HDR, the feature will preserve those details. On the other hand, the SDR quality saves screenshots in PNG format and offers more compatibility. As shown in the image below, you can check whether a screenshot is captured in HDR or not by swiping up on a screenshot in the Photos app to open its details. Record your iPhone screen in HDR on iOS 26 Not just screenshots, the HDR option also works for screen recordings. Such files are saved in HEVC HDR10 format, whereas screen recordings taken in SDR mode are saved in HEVC. After switching to the HDR options using the steps above, you can use the same old steps to screen record your iPhone; the option is available in the Control Center. That said, you can do a lot more to improve your screenshot experience on iOS 26. The Screen Capture page in the Settings app lets you customize your screenshot experience in multiple ways. Here's how use can use the different features Apple has added in iOS 26. Turn on full-screen previews by default When you turn on the "Full-Screen Previews" toggle button on the Screen Capture page, iOS 26 will display screenshots in full view instead of showing a small thumbnail in the bottom left corner that vanishes after a few seconds. The full-blown UI allows you to quickly edit or annotate a screenshot and share it with your friends across various apps. Alternatively, you can disable the toggle option and trigger this UI by tapping on the temporary thumbnail that shows up after taking the screenshot. Prevent CarPlay screenshots from flooding your device Apple has also changed (fixed) how screenshots work on CarPlay. Until now, screenshots on CarPlay have been an "it's a feature, not a bug" experience for the users. If your iPhone is connected to your car, an extra screenshot of the CarPlay interface is automatically captured when you press the buttons to take a screenshot on your phone. This functionality has been a pain point for many users, who have raised their voice on Apple's support forums. It seems the company heard them, and iOS 26 update brings a new toggle button in the picture, allowing you to have a manual way to enable or disable CarPlay screenshots. Use Visual Intelligence on screenshots iPhone's screenshot tool also supports the improved Visual Intelligence feature (works on iPhone 15 Pro or later). You can select objects in a screenshot and search for matching content in apps that offer integration with Visual Intelligence. These screenshot updates for iOS 26 are currently available for testing through the developer beta program on supported iPhone models. Apple is expected to release the first public beta of iOS 26 next month. If you plan to install the developer beta on your device, note that early builds may be unstable, and ensure that you back up your data in advance.
    • Looking around, it seems to indicate that an App is doing a download in the background.
    • Dopamine 3.0 Preview 39 by Razvan Serea Dopamine is an awesome free audio player which tries to make organizing and listening to music as simple and pretty as possible. Dopamine has been designed for Windows 7, Windows 8.x and Windows 10 and plays mp3, ogg vorbis, flac, wma and m4a/aac music formats quite well. The best part? It's created by long-time Neowin member, Raphaël Godart. If you’re looking for a music player to handle a large music collection, you should definitely give Dopamine a try. Dopamine 3.0 Preview 38 changelog: Added Added Ctrl-F shortcut to focus the search bar and ESC to clear it Added support for cover art images that have file name albumart.jpg, albumart.jpeg or albumart.png Added Turkish translation Changed Slightly improved the look of the mini player Improved scaling of text on Now Playing screen for smaller screens Order selections are now menus instead of toggle buttons Updated the Brazilian Portuguese translation Updated the Spanish translation Updated the Turkish translation Updated the Vietnamese translation Fixed Fixed an issue where a random song would start playing after the queue ended when using gapless playback. Fixed an issue where album lists were not refreshed after a search returned no results. Fixed an issue where progress was not reset to 0 when playback has finished Fixed an issue where a track that is longer than 4 minutes was scrobbled to Last.fm immediately after it started playing Fixed some sizing issues on the "Folders" screen Fixed search problems Download: Dopamine 3.0 Preview 39 | 98.4 MB (Open Source) View: Dopamine Home Page | Forum Discussion | Screenshot Get alerted to all of our Software updates on Twitter at @NeowinSoftware
  • Recent Achievements

    • One Month Later
      serfegyed earned a badge
      One Month Later
    • Dedicated
      firey earned a badge
      Dedicated
    • Dedicated
      fettermanj earned a badge
      Dedicated
    • One Month Later
      SekTheFirst earned a badge
      One Month Later
    • First Post
      zayanhani earned a badge
      First Post
  • Popular Contributors

    1. 1
      +primortal
      639
    2. 2
      ATLien_0
      232
    3. 3
      Michael Scrip
      219
    4. 4
      Xenon
      147
    5. 5
      Steven P.
      141
  • Tell a friend

    Love Neowin? Tell a friend!