-1

Hi I am currently creating an animated desktop background that uses axWindowsMideaPlayer to play video files in a loop I take the WMP and set its handle to the desktop handle, it works great on single display monitor setup but fails with multiple monitors. Why it is failing is because monitors can have their own set position like left/right/topleft/topright/top/bottom/bottomleft and bottom right of the primary screen which puts their position in the negatives and so forth.. My question is how can I position each WMP correctly on each monitor? Here is what I have so far,

this is how I get each monitor...

public class DisplayInfo
{
    

    public bool isPrimary { get; set; }
    public int ScreenHeight { get; set; }
    public int ScreenWidth { get; set; }
    public Rect MonitorArea { get; set; }
    public Rect WorkArea { get; set; }
    public string DeviceName { get; set; }        
}

/// <summary>
/// Collection of display information
/// </summary>
public class DisplayInfoCollection : List<DisplayInfo>
{
    // size of a device name string
    private const int CCHDEVICENAME = 32;

    /// <summary>
    /// The MONITORINFOEX structure contains information about a display monitor.
    /// The GetMonitorInfo function stores information into a MONITORINFOEX structure or a MONITORINFO structure.
    /// The MONITORINFOEX structure is a superset of the MONITORINFO structure. The MONITORINFOEX structure adds a string member to contain a name
    /// for the display monitor.
    /// </summary>
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    internal struct MONITORINFOEX
    {
        /// <summary>
        /// The size, in bytes, of the structure. Set this member to sizeof(MONITORINFOEX) (72) before calling the GetMonitorInfo function.
        /// Doing so lets the function determine the type of structure you are passing to it.
        /// </summary>
        public int Size;

        /// <summary>
        /// A RECT structure that specifies the display monitor rectangle, expressed in virtual-screen coordinates.
        /// Note that if the monitor is not the primary display monitor, some of the rectangle's coordinates may be negative values.
        /// </summary>
        public Rect Monitor;

        /// <summary>
        /// A RECT structure that specifies the work area rectangle of the display monitor that can be used by applications,
        /// expressed in virtual-screen coordinates. Windows uses this rectangle to maximize an application on the monitor.
        /// The rest of the area in rcMonitor contains system windows such as the task bar and side bars.
        /// Note that if the monitor is not the primary display monitor, some of the rectangle's coordinates may be negative values.
        /// </summary>
        public Rect WorkArea;

        /// <summary>
        /// The attributes of the display monitor.
        ///
        /// This member can be the following value:
        ///   1 : MONITORINFOF_PRIMARY
        /// </summary>
        public uint Flags;

        /// <summary>
        /// A string that specifies the device name of the monitor being used. Most applications have no use for a display monitor name,
        /// and so can save some bytes by using a MONITORINFO structure.
        /// </summary>
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHDEVICENAME)]
        public string DeviceName;

        public void Init()
        {
            this.Size = 40 + 2 * CCHDEVICENAME;
            this.DeviceName = string.Empty;
        }
    }

    [DllImport("user32.dll")]
    private static extern bool EnumDisplayMonitors(IntPtr hdc, IntPtr lprcClip,
   EnumMonitorsDelegate lpfnEnum, IntPtr dwData);
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    private static extern bool GetMonitorInfo(IntPtr hMonitor, ref MONITORINFOEX lpmi);
    /*
    [DllImport("user32.dll")]
    static extern bool GetMonitorInfo(IntPtr hMonitor, ref MONITORINFO lpmi);
    */
    /// <summary>
    /// Returns the number of Displays using the Win32 functions
    /// </summary>
    /// <returns>collection of Display Info</returns>
    public static DisplayInfoCollection GetDisplays()
    {
        DisplayInfoCollection col = new DisplayInfoCollection();

        EnumDisplayMonitors(IntPtr.Zero, IntPtr.Zero,
            delegate (IntPtr hMonitor, IntPtr hdcMonitor, ref Rect lprcMonitor, IntPtr dwData)
            {
                MONITORINFOEX mi = new MONITORINFOEX();
                mi.Size = (int)Marshal.SizeOf(mi);
                bool success = GetMonitorInfo(hMonitor, ref mi);
                if (success)
                {
                    DisplayInfo di = new DisplayInfo();
                    di.ScreenWidth = (mi.Monitor.Right - mi.Monitor.Left);
                    di.ScreenHeight = (mi.Monitor.Bottom - mi.Monitor.Top);
                    di.MonitorArea = mi.Monitor;
                    di.WorkArea = mi.WorkArea;
                    di.isPrimary = Convert.ToBoolean(mi.Flags);
                    di.DeviceName = mi.DeviceName;                        
                    col.Add(di);
                }
                return true;
            }, IntPtr.Zero);
        return col;
    }
}

this is how I have tried to call it and use it but it puts WMP all over the place depending on where the monitors are positioned.

DisplayInfoCollection dic = DisplayInfoCollection.GetDisplays();
        int count = 0;
        int totalPosX = 0;
        int totalPosY = 0;

        DisplayInfo dInfo = null;
                    
        List<DisplayInfo> di = dic.OrderByDescending(d => d.isPrimary).ToList();
        
        var or = SystemInformation.VirtualScreen;
        foreach (DisplayInfo dm in di)
        {
            bool zeroOutX = false;
            bool zeroOutY = false;
            if (dm.isPrimary)
            {
                totalPosX = or.Left > 0 ? or.Left : -or.Left;
                totalPosY = or.Top > 0 ? or.Top : -or.Top; 
                dInfo = dm;
            }
            else
            {                    
                bool left = false;
                bool top = false;
                bool right = false;
                bool bottom = false;
                bool topLeft = false;
                bool topRight = false;
                bool bottomLeft = false;
                bool bottomRight = false;
                int posY = dm.MonitorArea.Top > 0 ? dm.MonitorArea.Top : -dm.MonitorArea.Top;
                if (dm.MonitorArea.Left < 0)
                {
                    left = true;
                }
                else
                    right = dm.MonitorArea.Left > 0;
                if (dm.MonitorArea.Top < 0)
                {
                    top = true;
                }
                else
                    bottom = dm.MonitorArea.Top > 0;
                bool center = (dm.MonitorArea.Left > 0 ?
                    dm.MonitorArea.Left : -dm.MonitorArea.Left) > 0 ||
                    (dm.MonitorArea.Left > 0 ?
                    dm.MonitorArea.Left : -dm.MonitorArea.Left) < dInfo.ScreenWidth;

                topLeft = left && top;
                topRight = right && top;
                bottomLeft = left && bottom;
                bottomRight = right && bottom;
                if (topLeft || topRight || bottomLeft || bottomRight || left || right)
                {
                    if (dm.MonitorArea.Left < 0)
                        zeroOutX = true;
                    else
                        totalPosX += dInfo.ScreenWidth;
                    if (dm.MonitorArea.Top < 0)
                        zeroOutY = true;
                    else
                        totalPosY += dm.MonitorArea.Top;
                }
                dInfo = dm;
            }

            Display display = new Display(dm.DeviceName, dm.ScreenWidth,
               dm.ScreenHeight, zeroOutX ? 0 : totalPosX,
               zeroOutY ? 0 : totalPosY, Controls, count);
            Displays.Add(display);
            count++;
            
        }

I cant find much help on this matter and have tried numerous ways to do this its a c# windows form and I am new-ish to programming my knowledge is limited in this any help will be appreciated thanks in advance.

Scott
  • 11
  • 2
  • Why does this have a C tag? – Joshua Feb 03 '21 at 23:51
  • you are the only one that had replied with a message and even then its has nothing to do with my question..... – Scott Feb 04 '21 at 09:37
  • The coordinates from `EnumDisplaySettingsEx` and `GetMonitorInfo` are [virtual-screen](https://learn.microsoft.com/en-us/windows/win32/gdi/the-virtual-screen) coordinates which may be negative values. Not sure if axWindowsMideaPlayer uses the same coordinate system? Does it work if you set the location of axWindowsMideaPlayer to the default value(0,0)? – Drake Wu Feb 15 '21 at 05:57
  • it works on single monitor perfectly on multi monitor they get messed up, if monitors location is a negative value then then it throws the rest off, setting them to value(0,0) dose not work as the far left of virtual-desktop meaning x could be -1920 or y -1366 – Scott Feb 15 '21 at 10:09

2 Answers2

0

According to the EnumDisplaySettings:

The EnumDisplaySettings function sets values for the following five DEVMODE members:

  • dmBitsPerPel
  • dmPelsWidth
  • dmPelsHeight
  • dmDisplayFlags
  • dmDisplayFrequency

(Excluding dmPosition), You should try to use EnumDisplaySettingsEx, and specify DM_POSITION to get the correct dmPosition value.

Drake Wu
  • 6,927
  • 1
  • 7
  • 30
  • Hi Drake I have changed the code to EnumDisplaySettingsEx but it is still displaying the same positions not sure if I am doing it right? I added the changes to my original post thanks. – Scott Feb 13 '21 at 23:29
0

thanks for all that helped I found a solution to my problem here it is if anyone need to know.

        var or = SystemInformation.VirtualScreen;
        foreach (DisplayInfo dm in dic)
        {                
            int x = or.Left > 0 ? or.Left : -or.Left;
            int y = or.Top > 0 ? or.Top : -or.Top;

            if (dm.isPrimary)
            {
                Rect rect = new Rect();
                rect.Left = x;
                rect.Top = y;
                rect.Right = rect.Left + dm.ScreenWidth;
                rect.Bottom = rect.Top + dm.ScreenHeight;
                dm.MonitorArea = rect;
            }                
            else
            {                 
                Rect rect = new Rect();
                rect.Left = x + dm.MonitorArea.Left;
                rect.Top = y + dm.MonitorArea.Top;
                rect.Right = rect.Left + dm.ScreenWidth;
                rect.Bottom = rect.Top + dm.ScreenHeight;
                dm.MonitorArea = rect;
            }
Scott
  • 11
  • 2