Заметки / Подстройка разрешения экрана под программу

C++, Утилита


 Существует множество старых программ под Windows с фиксированным размером окна, созданных под низкое разрешение экрана. Менять перед их запуском разрешение неудобно, так же, как и пользоваться программой, занимающей незначительную часть дисплея. Выходом может стать утилита, подстраивающая экран под приложение и восстанавливающая дефолтное разрешение после завершения работы программы.

Вот основные моменты работы такой утилиты:

// Функция смены разрешения
bool fullScr (int fsWidth, int fsHeight)
{
 DEVMODE dmScreenSettings;
 memset (&dmScreenSettings, 0, sizeof (dmScreenSettings));
 dmScreenSettings.dmSize=sizeof (dmScreenSettings);
 dmScreenSettings.dmPelsWidth=fsWidth;
 dmScreenSettings.dmPelsHeight=fsHeight;
 dmScreenSettings.dmFields=DM_PELSWIDTH | DM_PELSHEIGHT;

 if (ChangeDisplaySettings (&dmScreenSettings, CDS_FULLSCREEN)!= DISP_CHANGE_SUCCESSFUL)
  return false;
 else
  return true;
}

// Проверка - поддерживается ли данное разрешение
bool isScr (int x, int y)
{
 DEVMODE devMode;// Режим устройства
 memset (&devMode, 0, sizeof (devMode));// Очистка для хранения установок
 devMode.dmSize=sizeof (devMode);// Размер структуры Devmode

 for (int i=0; EnumDisplaySettings (0, i, &devMode); i++)
 {
   if (devMode.dmPelsWidth==x && devMode.dmPelsHeight==y)
    return true;
 }

 return false;
}


// ...


 // Обработка входных параметров
 #define mx 256
 char arg1 [mx], arg2 [mx], arg3 [mx], arg4 [mx];
 char mess [256], err [32]={"Ошибка"};
 int i, i2, l=strlen (lpszArgument), x=0, y=0;

 memset (arg1, 0, mx);
 memset (arg2, 0, mx);
 memset (arg3, 0, mx);
 memset (arg4, 0, mx);
 for (i=0; i<l; i++)
 {
  if (lpszArgument [i]==' ')
  {
   for (i2=0; i2<i; i2++)
    arg1 [i2]=lpszArgument [i2];

   for (i2=i+1; i2<l; i2++)
    arg2 [i2-i-1]=lpszArgument [i2];
  }
 }

 l=strlen (arg2);
 for (i=0; i<l; i++)
 {
  if (arg2 [i]=='x')
  {
   for (i2=0; i2<i; i2++)
    arg3 [i2]=arg2 [i2];

   for (i2=i+1; i2<l; i2++)
    arg4 [i2-i-1]=arg2 [i2];

   x=atoi (arg3);
   y=atoi (arg4);
  }
 }

 if (x==0 || y==0)// Если параметры указаны неверно
 {
  char mess_ar [5] [64]={"Нужны два аргумента, разделённые пробелом:",
                         "название программы и разрешение. Например:",
                         "st.exe program.exe 800x600"
                        };
  sprintf (mess, "%s\n%s\n\n%s", mess_ar [0], mess_ar [1], mess_ar [2]);
  MessageBox (NULL, mess, err, MB_OK);
  PostQuitMessage (0);       /* send a WM_QUIT to the message queue */
 }
 else
 {
  // Проверка существования файла
  FILE *file;
  file=fopen (arg1, "rb");
  if (file==NULL)
  {
   sprintf (mess, "Программа \"%s\" не найдена.", arg1);
   MessageBox (NULL, mess, err, MB_OK);
   PostQuitMessage (0);       /* send a WM_QUIT to the message queue */
  }
  else
  {
   fclose (file);

   // Проверка поддержки заданного разрешения экрана
   if (!isScr (x, y))
   {
    sprintf (mess, "Разрешение %dx%d не поддерживается.", x, y);
    MessageBox (NULL, mess, err, MB_OK);
    PostQuitMessage (0);       /* send a WM_QUIT to the message queue */
   }
   else
   {
    // Установка пониженного разрешения
    fullScr (x, y);

    // Выполнение программы через системный вызов:
    // будет создано окно командной оболочки,
    // а выполнение утилиты остановлено до завершения работы программы
    system (arg1);

    // Выход - разрешение будет восстановлено
    PostQuitMessage (0);       /* send a WM_QUIT to the message queue */

Обрабатываемая программа и разрешение передаются в командной строке. Удобнее всего это сделать .bat-файлом:
st.exe program.exe 800x600

Если добавить команду "start", то не будет создано лишнее командное окно:
start st.exe program.exe 1024x768

Файлы "st.exe" и "st.bat" (именно к нему следует обращаться для вызова основной программы) нужно скопировать в директорию программы. Если для "st.bat" создать ярлык (правый клик мышью, "Создать ярлык"), то в его свойствах (снова правый клик, "Свойства") можно выбрать значок ("Сменить значок") из файла ключевой программы, сведя к минимуму отличия от обычного её выполнения.

Кстати, разрешение 640x480 можно указать в свойствах приложения:


Скачать утилиту.

31.07.2017

P.S. Добавил в программу выставление частоты обновления дисплея. Это может быть полезно, если, к примеру, игра использует VSync и потребляет слишком много ресурсов на дефолтной частоте монитора. В таком случае частоту можно понизить. Скачать утилиту.