Установка текущего монитора в Windows XP/7

Форум для изучающих FPC и их учителей.

Модератор: Модераторы

Установка текущего монитора в Windows XP/7

Сообщение PapaNT » 06.06.2012 17:03:40

Уважаемые коллеги, доброго времени суток!

Суть задачи в следующем:
1. Имеется комп с парой мониторов.
2. Нужно заустить IE в режиме киоска на две траницы и так, чтобы каждое отображалось в своем мониторе да еще и в режиме киоска.

С киоском проблем нет. Но экспериментально было установлено, что новое окно создается непосредственно на основном мониторе. Т.о. мне нудно прикрутить юзверю "кнопку" на смену текущего монитора с последующим запуском программы...

Есть ли возможность программно сменить основной монитор?

Возможно мой вопрос будет тривиален, но для меня, из-за отсувия большого практического опыта, его пока сложно решить...

Заранее брагодарен!
PapaNT
постоялец
 
Сообщения: 167
Зарегистрирован: 11.09.2009 12:06:46
Откуда: Москва

Re: Установка текущего монитора в Windows XP/7

Сообщение Little_Roo » 06.06.2012 17:49:20

PapaNT писал(а):Нужно заустить IE в режиме киоска

Шо це за зверь?
Аватара пользователя
Little_Roo
энтузиаст
 
Сообщения: 639
Зарегистрирован: 27.02.2009 19:56:36
Откуда: Санкт-Петербург

Re: Установка текущего монитора в Windows XP/7

Сообщение PapaNT » 06.06.2012 17:59:39

Little_Roo писал(а):
PapaNT писал(а):Нужно заустить IE в режиме киоска

Шо це за зверь?
Internet Explorer
PapaNT
постоялец
 
Сообщения: 167
Зарегистрирован: 11.09.2009 12:06:46
Откуда: Москва

Re: Установка текущего монитора в Windows XP/7

Сообщение Little_Roo » 06.06.2012 18:22:33

PapaNT писал(а):в режиме киоска

Я про ЭТО
Аватара пользователя
Little_Roo
энтузиаст
 
Сообщения: 639
Зарегистрирован: 27.02.2009 19:56:36
Откуда: Санкт-Петербург

Re: Установка текущего монитора в Windows XP/7

Сообщение alexey38 » 06.06.2012 20:59:41

Я нечто похожее делал, не для IE. И что такое киоск я тоже не заню (не понимаю термин).

Код: Выделить всё
     ShowWindow(WinHandle,SW_SHOWNORMAL);
     MoveWindow(WinHandle,0,0,Max(Screen.Width,Screen.DesktopWidth),Max(Screen.Height,Screen.DesktopHeight),true);


А что бы получит дискрипторы окон:
Код: Выделить всё
EnumWindows(@EnumWindowsProc,0);
EnumChildWindows(WinHandle, @EnumSubWindowsProc, 0);
alexey38
долгожитель
 
Сообщения: 1627
Зарегистрирован: 27.04.2011 19:42:31

Re: Установка текущего монитора в Windows XP/7

Сообщение PapaNT » 07.06.2012 12:02:44

Little_Roo писал(а):
PapaNT писал(а):в режиме киоска

Я про ЭТО
Режим киоска - это когда IE раскрывается на весь экран и не позволяет использовать средства перемещения окна (у окна нет органов управления свернуть, развернуть, закрыть, переместить и т.д...)
PapaNT
постоялец
 
Сообщения: 167
Зарегистрирован: 11.09.2009 12:06:46
Откуда: Москва

Re: Установка текущего монитора в Windows XP/7

Сообщение alexey38 » 07.06.2012 19:23:59

PapaNT писал(а):
Little_Roo писал(а):
PapaNT писал(а):в режиме киоска

Я про ЭТО
Режим киоска - это когда IE раскрывается на весь экран и не позволяет использовать средства перемещения окна (у окна нет органов управления свернуть, развернуть, закрыть, переместить и т.д...)


То есть речь идет про стандартный "полноэкранный режим", который во всех браузерах вызывается кнопкой F11?

Методы управления как мне кажется те же, что я и предлагал. Возможно нужно запустить в обычном режиме, а потом у ИЕ отправить команду F11.
alexey38
долгожитель
 
Сообщения: 1627
Зарегистрирован: 27.04.2011 19:42:31

Re: Установка текущего монитора в Windows XP/7

Сообщение PapaNT » 08.06.2012 09:06:45

Суть режима киоска в том, что органов управления не показывается - как на платежных терминалах.
Можете сами попробовать запустить:
iexplore -k http://server_name

alexey38 Если не тудно, то можно ли более развернутый пример, а то у меня не собирается из-за ошибок...
PapaNT
постоялец
 
Сообщения: 167
Зарегистрирован: 11.09.2009 12:06:46
Откуда: Москва

Re: Установка текущего монитора в Windows XP/7

Сообщение alexey38 » 09.06.2012 10:39:01

PapaNT писал(а):alexey38 Если не тудно, то можно ли более развернутый пример, а то у меня не собирается из-за ошибок...


У меня это встроено в большой проект. Все раскидано по модулям и компонентам.
Я просто перечислил основные функции, которые у меня использовались для управления окнами. Описание можете найти в инете.
У полноэкранных режимов возможно есть особенности, но суть от этого, как мне кажется, не меняется.
Можно еще покопать в сторону CreateProcess, там при запуске можно указать много параметров. Я это сам использую, но не для указания места на экране, хотя уверен, что можно задать координаты окна или номер экрана.
alexey38
долгожитель
 
Сообщения: 1627
Зарегистрирован: 27.04.2011 19:42:31

Re: Установка текущего монитора в Windows XP/7

Сообщение Timid » 11.06.2012 11:26:41

Импортируйте WebBrowser в IDE (как ActiveX), бросьте компонент на форму как alClient, уберите у формы все бордеры и строку заголовка. Затем разверните форму на экран (нужный) в StayOnTop. Можно вообще сделать развертывание на весь экран путем явного задания координат Monitor[1].Left, Monitor[1].Top, Monitor[1].Width, Monitor[1].Height и следить за потерей фокуса (например, открыть модально).
Так я делаю в приложении для тестирования студентов - все работает, если не дать им окно открытия файла, к примеру. Ваша форма с браузером (без контролов!) будет висеть всегда на развернутой на весь экран поверх других приложений.
Timid
постоялец
 
Сообщения: 290
Зарегистрирован: 21.11.2007 21:33:15

Re: Установка текущего монитора в Windows XP/7

Сообщение PapaNT » 15.06.2012 15:27:18

Timid писал(а):Импортируйте WebBrowser в IDE (как ActiveX), бросьте компонент на форму как alClient, уберите у формы все бордеры и строку заголовка. Затем разверните форму на экран (нужный) в StayOnTop. Можно вообще сделать развертывание на весь экран путем явного задания координат Monitor[1].Left, Monitor[1].Top, Monitor[1].Width, Monitor[1].Height и следить за потерей фокуса (например, открыть модально).
Так я делаю в приложении для тестирования студентов - все работает, если не дать им окно открытия файла, к примеру. Ваша форма с браузером (без контролов!) будет висеть всегда на развернутой на весь экран поверх других приложений.
Увы, это для промышленной системы защищенной СЗИ от НСД с функционально-замкнутой средой (только разрешенные приложения). К сожалению, описанные манипуляции с ActiveX недопустимы :(

Сейчас копаю в сторону функций USER32.dll...
PapaNT
постоялец
 
Сообщения: 167
Зарегистрирован: 11.09.2009 12:06:46
Откуда: Москва

Re: Установка текущего монитора в Windows XP/7

Сообщение PapaNT » 10.07.2012 09:59:45

С устновкой текущего монитора разобрался. Переключает как доктор прописал:)
Переключалка собрана на базе примера: http://stackoverflow.com/questions/956870/using-changedisplaysettingsex-in-delphi-to-set-primary-monitor

За мой пример прошу не бросаться тухлыми яйцами - собрал для тестирования концепции и код пока не вылизывал. Желающие могут это сделать самостояятельно.

Код: Выделить всё
Program SetActiveMonitor;
uses Windows,jwawinuser,JwaWinGDI;

Const

  MaxMonCount = 2; //Максимальное число поддерживаемых мониторов

Var
  MonCount : Byte; //Число обнаруженных мониторов
  i        : byte;

  // Display Devices
  DevMode1 ,             // Текущие видеорежимы
  DevMode2 : TDeviceMode;//LPDevModeA; //}_DeviceModeA;

  MonNameA : array [1..MaxMonCount] of PChar; // Список имен мониторов

  MonP     : byte; // Номер активного монитора

function GetVideoCard(cc : byte) : String; // Выдает имя устройства по номеру
Var
  lpDisplayDevice : TDisplaydevice;
  dwFlags : DWORD;
begin
  lpDisplaydevice.cb := Sizeof(lpDisplayDevice);
  dwFlags := 0;
  if EnumDisplayDevices(nil,cc,lpDisplayDevice, dwFlags) then
    GetVideoCard := lpDisplayDevice.DeviceName;
end;

Procedure ChangeDisplaySettingsExResult(res : DWord);
begin
  case res of
    Disp_Change_Successful : Writeln('Изменение видеорежима произошло успешно');
    Disp_Change_BadDualView : Writeln('Изменение видеорежима было неудачным из-за включенного режима DualView');
    Disp_Change_BadFlags : Writeln('Изменение видеорежима было неудачным из-за неверных флагов');
    Disp_Change_BadMode : Writeln('Изменение видеорежима было неудачным из-за неподдерживаемого видеорежима');
    Disp_Change_BadParam : Writeln('Изменение видеорежима было неудачным из-за неудачных параметров. Это может быть обусловлено ошибочным флагом или набором флагов');
    Disp_Change_Failed : Writeln('Изменение видеорежима было неудачным из-за ошибки интерпретации нового видеорежима драйвером видеокарты');
    Disp_Change_NotUpdated : Writeln('Изменение видеорежима было неудачным из-за невозможности произвести запись в системный реестр');
    Disp_Change_Restart : Writeln('Изменение видеорежима будет произведено после перезапуска компьютера')
  else
    Writeln('Изменение видеорежима было неудачным из-за неизвестной причины')
  end;
end;

Procedure Info;
begin
//  Writeln('DevMode1.dmDeviceName = ',PChar(DevMode1.dmDeviceName));
  Writeln('DevMode1.dmSpecVersion = ',DevMode1.dmSpecVersion);
  Writeln('DevMode1.dmDriverVersion = ',DevMode1.dmDriverVersion);
  Writeln('DevMode1.dmSize = ',DevMode1.dmSize);
  Writeln('DevMode1.dmDriverExtra = ',DevMode1.dmDriverExtra);
  Writeln('DevMode1.dmFields = ',DevMode1.dmFields);
  Writeln('DevMode1.dmOrientation = ',DevMode1.dmOrientation);
  Writeln('DevMode1.dmPaperSize = ',DevMode1.dmPaperSize);
  Writeln('DevMode1.dmPaperLength = ',DevMode1.dmPaperLength);
  Writeln('DevMode1.dmPaperWidth = ',DevMode1.dmPaperWidth);
  Writeln('DevMode1.dmScale = ',DevMode1.dmScale);
  Writeln('DevMode1.dmCopies = ',DevMode1.dmCopies);
  Writeln('DevMode1.dmDefaultSource = ',DevMode1.dmDefaultSource);
  Writeln('DevMode1.dmPrintQuality = ',DevMode1.dmPrintQuality);
  Writeln('DevMode1.dmColor = ',DevMode1.dmColor);
  Writeln('DevMode1.dmDuplex = ',DevMode1.dmDuplex);
  Writeln('DevMode1.dmYResolution = ',DevMode1.dmYResolution);
  Writeln('DevMode1.dmTTOption = ',DevMode1.dmTTOption);
  Writeln('DevMode1.dmCollate = ',DevMode1.dmCollate);
//  Writeln('DevMode1.dmFormName = ',DevMode1.dmFormName);
  Writeln('DevMode1.dmLogPixels = ',DevMode1.dmLogPixels);
  Writeln('DevMode1.dmBitsPerPel = ',DevMode1.dmBitsPerPel);
  Writeln('DevMode1.dmPelsWidth = ',DevMode1.dmPelsWidth);
  Writeln('DevMode1.dmPelsHeight = ',DevMode1.dmPelsHeight);
  Writeln('DevMode1.dmDisplayFlags = ',DevMode1.dmDisplayFlags);
  Writeln('DevMode1.dmDisplayFrequency = ',DevMode1.dmDisplayFrequency);
  Writeln('DevMode1.dmICMMethod = ',DevMode1.dmICMMethod);
  Writeln('DevMode1.dmICMINTENT = ',DevMode1.dmICMINTENT);
  Writeln('DevMode1.dmMediaType = ',DevMode1.dmMediaType);
  Writeln('DevMode1.dmDitherType = ',DevMode1.dmDitherType);
  Writeln('DevMode1.dmICCManufacturer = ',DevMode1.dmICCManufacturer);
  Writeln('DevMode1.dmICCModel = ',DevMode1.dmICCModel);
  Writeln('DevMode1.dmPosition.x = ',DevMode1.dmPosition.x);
  Writeln('DevMode1.dmPosition.y = ',DevMode1.dmPosition.y);
  Writeln('DevMode1.dmDisplayOrientation = ',DevMode1.dmDisplayOrientation);
  Writeln('DevMode1.dmDisplayFixedOutput = ',DevMode1.dmDisplayFixedOutput);

  Writeln;

  if MonCount <> 1 Then
    begin
    //  Writeln('DevMode2.dmDeviceName = ',PChar(DevMode2.dmDeviceName));
      Writeln('DevMode2.dmSpecVersion = ',DevMode2.dmSpecVersion);
      Writeln('DevMode2.dmDriverVersion = ',DevMode2.dmDriverVersion);
      Writeln('DevMode2.dmSize = ',DevMode2.dmSize);
      Writeln('DevMode2.dmDriverExtra = ',DevMode2.dmDriverExtra);
      Writeln('DevMode2.dmFields = ',DevMode2.dmFields);
      Writeln('DevMode2.dmOrientation = ',DevMode2.dmOrientation);
      Writeln('DevMode2.dmPaperSize = ',DevMode2.dmPaperSize);
      Writeln('DevMode2.dmPaperLength = ',DevMode2.dmPaperLength);
      Writeln('DevMode2.dmPaperWidth = ',DevMode2.dmPaperWidth);
      Writeln('DevMode2.dmScale = ',DevMode2.dmScale);
      Writeln('DevMode2.dmCopies = ',DevMode2.dmCopies);
      Writeln('DevMode2.dmDefaultSource = ',DevMode2.dmDefaultSource);
      Writeln('DevMode2.dmPrintQuality = ',DevMode2.dmPrintQuality);
      Writeln('DevMode2.dmColor = ',DevMode2.dmColor);
      Writeln('DevMode2.dmDuplex = ',DevMode2.dmDuplex);
      Writeln('DevMode2.dmYResolution = ',DevMode2.dmYResolution);
      Writeln('DevMode2.dmTTOption = ',DevMode2.dmTTOption);
      Writeln('DevMode2.dmCollate = ',DevMode2.dmCollate);
    //  Writeln('DevMode2.dmFormName = ',DevMode2.dmFormName);
      Writeln('DevMode2.dmLogPixels = ',DevMode2.dmLogPixels);
      Writeln('DevMode2.dmBitsPerPel = ',DevMode2.dmBitsPerPel);
      Writeln('DevMode2.dmPelsWidth = ',DevMode2.dmPelsWidth);
      Writeln('DevMode2.dmPelsHeight = ',DevMode2.dmPelsHeight);
      Writeln('DevMode2.dmDisplayFlags = ',DevMode2.dmDisplayFlags);
      Writeln('DevMode2.dmDisplayFrequency = ',DevMode2.dmDisplayFrequency);
      Writeln('DevMode2.dmICMMethod = ',DevMode2.dmICMMethod);
      Writeln('DevMode2.dmICMINTENT = ',DevMode2.dmICMINTENT);
      Writeln('DevMode2.dmMediaType = ',DevMode2.dmMediaType);
      Writeln('DevMode2.dmDitherType = ',DevMode2.dmDitherType);
      Writeln('DevMode2.dmICCManufacturer = ',DevMode2.dmICCManufacturer);
      Writeln('DevMode2.dmICCModel = ',DevMode2.dmICCModel);
      Writeln('DevMode2.dmPosition.x = ',DevMode2.dmPosition.x);
      Writeln('DevMode2.dmPosition.y = ',DevMode2.dmPosition.y);
      Writeln('DevMode2.dmDisplayOrientation = ',DevMode2.dmDisplayOrientation);
      Writeln('DevMode2.dmDisplayFixedOutput = ',DevMode2.dmDisplayFixedOutput);
    end;
end;

Procedure Usage;
begin
  WriteLN('Утилита командной строки для управления монитором.');
  WriteLN('(c) Геннадий Ольховой 2012 г.');
  WriteLN('bf72 at yandex.ru');
  Writeln;
  WriteLN('Использование:');
  Writeln;
  WriteLN('SetActiveMonitor.exe');
  WriteLN('Вызов без параметров командной строки производит смену текущего активного монитора в системах с двумя мониторами.');
  WriteLN;
  WriteLN('SetActiveMonitor.exe /?');
  WriteLN('Выводит на экран эту справку.');
  WriteLN;
  WriteLN('SetActiveMonitor.exe /i или SetActiveMonitor.exe /I');
  WriteLN('Выводит общую информацио о мониторах.');
end;

BEGIN
// Инициализация...
  MonCount := GetSystemMetrics(SM_CMONITORS); // Получили число мониторов
  // Получаем имена мониторов
  MonNameA[1] := PChar(GetVideoCard(0));
  Windows.EnumDisplaySettings(MonNameA[1],0,DevMode1);
  if MonCount <> 1 Then
    begin
      MonNameA[2] := PChar(GetVideoCard(1));
      Windows.EnumDisplaySettings(MonNameA[2],0,DevMode2);
    end;
  // get current display settings
  Windows.EnumDisplaySettings(PChar(MonNameA[1]), ENUM_REGISTRY_SETTINGS, DevMode1);
  if MonCount <> 1 Then
      Windows.EnumDisplaySettings(PChar(MonNameA[2]), ENUM_REGISTRY_SETTINGS, DevMode2);

// Обработка параметров команденой строки...
  if ParamCount <> 0 Then
    begin
      if ParamStr(1) = '/?' Then
        begin
          Usage;
          exit
        end;
      if (ParamStr(1) = '/i') or (ParamStr(1) = '/I') Then
        begin
          if ParamCount > 1 Then
            Usage
                               Else
            Info;
          exit
        end;
      Usage; // получили неизвестный параметр командной строки.
      exit
    end;


//  Пара строк отладки (выводит на экран список мониторов)
  for i := 0 to MonCount-1 do
    Writeln(GetVideoCard(i));

  if MonCount = 0 Then
    begin
      WriteLN('В системе установлен один монитор');
      exit // Ничего делать не надо
    end;

// Определяем какой монитор основной
  if DevMode1.dmPosition.x <> 0 then MonP := 2  // Из-за того, что список мониторов формируется без сортировки по признаку основной/вторичный
                                else MonP := 1; // определяем признак активности через (_!_) по координатам позиции смещения... $)
  // А теперь меняем мониторы местами...
  if MonP = 1 Then
    begin // "Активным" был первый монитор
      // move old primary display to new position
      DevMode1.dmFields := DM_POSITION;

      WriteLN('Монитор 1 (основной):');
      WriteLN('dmPosition.x изменяем с ', DevMode1.dmPosition.x, ' на ',DevMode2.dmPelsWidth);
      WriteLN('dmPosition.y изменяем с ', DevMode1.dmPosition.y, ' на 0');
      DevMode1.dmPosition.x := DevMode2.dmPelsWidth;
      DevMode1.dmPosition.y := 0;

      ChangeDisplaySettingsExResult(
        Windows.ChangeDisplaySettingsEx(PChar(MonNameA[1]), DevMode1, 0,
          CDS_UPDATEREGISTRY or CDS_NORESET, nil));
      WriteLN;

      // move old secondary display to (0, 0) and make the primary display
      WriteLN('Монитор 2 (второй):');
      WriteLN('dmPosition.x изменяем с ', DevMode2.dmPosition.x, ' на 0');
      WriteLN('dmPosition.y изменяем с ', DevMode2.dmPosition.y, ' на 0');

      DevMode2.dmFields := DM_POSITION;
      DevMode2.dmPosition.x := 0;
      DevMode2.dmPosition.y := 0;

      ChangeDisplaySettingsExResult(
        windows.ChangeDisplaySettingsEx(PChar(MonNameA[2]), DevMode2, 0,
          CDS_SET_PRIMARY or CDS_UPDATEREGISTRY or CDS_NORESET {or DM_DISPLAYFLAGS}, nil));
      WriteLN;
    end
              Else
    begin // "Активным" был второй монитор
      // move old primary display to new position
      DevMode2.dmFields := DM_POSITION;
      WriteLN('Монитор 2 (сновной):');
      WriteLN('dmPosition.x изменяем с ', DevMode2.dmPosition.x, ' на ',DevMode1.dmPelsWidth);
      WriteLN('dmPosition.y изменяем с ', DevMode2.dmPosition.y, ' на 0');

      DevMode2.dmPosition.x := {1601;//}DevMode1.dmPelsWidth;
      DevMode2.dmPosition.y := 0;

      ChangeDisplaySettingsExResult(
        Windows.ChangeDisplaySettingsEx(PChar(MonNameA[2]), DevMode2, 0,
          CDS_UPDATEREGISTRY or CDS_NORESET, nil));
      WriteLN;
      // move old secondary display to (0, 0) and make the primary display
      WriteLN('Монитор 1 (второй):');
      WriteLN('dmPosition.x изменяем с ', DevMode1.dmPosition.x, ' на ',0);
      WriteLN('dmPosition.y изменяем с ', DevMode1.dmPosition.y, ' на 0');

      DevMode1.dmFields := DM_POSITION;
      DevMode1.dmPosition.x := 0;
      DevMode1.dmPosition.y := 0;

      ChangeDisplaySettingsExResult(
        windows.ChangeDisplaySettingsEx(PChar(MonNameA[1]), DevMode1, 0,
          CDS_SET_PRIMARY or CDS_UPDATEREGISTRY or CDS_NORESET {or DM_DISPLAYFLAGS}, nil));
      WriteLN;
    end;

  WriteLN('Фиксируем установленную конфигурацию.');
  ChangeDisplaySettingsExResult(
    windows.ChangeDisplaySettingsEx(nil, PDeviceMode(0)^, 0, 0, nil));
END.


Но проблема в том, что хоть и переключает, но запускаемое после переключения окно нового запускаемого приложения не всегда появляется на новом активном мониторе.

Пробовал через

Код: Выделить всё
Var
P1 : TProcess;
Begin
  P1 := Tprocess.Create(nil);
  P1.CommandLine := 'Some.exe';

  P1.Desktop := '2';
\\или
\\P1.Desktop := '\\.\DISPLAY2';
  P1.Execute;
....
End.

Но не работет...
Пробовал Задать позицию окна, но не получается.
Может ли кто-либо помочь разобраться?
PapaNT
постоялец
 
Сообщения: 167
Зарегистрирован: 11.09.2009 12:06:46
Откуда: Москва

Re: Установка текущего монитора в Windows XP/7

Сообщение PapaNT » 11.07.2012 12:11:30

Попробовал порыть в сторону:

Код: Выделить всё
Var
P1 : TProcess;
Begin
  P1 := Tprocess.Create(nil);
  P1.CommandLine := 'c:\windows\notepad.exe';
  P1.Options := P1.Options + [suoWaitOnExit];

  writeln(P1.WindowHeight);
  writeln(P1.WindowLeft);
  writeln(P1.WindowWidth);
  writeln(P1.WindowTop);
End.


так оно выдает для запущенного нотпада нули :shock:
куда рыть?
PapaNT
постоялец
 
Сообщения: 167
Зарегистрирован: 11.09.2009 12:06:46
Откуда: Москва

Re: Установка текущего монитора в Windows XP/7

Сообщение PapaNT » 13.07.2012 15:44:43

Решено.

Как получить число и размеры мониторов я уже публиковал.

Перемещение окна дочернего приложения решил через createprocess

Код: Выделить всё
function myFunc(wnd:HWND; lParam: LPARAM): BOOL; stdcall;
begin
  MoveWindow(wnd, 20, 20, 400, 400, True); // Ну, забрось окно куда нужно
  result := False;
end;

...
  // здесь создаешь процесс

  WaitForInputIdle(ProcInfo.hProcess, INFINITE); // Ждем создания окна
  EnumThreadWindows(ProcInfo.dwThreadId, @myFunc, 0);
на основе http://forum.pascalnet.ru/lofiversion/index.php/t26066.html
PapaNT
постоялец
 
Сообщения: 167
Зарегистрирован: 11.09.2009 12:06:46
Откуда: Москва


Вернуться в Обучение Free Pascal

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 17

Рейтинг@Mail.ru