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

GetDC returns HDC but it should return a SafeHandle that calls ReleaseDC #209

Open
jnm2 opened this issue Mar 17, 2021 · 4 comments
Open

Comments

@jnm2
Copy link
Contributor

jnm2 commented Mar 17, 2021

I would also really love to have a public HWnd property on the safe handle. It should be stored in the safe handle anyway in order to call ReleaseDC, and it's also very useful in cases like this:

windowDC.Dispose();
windowDC = User32.GetDC(windowDC.HWnd);

The current workaround is to say new ReleaseDCSafeHandle(hwnd, PInvoke.GetDC(hwnd)) instead of PInvoke.GetDC(hwnd):

internal sealed class ReleaseDCSafeHandle : DeleteDCSafeHandle
{
    public ReleaseDCSafeHandle(HWND hWnd, IntPtr handle)
        : base(handle)
    {
        HWnd = hWnd;
    }

    public HWND HWnd { get; }

    protected override bool ReleaseHandle() => ReleaseDC(HWnd, handle);

    /// <summary>
    /// <seealso href="https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-releasedc"/>
    /// </summary>
    [DllImport("user32.dll")]
    private static extern bool ReleaseDC(HWND hWnd, IntPtr hDC);
}
@AArnott
Copy link
Member

AArnott commented Mar 17, 2021

GetDC already has a SafeHandle-returning variant. This usually appears as an overload of the original HANDLE-based method, but when the method parameters do not change (such that only the return type changes) in C# we must change the method name itself since method overloads are not allowed to change only by their return types.
So check out GetDC_SafeHandle, which returns DeleteDCSafeHandle.

Now, you wanted to see ReleaseDCSafeHandle instead, which is correct. We return the wrong type because of microsoft/win32metadata#251, which I see was fixed yesterday.

@AArnott
Copy link
Member

AArnott commented Mar 17, 2021

Your proposal for handling the oddity of HDC requiring two values to release seems reasonable. That's a lot of customization, but handling this at all (rather than giving up and just generating HDC APIs) will require at least some of it.

AArnott added a commit that referenced this issue Aug 17, 2021
@jnm2
Copy link
Contributor Author

jnm2 commented Nov 16, 2021

@AArnott Now that I know how templates work, do you mind if I add one for ReleaseDCSafeHandle (is that the naming convention you would want)?

Then to make this useful, can we hardcode the knowledge that GetDC returns ReleaseDCSafeHandle without waiting for metadata to figure something out?

@AArnott
Copy link
Member

AArnott commented Nov 16, 2021

Then to make this useful, can we hardcode the knowledge that GetDC returns ReleaseDCSafeHandle without waiting for metadata to figure something out?

The metadata bug was fixed ages ago (Mar 16). It already indicates that GetDC returns a ReleaseDC-released value. I think the only thing then that needs to be taught to CsWin32 (and possibly the metadata) is the special bit about retaining the extra value while constructing the SafeHandle, which will require some customization.
Yes, if you want to take this on I'd appreciate it. And yes please stick with the naming convention we use for generated safe handles. I expect you'll generate a SafeHandle-derived type similar to our auto-generated types, but with a constructor that takes two args and a special Release method implementation. Then teach anything that returns an HDC how to construct this particular type.

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

No branches or pull requests

2 participants