8

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

3 回答 3

2

您的声明:

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

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

更新以下评论:

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

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

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

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

于 2009-05-11T02:29:11.000 回答
2

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.");
    }
}
于 2011-06-02T17:57:20.300 回答
-1

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

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

如您所见,它的大小是pdwNumberOfPhysicalMonitors

PHYSICAL_MONITOR[] pPhysicalMonitorArray = new PHYSICAL_MONITOR[dwPhysicalMonitorArraySize];

我正在运行 Vista 32。

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

谢谢你。

于 2009-05-11T11:46:47.557 回答