views:

350

answers:

2

Hi,

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

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?

paxdiablo
Sorry but I made a mistake, I corrected my post. (I was looking for hPhysicalMonitor in fact)
A: 

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.

Also, I had to change the string description in PHYSICAL_MONITOR,because with P/Invoke Interop Assistant, SizeConst was set to -1, which is illegal.