Search code examples
c++apiwinapimonitor

How I change the resolution one monitor only


For example, my computer has two monitors, the primary monitor's resolution is 800*600, the other monitor's resolution is 1600*900.

I would like define the resolution on one monitor only ?

The function 'SetDisplayConfig' change the resolution screen on the two minotors...

https://learn.microsoft.com/fr-fr/windows-hardware/drivers/display/ccd-apis https://learn.microsoft.com/fr-fr/windows/win32/api/winuser/nf-winuser-setdisplayconfig

[DllImport("User32.dll")]
        public static extern int SetDisplayConfig(
            uint numPathArrayElements,
            [In] DisplayConfigPathInfo[] pathArray,
            uint numModeInfoArrayElements,
            [In] DisplayConfigModeInfo[] modeInfoArray,
            SdcFlags flags
        );
private static Boolean SetDisplaySettings(int Id_Monitor, uint Width, uint Height, uint Scaling)
        {
            try
            {
                CCDWrapper.DisplayConfigPathInfo[] pathInfoArray = new CCDWrapper.DisplayConfigPathInfo[0] { };
                CCDWrapper.DisplayConfigModeInfo[] modeInfoArray = new CCDWrapper.DisplayConfigModeInfo[0] { };
                CCDWrapper.MonitorAdditionalInfo[] additionalInfo = new CCDWrapper.MonitorAdditionalInfo[0] { };
                bool Status = GetDisplaySettings(ref pathInfoArray, ref modeInfoArray, ref additionalInfo, true);                       

                CCDWrapper.DisplayConfigPathInfo[] pathInfoArrayCurrent = new CCDWrapper.DisplayConfigPathInfo[0] { };
                CCDWrapper.DisplayConfigModeInfo[] modeInfoArrayCurrent = new CCDWrapper.DisplayConfigModeInfo[0] { };
                CCDWrapper.MonitorAdditionalInfo[] additionalInfoCurrent = new CCDWrapper.MonitorAdditionalInfo[0] { };
                bool StatusCurrent = GetDisplaySettings(ref pathInfoArrayCurrent, ref modeInfoArrayCurrent, ref additionalInfoCurrent, false);

                if (StatusCurrent)
                {
                    for (int iPathInfo = 0; iPathInfo <= pathInfoArray.Length-1; iPathInfo++)
                    //for (int iPathInfo = 0; iPathInfo <= pathInfoArray.Length - 1; iPathInfo++)                      
                    {                        
                        for (int iPathInfoCurrent = 0; iPathInfoCurrent <= pathInfoArrayCurrent.Length - 1; iPathInfoCurrent++)
                        {
                            if ((pathInfoArray[iPathInfo].sourceInfo.id == pathInfoArrayCurrent[iPathInfoCurrent].sourceInfo.id) && (pathInfoArray[iPathInfo].targetInfo.id == pathInfoArrayCurrent[iPathInfoCurrent].targetInfo.id))
                            {
                                pathInfoArray[iPathInfo].sourceInfo.adapterId.LowPart = pathInfoArrayCurrent[iPathInfoCurrent].sourceInfo.adapterId.LowPart;
                                pathInfoArray[iPathInfo].targetInfo.adapterId.LowPart = pathInfoArrayCurrent[iPathInfoCurrent].targetInfo.adapterId.LowPart;
                                pathInfoArray[iPathInfo].targetInfo.scaling = (CCDWrapper.DisplayConfigScaling)Scaling;
                                break;                                                                        
                            }
                        }                                                
                    }

                    for (int iModeInfo = 0; iModeInfo <= modeInfoArray.Length - 1; iModeInfo++)
                    {                       
                        for (int iPathInfo = 0; iPathInfo <= pathInfoArray.Length - 1; iPathInfo++)
                        {
                            if ((modeInfoArray[iModeInfo].id == pathInfoArray[iPathInfo].targetInfo.id) && (modeInfoArray[iModeInfo].infoType == CCDWrapper.DisplayConfigModeInfoType.Target))
                            {
                            for (int iModeInfoSource = 0; iModeInfoSource <= modeInfoArray.Length - 1; iModeInfoSource++)
                            {
                                if ((modeInfoArray[iModeInfoSource].id == pathInfoArray[iPathInfo].sourceInfo.id) && (modeInfoArray[iModeInfoSource].adapterId.LowPart == modeInfoArray[iModeInfo].adapterId.LowPart) && (modeInfoArray[iModeInfoSource].infoType == CCDWrapper.DisplayConfigModeInfoType.Source))
                                {  
                                    modeInfoArray[iModeInfoSource].adapterId.LowPart = pathInfoArray[iPathInfo].sourceInfo.adapterId.LowPart;
                                    modeInfoArray[iModeInfoSource].sourceMode.height = Height;
                                    modeInfoArray[iModeInfoSource].sourceMode.width = Width;
                                    break;                                            
                                }
                            }
                            modeInfoArray[iModeInfo].adapterId.LowPart = pathInfoArray[iPathInfo].targetInfo.adapterId.LowPart;
                            break;
                            }
                        }                                              
                    }

                    uint numPathArrayElements = System.Convert.ToUInt32(pathInfoArray.Length);
                    uint numModeInfoArrayElements = System.Convert.ToUInt32(modeInfoArray.Length);

                    long Result = CCDWrapper.SetDisplayConfig(numPathArrayElements, pathInfoArray, numModeInfoArrayElements, modeInfoArray, CCDWrapper.SdcFlags.Apply | CCDWrapper.SdcFlags.UseSuppliedDisplayConfig | CCDWrapper.SdcFlags.SaveToDatabase | CCDWrapper.SdcFlags.NoOptimization | CCDWrapper.SdcFlags.AllowChanges);
                    if (Result == 0)
                            return true;
                        else
                            return false;                                   
                }
                else
                    return false;                
            }
            catch (Exception ex)
            {
                EventLog.WriteEntry("ResolutionEcran", "Erreur SetDisplaySettings : " + ex.Message, EventLogEntryType.Error);
                return false;
            }
        }
private static Boolean GetDisplaySettings(ref CCDWrapper.DisplayConfigPathInfo[] pathInfoArray, ref CCDWrapper.DisplayConfigModeInfo[] modeInfoArray, ref CCDWrapper.MonitorAdditionalInfo[] additionalInfo, Boolean ActiveOnly, [System.Runtime.InteropServices.Optional] int ID_Monitor)
        {
            uint numPathArrayElements;
            uint numModeInfoArrayElements;

            CCDWrapper.QueryDisplayFlags queryFlags = CCDWrapper.QueryDisplayFlags.AllPaths;
            if (ActiveOnly)
            {
                //queryFlags = CCDWrapper.QueryDisplayFlags.OnlyActivePaths;
                queryFlags = CCDWrapper.QueryDisplayFlags.OnlyActivePaths;
            }

            var status = CCDWrapper.GetDisplayConfigBufferSizes(queryFlags, out numPathArrayElements, out numModeInfoArrayElements);
            if (status == 0)
            {
                pathInfoArray = new CCDWrapper.DisplayConfigPathInfo[numPathArrayElements];
                modeInfoArray = new CCDWrapper.DisplayConfigModeInfo[numModeInfoArrayElements];
                additionalInfo = new CCDWrapper.MonitorAdditionalInfo[numModeInfoArrayElements];                               

                status = CCDWrapper.QueryDisplayConfig(queryFlags, ref numPathArrayElements, pathInfoArray, ref numModeInfoArrayElements, modeInfoArray, IntPtr.Zero);
                if (status == 0)
                {                    
                    for (var iMode = 0; iMode < numModeInfoArrayElements; iMode++)
                    {
                        if (modeInfoArray[iMode].infoType == CCDWrapper.DisplayConfigModeInfoType.Target)
                        {
                            try
                            {
                                additionalInfo[iMode] = CCDWrapper.GetMonitorAdditionalInfo(modeInfoArray[iMode].adapterId, modeInfoArray[iMode].id);
                            }
                            catch (Exception)
                            {
                                additionalInfo[iMode].valid = false;
                            }
                        }
                    }
                    return true;
                }
                else
                {
                    //Erreur : Querying display;
                }
            }
            else
            {
                //Erreur : Taille Buffer;
            }

            return false;
        }

Solution

  • Use ChangeDisplaySettingsEx function to change the settings of the specified display device to the specified graphics mode. The following is an example you can refer to.

    #include <windows.h>
    
    int main()
    {
        for (DWORD devNum = 0; ; devNum++)
        {
            DISPLAY_DEVICE dev = {0};
            dev.cb = sizeof(DISPLAY_DEVICE);
    
            if (!EnumDisplayDevices(NULL, devNum, &dev, EDD_GET_DEVICE_INTERFACE_NAME))
                break;
    
            wprintf(L"Display name: %s \n", dev.DeviceName);
    
            DEVMODE dMode = { 0 };
            dMode.dmSize = sizeof(dMode);
    
            if (!EnumDisplaySettings(dev.DeviceName, ENUM_CURRENT_SETTINGS, &dMode))
            {
                wprintf(L"EnumDisplaySettings error: %d \n", GetLastError());
                continue;
            }
    
            wprintf(L"Display old settings: \n");
            wprintf(L"dmBitsPerPel: %d \n", dMode.dmBitsPerPel);
            wprintf(L"dmPelsWidth: %d \n", dMode.dmPelsWidth);
            wprintf(L"dmPelsHeight: %d \n", dMode.dmPelsHeight);
            wprintf(L"dmDisplayFlags: %x \n", dMode.dmDisplayFlags);
            wprintf(L"dmDisplayFrequency: %d \n", dMode.dmDisplayFrequency);
    
            dMode.dmPelsWidth = 800;
            dMode.dmPelsHeight = 600;
            ChangeDisplaySettingsEx(dev.DeviceName, &dMode, NULL, 0, NULL);
    
            DEVMODE dModeNew = { 0 };
            dModeNew.dmSize = sizeof(DEVMODE);
            if (!EnumDisplaySettings(dev.DeviceName, ENUM_CURRENT_SETTINGS, &dModeNew))
            {
                wprintf(L"EnumDisplaySettings error: %d \n", GetLastError());
                continue;
            }
    
            wprintf(L"Display new settings: \n");
            wprintf(L"dmBitsPerPel: %d \n", dModeNew.dmBitsPerPel);
            wprintf(L"dmPelsWidth: %d \n", dModeNew.dmPelsWidth);
            wprintf(L"dmPelsHeight: %d \n", dModeNew.dmPelsHeight);
            wprintf(L"dmDisplayFlags: %x \n", dModeNew.dmDisplayFlags);
            wprintf(L"dmDisplayFrequency: %d \n", dModeNew.dmDisplayFrequency);
    
        }
    
        getchar();
    }
    

    I set dwflags to 0 let the graphics mode for the current screen change dynamically. Refer to dwflags parameter part of ChangeDisplaySettingsEx's document for deciding how you would like the graphics mode should be changed.