Приложение.дескриптор из DLL

delphi

#delphi

Вопрос:

Delphi. Как из DLL научиться обрабатывать приложение, вызвавшее эту DLL?

Что нужно: зная дескрипторы приложений, я хочу в Dll использовать этот дескриптор при создании диалогов, потому что диалог создается как TOpenDialog.Создать (ноль) иногда он появляется под главным окном базовой формы. Итак, в DLL я бы сделал:

 application.handle:=GetExeHandle; // GetExeHandle - How to learn?
Opendialog1:=TOpendialog.Create(application);
...
 

Так это правильно?

Ответ №1:

Единственный раз, когда ваша DLL показывает диалоговое окно, это когда хост-приложение вызывает функцию из вашей DLL. Включите дескриптор родительского окна в качестве одного из входных параметров функции, чтобы EXE мог указать вам, какой дескриптор использовать. Не пытайтесь обнаружить дескриптор самостоятельно. Как разработчик библиотеки, вы не можете догадаться, что делает хост-приложение.

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

Комментарии:

1. Т.е. из dll узнать handle совершенно невозможно? 🙁

2. Gu, хост-приложение может иметь любое количество окон, включая ноль . Можете ли вы придумать способ узнать, какое из этих окон является «главным» окном, если вы больше ничего не знаете о природе хост-приложения? А что, если «главное» окно не принадлежит потоку, который вызывает вашу DLL-функцию? Делайте то, что делают все другие библиотеки DLL, и переложите нагрузку на хост: попросите хост указать вам , какой дескриптор использовать для родительских элементов диалога.

3. @Gu передача родительского дескриптора в DLL является стандартной практикой в Windows API (часто в пределах типа record [struct], например, TASKDIALOGCONFIG msdn.microsoft.com/en-us/library/bb787473(v=vs.85).aspx

4. Ок, произвел процедуру инициализации InitDll (h:thandle); {запустить приложение. handle: = h; end;}, после загрузки dll я вызываю InitDll (application. handle), вопрос: в dll достаточно сделать приложение. handle: =h; или нужно еще приложение перед этим создать?

5. это HWND, а не THandle

Ответ №2:

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

Ваша библиотека будет иметь собственную копию не только (T)Application очереди и события синхронизации потоков, но и всего остального.

То, что вы пытаетесь сделать, может показаться работающим, но оно может (и будет) прерываться в любое время, вызывая любой сложный диалог, независимо от того, выполняет ли VCL или WinAPI собственную перекачку сообщений, которая будет обходить обработку бездействия и синхронизации приложений, что приведет к проблемам повторного входа и случайным остановкам или тупикам.

Вы можете попытаться обработать множество случаев, скопировав дескрипторы приложений, события и т. Д. для глобальных файлов DLL при ее инициализации (это я пытался сделать), но (не только), если вы используете что-то вроде TApplication или TThread в DLL, иногда это будет ломаться.

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

Комментарии:

1. Вы можете использовать пакеты, только если ваше хост-приложение является приложением Delphi, созданным с той же версией компилятора, что и DLL. Иногда вам нужно показывать диалоги из DLL. Например, это важно, если вы показываете пользовательский интерфейс из надстройки COM Office.

2. Ах, конечно, мой ответ применим к приложениям Delphi. Если ваше хост-приложение не построено на Delphi, есть вероятность, что оно не будет страдать от этих проблем.

3. Ну, вам все равно придется иметь дело с проблемами, но на самом деле это не так сложно.