Delphi, как сделать независимые окна

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

образ мой проводник!--4-->

С Наилучшими Пожеланиями Рой М. Клевер

5 ответов


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

чтобы начать, вам нужно избежать применения.Полностью форму mainform. Всегда используйте Form := TMyForm.Create(Application) вместо Application.CreateForm(TMyForm, Form). Более поздние наборы MainForm, и вы никогда не хотите, чтобы это произошло.

чтобы сделать вещи закрытыми должным образом, вам нужно будет сделать что-то вроде этого в вашей форме OnClose обработчик событий:

if Screen.FormCount = 1 then
  Application.Terminate;
CloseAction := caFree;

Application.Run полагается на присвоение MainForm, поэтому в вашем DPR замените эту строку этим циклом:

repeat
  try
    Application.HandleMessage;
  except
    Application.HandleException(Application);
  end;
until Application.Terminated;

существует несколько способов обработки записи на панели задач.

  1. запись на одной панели задач: Set Application.MainFormOnTaskbar := False; и будет использоваться скрытая ручка TApplication. При нажатии на запись панели задач все окна будут выведены на передний план. Вам нужно будет переопределить Application.OnMessage или добавить TApplicationEvents компонент, и следите за WM_CLOSE С Msg.Ручка = Приложение.Ручка.` В этом случае пользователь щелкнул правой кнопкой мыши на панели задач и выбрал закрыть, так что вы должны закрыть все окна.

  2. несколько записей панели задач: Set Application.MainFormOntaskbar := True. Переопределите форму CreateParams метод Params.WndParent := 0;. Каждая запись панели задач будет управлять этой формой.

есть, вероятно, несколько других gotchas, но это основы.


как я уже сказал, что делает ShowModal и TOpenDialog/TSaveDialog работает независимо, поэтому он влияет только на его родительскую форму, и поэтому несколько диалогов могут быть открыты сразу, это тонна работы, и я не могу ее рекомендовать. Если вы мазохист, вот общие шаги:

  1. заменить TCustomForm.ShowModal С пользовательской версии. Среди прочего, эта процедура отключает все остальные окна в приложении, поэтому вам нужно заменить DisableTaskWindows/EnableTaskWindows звонки с EnableWindow(Owner.Handle, False/True) чтобы просто отключить родительскую форму. На этом этапе можно открыть несколько диалоговых окон, но они могут быть закрыты только в порядке "последний вход" и "первый выход", поскольку вызовы становятся рекурсивными. Если все в порядке, остановись здесь.

    есть два способа обойти это:

    1. вместо ShowModal блокирование StartModal и EndModal подпрограммы, которые имеют Первый БИТ и последний бит кода ShowModal и вызывают OnShowModalDone событие, когда диалоговое окно закрытый. Это своего рода боль в использовании, но относительно легко кодировать и легко сделать стабильным.

    2. используйте Windows подпрограммы волокна для замены стека и запуска нового цикла сообщений. Этот подход прост в использовании, потому что ShowModal блокирует, поэтому вы называете это как обычно. Это подход, который мы использовали в Beyond Compare. не делай этого. это сложно написать, там будет вопросы стабильности для нетривиальных приложения из-за несовместимости со сторонним кодом (Windows global message hooks, TWebBrowser, .NET в расширениях оболочки, загружаемых диалоговым окном обзора и т. д.), И если это кросс-платформенный проект, функции ucontext Unix также небезопасны для использования.

  2. общие диалоги (TOpenDialog, TColorDialog и т. д.) имеют аналогичные ограничения. Чтобы сделать их только отключить родительскую форму, вам нужно переопределить TCommonDialog.TaskModalDialog и заменить DisableTaskWindows/EnableTaskWindows звонит и туда. Они не могут быть сделаны асинхронными, как обычные диалоговые окна Delphi выше, хотя, поскольку они блокируют функции, предоставляемые Windows (GetOpenFileName, ChooseColor и т. д.). Единственный способ закрыть их в любом порядке-запустить каждый диалог в выделенном потоке. Windows может обрабатывать большую часть синхронизации для этого, если вы будете осторожны с доступом к объектам VCL, но это в основном включает перезапись больших частей Dialogs.pas.


Если вы действительно хотите этого,

1) используйте небольшую, возможно скрытую, MainForm и запустите только первую дочернюю форму при запуске.

2) запуск отдельных приложений вместо Windows в том же процессе. Это то, что использует более поздняя версия Office.


вот аналогичный вопрос StackOverflow: активация нескольких приложений windows работает неправильно

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

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


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

Я не пробовал это, но он должен работать.


Это слишком поздно, чтобы ответить, но я столкнулся с той же проблемой. Решение, которое я выбрал, - это извлечь Application.ExeName и передать его функции, как createProcess или даже shellExecute. Итак, теперь у меня есть независимые приложения на уровне ОС. Мне также нужны были разные кнопки панели задач для разных экземпляров.