GetPhysicalMonitorsFromHMONITOR 返回的句柄始终为 null

发布于 2024-07-19 15:10:39 字数 5778 浏览 5 评论 0原文

在 Media Foundation SDK 上有 GetPhysicalMonitorsFromHMONITOR 函数 我正在尝试使用 C# 实现,但没有成功...

在返回的 PHYSICAL_MONITOR[] 中,该函数返回监视器的字符串描述,但由于一些神秘的原因,hPhysicalMonitor 句柄保持为 0 我已

使用 P/Invoke Interop Assistant 生成了签名,并进行了少量修改。

PHYSICAL_MONITOR 结构或其他任何内容是否需要进一步调整?

谢谢。

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using WindowsFormsApplication1;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public enum MC_DISPLAY_TECHNOLOGY_TYPE
        {
            MC_SHADOW_MASK_CATHODE_RAY_TUBE,

            MC_APERTURE_GRILL_CATHODE_RAY_TUBE,

            MC_THIN_FILM_TRANSISTOR,

            MC_LIQUID_CRYSTAL_ON_SILICON,

            MC_PLASMA,

            MC_ORGANIC_LIGHT_EMITTING_DIODE,

            MC_ELECTROLUMINESCENT,

            MC_MICROELECTROMECHANICAL,

            MC_FIELD_EMISSION_DEVICE,
        }

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        public struct PHYSICAL_MONITOR
        {
            public IntPtr hPhysicalMonitor;

            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] public string szPhysicalMonitorDescription;
        }

        #region Imports

        [DllImport("user32.dll", EntryPoint = "MonitorFromWindow")]
        public static extern IntPtr MonitorFromWindow(
            [In] IntPtr hwnd, uint dwFlags);

        [DllImport("dxva2.dll", EntryPoint = "GetMonitorTechnologyType")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool GetMonitorTechnologyType(
            IntPtr hMonitor, ref MC_DISPLAY_TECHNOLOGY_TYPE pdtyDisplayTechnologyType);

        [DllImport("dxva2.dll", EntryPoint = "GetMonitorCapabilities")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool GetMonitorCapabilities(
            IntPtr hMonitor, ref uint pdwMonitorCapabilities, ref uint pdwSupportedColorTemperatures);

        [DllImport("dxva2.dll", EntryPoint = "DestroyPhysicalMonitors")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool DestroyPhysicalMonitors(
            uint dwPhysicalMonitorArraySize, ref PHYSICAL_MONITOR[] pPhysicalMonitorArray);

        [DllImport("dxva2.dll", EntryPoint = "GetNumberOfPhysicalMonitorsFromHMONITOR")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool GetNumberOfPhysicalMonitorsFromHMONITOR(
            IntPtr hMonitor, ref uint pdwNumberOfPhysicalMonitors);

        [DllImport("dxva2.dll", EntryPoint = "GetPhysicalMonitorsFromHMONITOR")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool GetPhysicalMonitorsFromHMONITOR(
            IntPtr hMonitor, uint dwPhysicalMonitorArraySize, [Out] PHYSICAL_MONITOR[] pPhysicalMonitorArray);

        #endregion

        public Form1() { InitializeComponent(); }

        private void Form1_Load(object sender, EventArgs e)
        {
            // Get monitor handle.
            uint dwFlags = 0u;
            IntPtr ptr = MonitorFromWindow(Handle, dwFlags);

            // Get number of physical monitors.
            uint pdwNumberOfPhysicalMonitors = 0u;
            bool b1 = GetNumberOfPhysicalMonitorsFromHMONITOR(ptr, ref pdwNumberOfPhysicalMonitors);

            if (b1)
            {
                // Get physical monitors.
                uint dwPhysicalMonitorArraySize = 0u;
                dwPhysicalMonitorArraySize = pdwNumberOfPhysicalMonitors;
                PHYSICAL_MONITOR[] pPhysicalMonitorArray = new PHYSICAL_MONITOR[dwPhysicalMonitorArraySize];

                //NOTE : Handles remain null !
                bool b2 = GetPhysicalMonitorsFromHMONITOR(ptr, dwPhysicalMonitorArraySize, pPhysicalMonitorArray);

                if (pPhysicalMonitorArray[0].hPhysicalMonitor
                    == IntPtr.Zero)
                {
                    throw new Exception("ERROR !");
                }

                // Monitor has capabilities to do that ?
                if (b2)
                {
                    uint pdwMonitorCapabilities = 0u;
                    uint pdwSupportedColorTemperatures = 0u;
                    bool b3 = GetMonitorCapabilities(
                        ptr, ref pdwMonitorCapabilities, ref pdwSupportedColorTemperatures);

                    // If yes, get technology type.
                    if (b3)
                    {
                        MC_DISPLAY_TECHNOLOGY_TYPE type = MC_DISPLAY_TECHNOLOGY_TYPE.MC_SHADOW_MASK_CATHODE_RAY_TUBE;

                        bool b4 = GetMonitorTechnologyType(ptr, ref type);
                        if (b4)
                        {
                            // Do work.
                        }
                        else
                        {
                            throw new Exception("Couldn't get monitor technology type.");
                        }
                    }
                    else
                    {
                        throw new Exception("Couldn't get monitor capabilities.");
                    }
                }
                else
                {
                    throw new Exception("The monitor doesn't have the required capabilities.");
                }

                bool b5 = DestroyPhysicalMonitors(dwPhysicalMonitorArraySize, ref pPhysicalMonitorArray);
                if (!b5)
                {
                    throw new Exception("Couldn't destroy physical monitors.");
                }
            }
            else
            {
                throw new Exception("Couldn't get number of physical monitors.");
            }
        }
    }
}

On the Media Foundation SDK there is the GetPhysicalMonitorsFromHMONITOR function
that I am trying to implement using C# but with no luck ...

In the returned PHYSICAL_MONITOR[], the function returns the string description of the monitor but for some mysterious reasons, the hPhysicalMonitor handle remains at 0.

I have generated the signatures with P/Invoke Interop Assistant with minor modifications.

Does the PHYSICAL_MONITOR structure or anything else needs further tuning ?

Thank you.

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using WindowsFormsApplication1;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public enum MC_DISPLAY_TECHNOLOGY_TYPE
        {
            MC_SHADOW_MASK_CATHODE_RAY_TUBE,

            MC_APERTURE_GRILL_CATHODE_RAY_TUBE,

            MC_THIN_FILM_TRANSISTOR,

            MC_LIQUID_CRYSTAL_ON_SILICON,

            MC_PLASMA,

            MC_ORGANIC_LIGHT_EMITTING_DIODE,

            MC_ELECTROLUMINESCENT,

            MC_MICROELECTROMECHANICAL,

            MC_FIELD_EMISSION_DEVICE,
        }

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        public struct PHYSICAL_MONITOR
        {
            public IntPtr hPhysicalMonitor;

            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] public string szPhysicalMonitorDescription;
        }

        #region Imports

        [DllImport("user32.dll", EntryPoint = "MonitorFromWindow")]
        public static extern IntPtr MonitorFromWindow(
            [In] IntPtr hwnd, uint dwFlags);

        [DllImport("dxva2.dll", EntryPoint = "GetMonitorTechnologyType")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool GetMonitorTechnologyType(
            IntPtr hMonitor, ref MC_DISPLAY_TECHNOLOGY_TYPE pdtyDisplayTechnologyType);

        [DllImport("dxva2.dll", EntryPoint = "GetMonitorCapabilities")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool GetMonitorCapabilities(
            IntPtr hMonitor, ref uint pdwMonitorCapabilities, ref uint pdwSupportedColorTemperatures);

        [DllImport("dxva2.dll", EntryPoint = "DestroyPhysicalMonitors")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool DestroyPhysicalMonitors(
            uint dwPhysicalMonitorArraySize, ref PHYSICAL_MONITOR[] pPhysicalMonitorArray);

        [DllImport("dxva2.dll", EntryPoint = "GetNumberOfPhysicalMonitorsFromHMONITOR")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool GetNumberOfPhysicalMonitorsFromHMONITOR(
            IntPtr hMonitor, ref uint pdwNumberOfPhysicalMonitors);

        [DllImport("dxva2.dll", EntryPoint = "GetPhysicalMonitorsFromHMONITOR")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool GetPhysicalMonitorsFromHMONITOR(
            IntPtr hMonitor, uint dwPhysicalMonitorArraySize, [Out] PHYSICAL_MONITOR[] pPhysicalMonitorArray);

        #endregion

        public Form1() { InitializeComponent(); }

        private void Form1_Load(object sender, EventArgs e)
        {
            // Get monitor handle.
            uint dwFlags = 0u;
            IntPtr ptr = MonitorFromWindow(Handle, dwFlags);

            // Get number of physical monitors.
            uint pdwNumberOfPhysicalMonitors = 0u;
            bool b1 = GetNumberOfPhysicalMonitorsFromHMONITOR(ptr, ref pdwNumberOfPhysicalMonitors);

            if (b1)
            {
                // Get physical monitors.
                uint dwPhysicalMonitorArraySize = 0u;
                dwPhysicalMonitorArraySize = pdwNumberOfPhysicalMonitors;
                PHYSICAL_MONITOR[] pPhysicalMonitorArray = new PHYSICAL_MONITOR[dwPhysicalMonitorArraySize];

                //NOTE : Handles remain null !
                bool b2 = GetPhysicalMonitorsFromHMONITOR(ptr, dwPhysicalMonitorArraySize, pPhysicalMonitorArray);

                if (pPhysicalMonitorArray[0].hPhysicalMonitor
                    == IntPtr.Zero)
                {
                    throw new Exception("ERROR !");
                }

                // Monitor has capabilities to do that ?
                if (b2)
                {
                    uint pdwMonitorCapabilities = 0u;
                    uint pdwSupportedColorTemperatures = 0u;
                    bool b3 = GetMonitorCapabilities(
                        ptr, ref pdwMonitorCapabilities, ref pdwSupportedColorTemperatures);

                    // If yes, get technology type.
                    if (b3)
                    {
                        MC_DISPLAY_TECHNOLOGY_TYPE type = MC_DISPLAY_TECHNOLOGY_TYPE.MC_SHADOW_MASK_CATHODE_RAY_TUBE;

                        bool b4 = GetMonitorTechnologyType(ptr, ref type);
                        if (b4)
                        {
                            // Do work.
                        }
                        else
                        {
                            throw new Exception("Couldn't get monitor technology type.");
                        }
                    }
                    else
                    {
                        throw new Exception("Couldn't get monitor capabilities.");
                    }
                }
                else
                {
                    throw new Exception("The monitor doesn't have the required capabilities.");
                }

                bool b5 = DestroyPhysicalMonitors(dwPhysicalMonitorArraySize, ref pPhysicalMonitorArray);
                if (!b5)
                {
                    throw new Exception("Couldn't destroy physical monitors.");
                }
            }
            else
            {
                throw new Exception("Couldn't get number of physical monitors.");
            }
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

漆黑的白昼 2024-07-26 15:10:40

hPhysicalMonitor 值为 0 是可以的。但是,在问题的代码示例中,GetPhysicalMonitorsFromHMONITOR 之后的所有调用都应使用 hPhysicalMonitor 引用而不是 ptr 引用。 更新后的 Form_Load 方法应如下所示:

private void Form1_Load(object sender, EventArgs e)
{
    // Get monitor handle.
    uint dwFlags = 0u;
    IntPtr ptr = MonitorFromWindow(Handle, dwFlags);

    // Get number of physical monitors.
    uint pdwNumberOfPhysicalMonitors = 0u;
    bool b1 = GetNumberOfPhysicalMonitorsFromHMONITOR(ptr, ref pdwNumberOfPhysicalMonitors);

    if (b1)
    {
        // Get physical monitors.
        uint dwPhysicalMonitorArraySize = 0u;
        dwPhysicalMonitorArraySize = pdwNumberOfPhysicalMonitors;
        PHYSICAL_MONITOR[] pPhysicalMonitorArray = new PHYSICAL_MONITOR[dwPhysicalMonitorArraySize];

        //NOTE : Handles remain null !
        bool b2 = GetPhysicalMonitorsFromHMONITOR(ptr, dwPhysicalMonitorArraySize, pPhysicalMonitorArray);

        // Monitor has capabilities to do that ?
        if (b2)
        {
            uint pdwMonitorCapabilities = 0u;
            uint pdwSupportedColorTemperatures = 0u;
            bool b3 = GetMonitorCapabilities(pPhysicalMonitorArray[0].hPhysicalMonitor, ref pdwMonitorCapabilities, ref pdwSupportedColorTemperatures);

            // If yes, get technology type.
            if (b3)
            {
                MC_DISPLAY_TECHNOLOGY_TYPE type = MC_DISPLAY_TECHNOLOGY_TYPE.MC_SHADOW_MASK_CATHODE_RAY_TUBE;

                bool b4 = GetMonitorTechnologyType(pPhysicalMonitorArray[0].hPhysicalMonitor, ref type);
                if (b4)
                {
                    // Do work.
                }
                else
                {
                    throw new Exception("Couldn't get monitor technology type.");
                }
            }
            else
            {
                throw new Exception("Couldn't get monitor capabilities.");
            }
        }
        else
        {
            throw new Exception("The monitor doesn't have the required capabilities.");
        }

        bool b5 = DestroyPhysicalMonitors(dwPhysicalMonitorArraySize, ref pPhysicalMonitorArray);
        if (!b5)
        {
            throw new Exception("Couldn't destroy physical monitors.");
        }
    }
    else
    {
        throw new Exception("Couldn't get number of physical monitors.");
    }
}

It is alright that the hPhysicalMonitor value is 0. However, in the question's code sample all calls after the GetPhysicalMonitorsFromHMONITOR should use the hPhysicalMonitor reference instead of the ptr reference. The updated Form_Load method should be the following:

private void Form1_Load(object sender, EventArgs e)
{
    // Get monitor handle.
    uint dwFlags = 0u;
    IntPtr ptr = MonitorFromWindow(Handle, dwFlags);

    // Get number of physical monitors.
    uint pdwNumberOfPhysicalMonitors = 0u;
    bool b1 = GetNumberOfPhysicalMonitorsFromHMONITOR(ptr, ref pdwNumberOfPhysicalMonitors);

    if (b1)
    {
        // Get physical monitors.
        uint dwPhysicalMonitorArraySize = 0u;
        dwPhysicalMonitorArraySize = pdwNumberOfPhysicalMonitors;
        PHYSICAL_MONITOR[] pPhysicalMonitorArray = new PHYSICAL_MONITOR[dwPhysicalMonitorArraySize];

        //NOTE : Handles remain null !
        bool b2 = GetPhysicalMonitorsFromHMONITOR(ptr, dwPhysicalMonitorArraySize, pPhysicalMonitorArray);

        // Monitor has capabilities to do that ?
        if (b2)
        {
            uint pdwMonitorCapabilities = 0u;
            uint pdwSupportedColorTemperatures = 0u;
            bool b3 = GetMonitorCapabilities(pPhysicalMonitorArray[0].hPhysicalMonitor, ref pdwMonitorCapabilities, ref pdwSupportedColorTemperatures);

            // If yes, get technology type.
            if (b3)
            {
                MC_DISPLAY_TECHNOLOGY_TYPE type = MC_DISPLAY_TECHNOLOGY_TYPE.MC_SHADOW_MASK_CATHODE_RAY_TUBE;

                bool b4 = GetMonitorTechnologyType(pPhysicalMonitorArray[0].hPhysicalMonitor, ref type);
                if (b4)
                {
                    // Do work.
                }
                else
                {
                    throw new Exception("Couldn't get monitor technology type.");
                }
            }
            else
            {
                throw new Exception("Couldn't get monitor capabilities.");
            }
        }
        else
        {
            throw new Exception("The monitor doesn't have the required capabilities.");
        }

        bool b5 = DestroyPhysicalMonitors(dwPhysicalMonitorArraySize, ref pPhysicalMonitorArray);
        if (!b5)
        {
            throw new Exception("Couldn't destroy physical monitors.");
        }
    }
    else
    {
        throw new Exception("Couldn't get number of physical monitors.");
    }
}
呆萌少年 2024-07-26 15:10:40

显示器支持此功能,因为使用softMCCS和WinI2C/DDC等软件,
属性已正确返回。

返回的 pdwNumberOfPhysicalMonitors 值为 1,这是正确的。

正如你所看到的,它的大小是pdwNumberOfPhysicalMonitors

PHYSICAL_MONITOR[] pPhysicalMonitorArray = new PHYSICAL_MONITOR[dwPhysicalMonitorArraySize];

我运行的是Vista 32。

这有点奇怪,因为一半可以工作,现在大约4天了,我已经完成了它,但仍然没有进展......

谢谢。

The monitor supports this function because with software like softMCCS and WinI2C/DDC,
the properties are returned correctly.

The return pdwNumberOfPhysicalMonitors value is 1 which is correct.

As you can see, its size is pdwNumberOfPhysicalMonitors :

PHYSICAL_MONITOR[] pPhysicalMonitorArray = new PHYSICAL_MONITOR[dwPhysicalMonitorArraySize];

And I am running Vista 32.

It is somewhat strange because half of it works, that's now about 4 days I am over it but still no progress ...

Thank you.

凤舞天涯 2024-07-26 15:10:39

您的声明:

该函数返回监视器的字符串描述,但由于某些神秘的原因,hMonitor 句柄保持为 0。

是正确的。 如果您查看此处的文档,您会发现将会看到 hMonitor 显然是一个 [in] 参数并且不会被更改。

更新以下评论:

抱歉,没有意识到您的意思是在结构中返回物理句柄。 我能找到的有关该特定问题的所有信息似乎都表明您的显示器可能不完全兼容 DDC/CI(例如,此处)。

根据 MSDN 上针对该特定调用的文档,您的所有结构定义对我来说都很好。 事实上,它正在为您填充描述。

GetNumberOfPhysicalMonitorsFromHMONITOR (pdwNumberOfPhysicalMonitors) 返回的物理监视器数量的值是多少?

另外,您的 PHYSICAL_MONITOR 结构的大小是多少?您运行的是 32 位还是 64 位?

Your statement:

The function returns the string description of the monitor but for some mysterious reasons, the hMonitor handle remains at 0.

is correct. If you look at the docs here, you'll see that hMonitor is clearly an [in] parameter and will not be changed.

Update following comment:

Sorry, didn't realize you meant the physical handle being returned in the structure. All the information I can find on that particular problem seems to indicate that your monitor probably isn't fully DDC/CI compatible (e.g., here).

All your structure definitions look fine to me, based on the docs on MSDN for that particular call. And indeed, it is populating the description for you.

What is the value for the number of physical monitors being returned from GetNumberOfPhysicalMonitorsFromHMONITOR (pdwNumberOfPhysicalMonitors)?

Also, what is the size of your PHYSICAL_MONITOR structure and are you running in 32 or 64 bits?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文