8

During the lifetime of a .NET process, does the handle of a System.Windows.Forms.Form, lets say the main form used in Application.Run(form) actually change it's value, i.e. if using the value of the handle in a different process, e.g. IntPtr handle = User32.FindWindow(null, "Name"), is there a case where that handle might be invalidated by the .NET runtime?

EDIT

I need to know the handles because I want to use SendMessage and WM_COPYDATA and the like for IPC.

Sebastian
  • 6,293
  • 6
  • 34
  • 47
  • I think a window handle is unchangeable during lifetime of the window, no matter .Net or not .Net – nabuchodonossor Jul 21 '11 at 07:30
  • @nabuchodonossor: Yes, that's correct. The trick is that the window can be recreated under the hood, effectively changing its lifetime but not in a way that the user is going to notice or even the programmer who is working at the high level of abstraction that the .NET FW provides for the Win32 API. – Cody Gray - on strike Jul 21 '11 at 10:48
  • what about an effectively invisible window which will not be touched at all? should be permanent then, right? – Sebastian Jul 21 '11 at 10:49

1 Answers1

10

A window handle is guaranteed to be valid and not get reused for as long as the window lives. It's index like in nature, valid globally and generally behaves more like a global ID than like a kernel handle(which are only valid in one process and pointer like in nature). Once the window gets closed the window handle might get reused and now points to another window.

But what's not obvious is if the lifetime of the Form and the underlying windows window are the same. I vaguely remember that in Delphi's VCL(Which is the spiritual predecessor of Windows.Forms) certain property changes recreated the window in the background.

The existence of the Control.RecreatingHandle property seems like a strong indication that indeed the lifetime of the underlying window can be shorter than the lifetime of the .net control. Which could lead to the handle of a Form changing during its lifetime.

Control.RecreateHandle
The RecreateHandle method is called whenever parameters are needed for a new control, but using a call from UpdateStyles to CreateParams is insufficient. This method also calls DestroyHandle and CreateHandle and sets RecreatingHandle to true.
http://msdn.microsoft.com/en-us/library/system.windows.forms.control.recreatehandle.aspx

From the description of this method I conclude that the window handle can indeed change during the lifetime of the form.

CodesInChaos
  • 106,488
  • 23
  • 218
  • 262
  • I always thought kernel handles behaved like indices too - how else would handle inheritance work? – Niki Jul 21 '11 at 08:07
  • Control.RecreateHandle ; good point there, I didn't think that it was actually destroying and re-creating the handle but it looks like it does. – Teoman Soygul Jul 21 '11 at 08:09
  • 1
    What I remember is that kernel handles originally were implemented as normal pointers. But at some point MS decided to obfuscate them to deter people from dereferencing them and then working on the undocumented data-structure at its end. That's reason why you normally need to duplicate handles with `DuplicateHandle` to use them across processes. "A duplicated or inherited handle is a unique value, but it refers to the same object as the original handle." so it looks like inheriting isn't much different from duplicating it manually. – CodesInChaos Jul 21 '11 at 08:12
  • Yes, **lots** of operations cause the controls to recreate themselves, and thus change their handles. Any property that sets style flags on the underlying control is likely to do this. The problem is that you're saving the window handle in the first place. This is working at the wrong level of abstraction for a .NET app. – Cody Gray - on strike Jul 21 '11 at 10:45
  • @Cody Gray, well I want to use `SendMessage` and `WM_COPYDATA` and the like, for that I need to know the handles – Sebastian Jul 21 '11 at 10:47
  • 2
    @Sebastian: Sure, the handles are available from .NET. My point is that you should retrieve them from the `Handle` property of the control whenever you need them, rather than trying to *store* the handles in an `IntPtr` variable somewhere yourself. Keep references to the control classes, not the handles. – Cody Gray - on strike Jul 21 '11 at 10:49
  • @Cody Gray: But I don't have the references to the Control in a different process (with a different language), so far it seems the only liable option to copy the IntPtr – Sebastian Jul 22 '11 at 20:26
  • 2
    @Sebastian: Okay, fair enough. I'd add some debug-time assertions that validate the window handle is valid, though. As we discussed, the only thing that's going to cause Windows to re-create the window (assigning it a new handle) is you changing properties or styles of that window. That means you can easily catch this at debug time, and if no assertions are triggered, you know that you'll be fine when the app is released. Check into P/Invoking the [`IsWindow` function](http://msdn.microsoft.com/en-us/library/ms633528.aspx) to do this validation in an assert. – Cody Gray - on strike Jul 23 '11 at 08:37