Delphi: обмен данными между приложениями

КОМПЬЮТЕРНЫЕ КУРСЫ "ПОИСК"

[Главная страница] [Delphi] [Контакты]

Проецируемые в память файлы


m2

В секции определения переменных главной формы (перед началом раздела implementation) объявите переменные hMFile и pMFile и константу mFileName:

var
  Form1: TForm1;
  hMFile : THandle;
  pMFile : pointer;
const
  mFileName = 'FileMappingDemo'; //имя объекта отображения

Сохраните приложение под именем FMapping.dpr. Перейдите к головному модулю проекта .dpr и внесите в него изменения так, как предложено в следующем листинге:

program FMapping;

uses
  Forms, Windows, SysUtils,
  Unit1 in 'Unit1.pas' {Form1};

{$R *.res}

begin
  Application.Initialize;
  {Для того чтобы процессы смогли разделить объект файлового отображения, они должны
  передавать одинаковые параметры в методы CreateFileMapping() и MapViewOfFile()}
  hMFile := CreateFileMapping($FFFFFFFF, nil, Page_ReadWrite, 0, 256, mFileName);
  {размер объекта отображения – всего-навсего 256 байт, он доступен для чтения и записи}
  if hmFile > 0 then
  begin
    pMFile := MapViewOfFile(hmFile,File_Map_All_Access,0,0,0);
    Application.MainFormOnTaskbar := True;
    Application.CreateForm(TForm1, Form1);
    Application.MainForm.Caption := Format('Handle = $%x',[Application.Handle]);
    Application.Run;
  end
    else Halt;  //мы не смогли создать объект отображения
end.

Сразу после инициализации приложения мы пытаемся создать объект отображения. Если эта операция завершилась неудачно, прекращаем работу программы, вызвав метод Halt(). Если же дескриптор объекта отображения получен, то проецируем его в виртуальное адресное пространство нашего процесса. Для этого вызываем функцию CreateFileMapping() и получаем указатель на начальную область памяти pMFile. Затем создаем главную форму и запускаем приложение на выполнение.

Опишем событие закрытия главной формы:

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  UnMapViewOfFile(pMFile); //отмена представления файла в адресном пространстве
  CloseHandle(hMFile); //освобождаем дескриптор объекта отображения
end;

Научившись создавать и уничтожать объекты отображения, займемся самым интересным. Разместите на главной форме проекта два элемента управления: группу переключателей TRadioGroup и таймер TTimer. Чтобы заполнить группу переключателей некоторым набором элементов, перепишите событие создания формы:

procedure TForm1.FormCreate(Sender: TObject);
var Ch : byte;
begin
  RadioGroup1.Align := alClient;
  for Ch:=Byte('A') to Byte('Z') do
    RadioGroup1.Items.Add(Char(Ch));
  RadioGroup1.Columns := 3;
end;

Компонент RadioGroup1 заполняется тремя колонками символов латинского алфавита. Опишем щелчок по компоненту:

procedure TForm1.RadioGroup1Click(Sender: TObject);
var
  ind : string;
begin
  ind := IntToStr(RadioGroup1.ItemIndex); //индекс выбранной кнопки
  StrCopy(pMFile,PChar(ind)); //передаем индекс в файл
end;

В момент щелчка по группе переключателей выясняется индекс отмеченного переключателя, и он передается в объект отображения. Для этого применяется метод StrCopy(). Для считывания данных из объекта отображения предназначен таймер:

procedure TForm1.Timer1Timer(Sender: TObject);
var
  ind: string;
begin
  if not (Application.Active) then
  begin
    ind := PChar(pMFile);
    RadioGroup1.ItemIndex := StrToIntDef(ind, 0);
  end;
end;

В момент возникновения события OnTimer() производится считывание данных из объекта отображения. Полученное значение соответствует индексу переключателя, выбранного в другом приложении.

Проект завершен. Запустите несколько экземпляров нашего приложения и проверьте работоспособность кода.

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

Исходный код проекта (Delphi XE)

Используемая литература: Delphi. Профессиональное программирование. Д. Осипов.