Нарушение прав доступа между интерфейсом MDIChildren: ShowModal TButton.OnНажмите MDIChild1, чтобы открыть форму MDIChild2. - PullRequest
0 голосов
/ 26 января 2020

У меня есть простой пример минимальной воспроизводимости (MRE) для взаимодействия детей MDI с использованием примера ShowModal. Но на самом деле у меня так много процедур, которые должны взаимодействовать между дочерними формами.

Родительская единица

unit Parent_u;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.Menus;

type
  TParentForm = class(TForm)
    mm1: TMainMenu;
    miOpenChild1: TMenuItem;
    miOpenChild2: TMenuItem;
    procedure miOpenChild1Click(Sender: TObject);
    procedure miOpenChild2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  ParentForm: TParentForm;

implementation

uses
  Child1_u, Child2_u;

{$R *.dfm}

procedure TParentForm.miOpenChild1Click(Sender: TObject);
var
  vChildForm1 : TChildForm1;
begin
  vChildForm1 := TChildForm1.Create(Self);
  miOpenChild1.Enabled := False;

end;

procedure TParentForm.miOpenChild2Click(Sender: TObject);
var
  vChildForm2 : TChildForm2;
begin
  vChildForm2 := TChildForm2.Create(Self);
  miOpenChild2.Enabled := False;
end;

end.

Дочерняя единица

unit Child1_u;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TChildForm1 = class(TForm)
    btnOpenChild2: TButton;
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure btnOpenChild2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  ChildForm1: TChildForm1;

implementation

uses
  Parent_u, Child2_u;

{$R *.dfm}

procedure TChildForm1.btnOpenChild2Click(Sender: TObject);
begin
  ChildForm2.ShowModal; // ERROR HERE: ACCESS VIOLATION
end;

procedure TChildForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Parent_u.ParentForm.miOpenChild1.Enabled := True;
  Action := caFree;
end;

end.

Дочерняя единица

unit Child2_u;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs;

type
  TChildForm2 = class(TForm)
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  ChildForm2: TChildForm2;

implementation

uses
  Parent_u, Child1_u;

{$R *.dfm}

procedure TChildForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Parent_u.ParentForm.miOpenChild2.Enabled := True;
  Action := caFree;
end;

end.

У меня всегда возникают проблемы со связью между дочерними формами MDI. То, что я показал здесь, это простая ошибка взаимодействия между дочерними формами, созданными для этой цели.

Есть ли другой подход для взаимодействия между дочерними формами MDI?

1 Ответ

0 голосов
/ 27 января 2020

По сути, я смотрю на доступ к другой форме из типа формы fsMDIChild через TButton. Но я понял, что доступ к форме - это еще один fsMDIChild, - это будет более трудным и очень много соображений.

Я нашел решение, сохранив форму для доступа как тип формы fsNormal вместо fsMDIChild. Это практически служит моим намерениям - ограничить доступ к другим открытым формам, таким как parent и child1, пока не закроется обычная форма.

Вот обновленный код, который работает для меня:

Родительская форма ChildForm.

unit Parent_u;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.Menus;

type
  TParentForm = class(TForm)
    mm1: TMainMenu;
    miOpenChild1: TMenuItem;
    procedure miOpenChild1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  ParentForm: TParentForm;

implementation

uses
  Child1_u;

{$R *.dfm}

procedure TParentForm.miOpenChild1Click(Sender: TObject);
var
  vChildForm1 : TChildForm1;
begin
  vChildForm1 := TChildForm1.Create(Self);
  miOpenChild1.Enabled := False;

end;

end.

Ниже ChildForm, который должен получить доступ к NormalForm через TButton.

unit Child1_u;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TChildForm1 = class(TForm)
    btnOpenForm11: TButton;
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure btnOpenForm11Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  ChildForm1: TChildForm1;

implementation

uses
  Parent_u, NormalForm_u;

{$R *.dfm}

procedure TChildForm1.btnOpenForm11Click(Sender: TObject);
begin
  NormalForm.ShowModal;
end;

procedure TChildForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Parent_u.ParentForm.miOpenChild1.Enabled := True;
  Action := caFree;
end;

end.

Нормальная форма, к которой здесь следует обращаться.

unit NormalForm_u;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs;

type
  TNormalForm = class(TForm)
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  NormalForm: TNormalForm;

implementation

{$R *.dfm}

end.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...