Zigma
Zigma

Reputation: 529

Move Application GUI to another monitor

Question similar to my problem is asked here previously. But I assume this is unique .

I have my PC monitor and an extended monitor, I got the EDID and some data by this code :

ManagementObjectSearcher searcher =
   new ManagementObjectSearcher("root\\WMI", "SELECT * FROM WmiMonitorID");

foreach (ManagementObject queryObj in searcher.Get())
{
    dynamic snid = queryObj["SerialNumberID"];
    string serialnum = GetStringFromInt(snid);

    Console.WriteLine("SerialNumber:  {0}",serialnum);
    Console.WriteLine("YearOfManufacture: {0}", queryObj["YearOfManufacture"]);
    dynamic code = queryObj["ProductCodeID"];
    string pcid = GetStringFromInt(code);
    code = queryObj["ManufacturerName"];
    string manufactrName = GetStringFromInt(code);

    Console.WriteLine("ProductCodeID: " + pcid);
    Console.WriteLine("Manufacture: " + manufactrName);
}}

So I have Manufacture and ProductCodeID combined, which is something like ABC3401 and DEF4561 (I have two monitor). I need to move my application to DEF4561. I tried Move Form onto specified Screen but the name returns \\DISPLAY1 , \\DISPLAY2 etc. I need the ABC3401 strng to identify the monitor. I dont know how to combine these results.

Upvotes: 0

Views: 1808

Answers (2)

Erdogan Kurtur
Erdogan Kurtur

Reputation: 3685

You must use EnumDisplayDevices to enumerate display devices and monitors attached to them, then you can match them.

Below is a shameless copy of the codes from pinvoke.net

[Flags()]
public enum DisplayDeviceStateFlags : int
{
    /// <summary>The device is part of the desktop.</summary>
    AttachedToDesktop = 0x1,
    MultiDriver = 0x2,
    /// <summary>The device is part of the desktop.</summary>
    PrimaryDevice = 0x4,
    /// <summary>Represents a pseudo device used to mirror application drawing for remoting or other purposes.</summary>
    MirroringDriver = 0x8,
    /// <summary>The device is VGA compatible.</summary>
    VGACompatible = 0x10,
    /// <summary>The device is removable; it cannot be the primary display.</summary>
    Removable = 0x20,
    /// <summary>The device has more display modes than its output devices support.</summary>
    ModesPruned = 0x8000000,
    Remote = 0x4000000,
    Disconnect = 0x2000000
}

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public struct DISPLAY_DEVICE 
{
      [MarshalAs(UnmanagedType.U4)]
      public int cb;
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)]
      public string DeviceName;
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst=128)]
      public string DeviceString;
      [MarshalAs(UnmanagedType.U4)]
      public DisplayDeviceStateFlags StateFlags;
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst=128)]
      public string DeviceID;
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst=128)]
      public string DeviceKey;
}


[DllImport("user32.dll")]
static extern bool EnumDisplayDevices(string lpDevice, uint iDevNum, ref DISPLAY_DEVICE lpDisplayDevice, uint dwFlags);

void Main()
{
    DISPLAY_DEVICE d=new DISPLAY_DEVICE();
    d.cb=Marshal.SizeOf(d);
    try {
        for (uint id=0; EnumDisplayDevices(null, id, ref d, 0); id++) {
            Console.WriteLine(String.Format("{0}, {1}, {2}, {3}, {4}", id, d.DeviceName, d.DeviceString, d.StateFlags, d.DeviceID));
            
            EnumDisplayDevices(d.DeviceName, 0, ref d, 1);
            Console.WriteLine(String.Format("    {0}, {1}, {2}, {3}, {4}", id, d.DeviceName, d.DeviceString, d.StateFlags, d.DeviceID));                          
            d.cb=Marshal.SizeOf(d);
        }
    } catch (Exception ex) {
        Console.WriteLine(String.Format("{0}",ex.ToString()));
    }
}

It gives following output on my computer

0, \\.\DISPLAY1, ATI Radeon HD 5570, 134742017, PCI\VEN_1002&DEV_68D9&SUBSYS_E142174B&REV_00
    0, \\.\DISPLAY1\Monitor0, SyncMaster B2230 (Digital), AttachedToDesktop, MultiDriver, \\?\DISPLAY#SAM0635#5&15bb0574&0&UID256#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}
1, \\.\DISPLAY2, ATI Radeon HD 5570, 134742021, PCI\VEN_1002&DEV_68D9&SUBSYS_E142174B&REV_00
    1, \\.\DISPLAY2\Monitor0, SyncMaster B2230 (Analog), AttachedToDesktop, MultiDriver, \\?\DISPLAY#SAM0635#5&15bb0574&0&UID257#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}
2, \\.\DISPLAYV1, RDPDD Chained DD, 2097160, 
    2, , , 0, 
3, \\.\DISPLAYV2, RDP Encoder Mirror Driver, 2097160, 
    3, , , 0, 
4, \\.\DISPLAYV3, RDP Reflector Display Driver, 2097160, 
    4, , , 0, 

Upvotes: 0

Zigma
Zigma

Reputation: 529

To complete the answer, I am completing this. First, get the Details of monitor by the edokan's answer

    public struct DisplayInfo
    {
        public string DisplayID;
        public string DisplayName;
        public string EDID;
    }
     [DllImport("user32.dll")]
    static extern bool EnumDisplayDevices(string lpDevice, uint iDevNum, ref DISPLAY_DEVICE lpDisplayDevice, uint dwFlags);
     [DllImport("user32.dll")]
      [return: MarshalAs(UnmanagedType.Bool)]
      static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, SetWindowPosFlags uFlags);

    public static List<DisplayInfo> GetConnectedMonitorInfo()
    {
        var MonitorCollection = new List<DisplayInfo>();
        DISPLAY_DEVICE d = new DISPLAY_DEVICE();
        d.cb = Marshal.SizeOf(d);
        try
        {
            for (uint id = 0; EnumDisplayDevices(null, id, ref d, 0); id++)
            {

                EnumDisplayDevices(d.DeviceName, 0, ref d, 1);

                if (string.IsNullOrEmpty(d.DeviceName.ToString()) 
                        && string.IsNullOrEmpty(d.DeviceID.ToString())) continue; 

                var dispInfo = new DisplayInfo();
                dispInfo.DisplayID = id.ToString();
                dispInfo.DisplayName = d.DeviceName.ToString();
                dispInfo.EDID = d.DeviceID.ToString();

                if (d.DeviceID.ToString().Contains("ABC4562"))
                {
                    //Identify Multiple monitor of same series
                    if (string.IsNullOrEmpty(myMonitor.myMonDevName))
                    {
                        myMonitor.myMonDevName = d.DeviceName.ToString();
                    }
                    else
                    {
                        MultipleMonitorFound = true;
                    }

                }
                    MonitorCollection.Add(dispInfo);

                d.cb = Marshal.SizeOf(d);
            }
        }
        catch (Exception ex)
        {
           LogError(ex.ToString());
        }
        return MonitorCollection;
    }

Now we have the list of monitors and its details. Now need to change GUI to that monitor,

We need some params for the method :

        //I am Using WPF
        //For C# only, we can use GetActiveWindow() API.
        WindowInteropHelper winHelp = new WindowInteropHelper(this);
        ScreenObject sc = new ScreenObject();
        //Compare the name with screens
        sc.screen = sc.GetMyMonitor(myMonitor.myMonDevName);

The ScreenObject class is from Move form onto the specified screen answer.

    public static void MoveWindowToMonitor(IntPtr hWnd, int left, int top,double width, double height)
    {


        if (SetWindowPos(hWnd, (IntPtr)SpecialWindowHandles.HWND_TOP, left, top, (int)width, (int)height, SetWindowPosFlags.SWP_SHOWWINDOW))
           LogError( " :  Success");
        else
            LogError(" :  Failed");
    }

P/Invoke can help you there.

A note for C# WPF users :

If you use Windows Presentation Foundation you'll need WindowInteropHelper to get Window handle.

Make sure you referenced PresentationFramework assembly.

Insert this into Using block

using System.Windows.Interop;

Create instance of WindowInteropHelper

WindowInteropHelper winHelp = new WindowInteropHelper(target);

Then use winHelp.Handle insted of GetActiveWindowHandle().

Upvotes: 1

Related Questions