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

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

Изображение моего проводника

Наилучшие пожелания Roy M Klever

10
задан Roy M Klever 12 April 2010 в 18:53
поделиться

4 ответа

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

Для начала вам нужно полностью избегать Application.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. Отдельная запись на панели задач: Установите Application.MainFormOnTaskbar: = False; , и будет использоваться скрытый дескриптор TApplication. При нажатии на запись на панели задач все окна выводятся на передний план. Вам нужно будет переопределить Application.OnMessage или добавить компонент TApplicationEvents и следить за WM_CLOSE с помощью Msg.Handle = Application.Handle`. В этом случае пользователь щелкнул правой кнопкой мыши на панели задач и выбрал Закрыть , поэтому вам следует закрыть все окна.

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

Вероятно, есть еще несколько ошибок, но это основы.


Как я уже сказал, заставить 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, TWebBrowser, .NET в расширениях оболочки, загружаемых из диалогового окна просмотра, и т. д.), и если это кроссплатформенный проект, использование функций ucontext в Unix тоже небезопасно.

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

16
ответ дан 3 December 2019 в 18:32
поделиться

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

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

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

2
ответ дан 3 December 2019 в 18:32
поделиться

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

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

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

2
ответ дан 3 December 2019 в 18:32
поделиться

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

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

1
ответ дан 3 December 2019 в 18:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: