GetPhysicalMonitorsFromHMONITOR返回的句柄始终为null

时间:2009-05-11 02:18:36

标签: interop unmanaged structure intptr

在Media Foundation SDK上有GetPhysicalMonitorsFromHMONITOR功能 我试图用C#实现,但没有运气......

在返回的PHYSICAL_MONITOR []中,函数返回监视器的字符串描述,但出于某些神秘的原因, hPhysicalMonitor 句柄仍为0。

我使用P / Invoke Interop助手生成了签名,只做了一些修改。

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.");
            }
        }
    }
}

3 个答案:

答案 0 :(得分:1)

您的陈述:

  

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

是对的。如果您查看文档here,您会看到hMonitor显然是[in]参数,不会更改。

更新以下评论:

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

根据MSDN上针对该特定调用的文档,所有结构定义对我来说都很合适。事实上, 为您填写说明。

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

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

答案 1 :(得分:1)

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.");
    }
}

答案 2 :(得分:-1)

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

返回 pdwNumberOfPhysicalMonitors 值为1是正确的。

如您所见,其大小为 pdwNumberOfPhysicalMonitors

PHYSICAL_MONITOR[] pPhysicalMonitorArray = new PHYSICAL_MONITOR[dwPhysicalMonitorArraySize];

我正在运行Vista 32。

这有点奇怪,因为它的一半有效,现在大约4天我已经超过它但仍然没有进展......

谢谢。