microsoft / CsWin32

A source generator to add a user-defined set of Win32 P/Invoke methods and supporting types to a C# project.
MIT License
2.06k stars 87 forks source link

GetMonitorInfo method generates parameters compatible only with the MONITORINFO struct and not MONITORINFOEXW or MONITORINFOEXA. #917

Closed waylaa closed 1 year ago

waylaa commented 1 year ago

The title says it all. Normally, GetMonitorInfo() should be generated with multiple overloads that support both 3 of said structs.

NativeMethods.txt content: WM_CLOSE SEND_MESSAGE_TIMEOUT_FLAGS EnumWindowsProc EnumWindows FindWindow FindWindowEx SetParent SendMessageTimeout SendMessage ShowWindow

MONITORINFOEXW MONITORENUMPROC EnumDisplayMonitors GetMonitorInfo

AArnott commented 1 year ago

GetMonitorInfo in native code only takes MONITORINFO*. C# emits this same signature. Just like in native code, you can pass a pointer to a MONITORINFOEXW structure to this method, which is why the structure's first field is a cbSize so that the receiver can tell which type of structure was passed in.

CsWin32 also generates friendly overloads, which in this case turns MONITORINFO* into ref MONITORINFO, and C# won't let you pass the EX structs to a ref parameter. If you want to pass the EX structs, you'll have to use the pointer syntax.

For example:

unsafe
{
    HMONITOR monitor = default;
    var info = new MONITORINFOEXW
    {
        monitorInfo =
        {
            cbSize = (uint)sizeof(MONITORINFOEXW),
            // more
        },
        szDevice = default,
    };
    if (!PInvoke.GetMonitorInfo(monitor, (MONITORINFO*)&info))
    {
        throw new Win32Exception();
    }
}
waylaa commented 1 year ago

Got it. Thank you for helping.