Как получить список открытых окон, включая DLL в приложении Delphi

Мое приложение может загружать библиотеки DLL, которые в основном содержат другие оконные приложения.

Он может открыть только одно окно DLL в любой момент времени.

Я столкнулся с ситуацией, когда в окне DLL отображается окно сообщения и/или в моем основном приложении отображается окно сообщения или модальная форма, а при деактивации приложения (переключение на другое), а затем его активация перемещает все окна случайным образом ( ?) z-порядок, благодаря чему форма DLL с окном сообщения располагается позади основной формы. Окно сообщения основной формы располагается за основной формой.

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

В Delphi я вижу, что есть объект Screen и у него есть список Forms. Я проверил его и увидел, что он содержит все формы, открытые в настоящее время моим приложением (даже окно сообщения, которое является результатом ShowMessage(), у него нет имени, но я вижу ClassName).

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

Как управлять z-порядком форм DLL?
DLL создаются с использованием Delphi, C++, WPF.


person user1651105    schedule 03.02.2014    source источник
comment
Что-то вроде этого, DLL Questions?   -  person LU RD    schedule 03.02.2014
comment
Вы подходите к этому совершенно неправильно. Перечисление окон и работа с z-порядком не помогут. Правильный способ решить эту проблему — убедиться, что окна созданы с правильным окном-владельцем. Как только вы это сделаете, система позаботится о z-порядке за вас. А когда у вас есть модальность, это еще более важно. Вам нужно перекалибровать свои усилия. Начните с прочтения этого: msdn.microsoft.com/en-us /библиотека/окна/рабочий стол/ms632599.aspx   -  person David Heffernan    schedule 03.02.2014


Ответы (1)


Вы должны следовать способу упорядочения окон ОС (с использованием ручки). Дескриптор приложения DLL по умолчанию равен нулю, поэтому вам необходимо определить его при отображении модальных диалогов.

Согласно документации Vcl.Forms.TApplication.Handle:

Примечание. При написании библиотеки DLL, использующей формы VCL, назначьте дескриптор главного окна исполняемого файла хоста свойству Handle глобальной переменной приложения библиотеки DLL. Это делает DLL частью основного приложения. Никогда не назначайте свойство Handle в EXE.

Чтобы сохранить Z-порядок модальных форм dll, выполните действия Питера Ниже suggests:

// In the dll
var
  oldWnd: HWND;
begin
  oldWnd := Application.Handle;
  Application.Handle := HandleOfHostform; // <-- Pass the exe host form handle
  try
    .... create and show the DLL form
  finally
    Application.Handle := oldWnd;
  end;
end;

Модальная форма должна быть создана без владельца, TMyDllForm.Create(nil).


Я не уверен на 100%, что Delphi-7 правильно разрешает дескриптор в DLL таким образом. Другой подход заключается в переопределении CreateParams для объекта формы, как предлагается here.

procedure TMyDLLForm.CreateParams(var Params: TCreateParams);
begin
  inherited;
  Params.WndParent := HandleOfHostForm;
end;
person LU RD    schedule 03.02.2014