:: MVP ::
|
|
:: RSS ::
|
|
|
Результат, к которому приводит попытка скрыть MDIChild окно штатными средствами Delphi,
всегда заканчивается одинаково – а именно сообщением “Cannot hide an MDI Child Form”.
Мне это кажется странным, ведь в желании спрятать MDIChild окно нет ничего криминального.
Найти причину такого поведения оказалось несложно – она кроется в методе VisibleChanging
класса TCustomForm, который объявлен следующим образом:
TCustomForm = class(...)
{...}
protected
procedure VisibleChanging; override;
{...}
end;
implementation
procedure TCustomForm.VisibleChanging;
begin
if (FormStyle = fsMDIChild) and Visible and (Parent = nil) then
raise EInvalidOperation.Create(SMDIChildNotVisible);
end;
|
Первое, что бросается в глаза, метод объявлен с директивой override. Но что же он перекрывает?
А перекрывает он пустой динамический метод класса TControl, который вызывается из метода
SetVisible этого же класса:
TControl = class(...)
private
procedure SetVisible(Value: Boolean);
{...}
protected
procedure VisibleChanging; dynamic;
{...}
public
property Visible: Boolean read FVisible write SetVisible stored IsVisibleStored default True;
{...}
end;
implementation
procedure TControl.VisibleChanging;
begin
end;
procedure TControl.SetVisible(Value: Boolean);
begin
if FVisible <> Value then
begin
VisibleChanging;
FVisible := Value;
Perform(CM_VISIBLECHANGED, Ord(Value), 0);
RequestAlign;
end;
end;
|
Все это наводит на пару мыслей. Метод динамический – значит мы можем его перекрыть.
А так как этот метод ничего, кроме генерации исключения, не делает, перекрывающий
метод нужно просто оставить пустым.
//
// MDIChild
//
type
TForm2 = class(TForm)
protected
procedure VisibleChanging; override;
end;
implementation
procedure TForm2.VisibleChanging;
begin
end;
//
// MDIForm
//
uses
{...,} Unit2;
procedure TForm1.Button1Click(Sender: TObject);
begin
Form2.Hide;
end;
|
Другая мысль – нужно скрыть форму не используя свойства Visible и метода Hide. В этом нам поможет
API функция ShowWindow. При этом нам не нужно вносить в код MDIChild формы никаких изменений.
//
// MDIForm
//
uses
{...,} Unit2;
procedure TForm1.Button1Click(Sender: TObject);
begin
ShowWindow( Form2.Handle, SW_HIDE );
end;
|
А теперь давайте вернемся к коду метода VisibleChanging, и внимательно посмотрим в каком случае
генерируется исключение. Для генерации исключения должно выполняться 3 условия.
1. У скрываемой формы свойство FormStyle должно иметь значение fsMDIChild. Что ж, тут ничего
не поделаешь, ведь именно такую форму нам и нужно скрыть.
2. Она должна быть видимой. И тут все логично, ведь вряд ли кому то придет в голову скрывать
форму, которая и так не видна.
3. У формы не должно быть “родителя”. Вот на этом и можно сыграть, чтобы обмануть метод VisibleChanging!
Это может выглядеть примерно так:
//
// MDIForm
//
uses
{...,} Unit2;
procedure TForm1.Button1Click(Sender: TObject);
begin
Form2.Parent := Application.MainForm;
// или так
// Form2.Parent := TWinControl.Create( nil );
Form2.Hide;
end;
|
Вот оно, очередное подтверждение всем вам хорошо известной истины – если нельзя, но очень
хочется, то можно! Успехов в программировании!
|
При использовании материала - ссылка на сайт обязательна
|
|