Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(c#) Why now struct HWND instead of IntPtr ? #61

Closed
Micke3rd opened this issue Jan 24, 2021 · 10 comments
Closed

(c#) Why now struct HWND instead of IntPtr ? #61

Micke3rd opened this issue Jan 24, 2021 · 10 comments
Labels
question Further information is requested

Comments

@Micke3rd
Copy link

Hi,
outside of this project the parameter type for handles is IntPtr, e.g.:
GetWindow(IntPtr hWnd, ...)
SetFocus(IntPtr hWnd)

That fits to the return type of functions which deliver these arguments like:
IntPtr Process.MainWindowHandle { get; }
IntPtr System.Windows.Interop.WindowInteropHelper.Handle { get; }

But win32metadata generates functions with Microsoft.Windows.Sdk.HWND as parameter type. E.g.:
PInvoke.GetWindow( HWND hwnd, ... );
PInvoke.SetFocus( HWND hwnd );
With the consequence, that we first have to convert IntPtr returns to HWND, before we can use win32metadata stuff.

What is the intension behind that type change ?
Whatever disadvantage is removed at HWND site isn't completely gone, its presumably just moved to that convert place.

thank you in advance for any candle light

@AArnott AArnott transferred this issue from microsoft/win32metadata Jan 24, 2021
@AArnott
Copy link
Member

AArnott commented Jan 24, 2021

We use structs for each unique handle type to give added type safety, similar to that enjoyed by C developers. HWND as a parameter type immediately gives an idea on its content and where you might come by a value to fit, whereas IntPtr tells nearly nothing.

Our structs that serve as IntPtr substitutes are implicitly convertable to IntPtr, so you can use them without casts anywhere that an IntPtr is expected.
You can also explicitly cast any IntPtr to one of these structs, making it nearly as convenient to go the other way as well.

@AArnott AArnott added the question Further information is requested label Jan 24, 2021
@Micke3rd
Copy link
Author

I understand, thank you.

@michael-hawker
Copy link

@AArnott is this documented somewhere? You get an IntPtr from the Process APIs, so it's not clear compared to the old manual way of doing PInvoke how to pass those into the generated methods (e.g. SetForegroundWindow).

It sounds like you can just do:

     PInvoke.SetForegroundWindow((HWD)process.MainWindowHandle);

@AArnott
Copy link
Member

AArnott commented Jun 25, 2021

Yes, you can cast them. If Process APIs use IntPtr instead of handle struct types, can you please file a bug at https://github.com/microsoft/win32metadata/issues giving specific APIs as examples?

@AArnott
Copy link
Member

AArnott commented Jun 29, 2021

I'm sorry for misdirecting you.
.NET has a convention that we use implicit conversion operators for lossy or base type conversions, and explicit conversion operators for derived types. In this case every HWND is an IntPtr, but not every IntPtr is an HWND. This is why we have the HWND conversion operators set up like this:

public static implicit operator nint(HWND value) => value.Value;
public static explicit operator HWND(nint value) => new HWND(value);

Note that nint is equivalent to IntPtr for our purposes here (although it actually should be an IntPtr... that's a regression #312).

@jnm2
Copy link
Contributor

jnm2 commented Jun 29, 2021

If Process APIs use IntPtr instead of handle struct types, can you please file a bug at https://github.com/microsoft/win32metadata/issues giving specific APIs as examples?

I believe his example was showing the BCL Process API https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.process.mainwindowhandle.

@michael-hawker
Copy link

Thanks @AArnott, should we re-open this issue for tracking the regression then?

@AArnott
Copy link
Member

AArnott commented Jun 30, 2021

@michael-hawker What is the regression? Per my last comment, the behavior of requiring an explicit cast to "upgrade" an IntPtr to an HWND is by design with strong precedent in the .NET community. And it's also by design that the metadata and generated code use HWND as a more concrete type than IntPtr.

@jnm2
Copy link
Contributor

jnm2 commented Jun 30, 2021

@michael-hawker Did you mean the regression Andrew mentioned as already being tracked at #312?

@michael-hawker
Copy link

@michael-hawker Did you mean the regression Andrew mentioned as already being tracked at #312?

Yup, sorry. Didn't connect the dots that that issue was tracking the regression itself.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

4 participants