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. Ну, вам все равно придется иметь дело с проблемами, но на самом деле это не так сложно.