Форум: "Основная";
Текущий архив: 2002.01.10;
Скачать: [xml.tar.bz2];
Вниз
В дочерних окнах из DLL не работают Найти похожие ветки
← →
ilysha (2001-12-20 10:00) [0]Ситуация такова - разработан огромный пакет прикладных программ, состоящий из основного exe-модуля и приложений DLL. Все было протестировано и отлажено.
Теперь настало время оформить пользовательский интерфейс согласно промышленного стандарта и вдруг выяснилось, что в дочерних MDI-окнах из DLL не работают горячие клавиши из PopupMenu. Если вызывать окно как SDI-окно, то все великолепно, но не подходит как решение этой проблемы.
Опытным путем выяснилось, что все команды обрабатываются главным окном приложения.
Кто сталкивался с данной проблемой поделитесь опытом решения.
← →
Алексей Петров (2001-12-20 10:05) [1]Включи везде опцию "Build with runtime packages" - это и требования к ресурсам уменьшит и указанную проблему должно решить.
Проблема-то в том, что в exe и в DLL свои отдельные Application. Причем они разных типов, т.к. TApplication в exe не то-же самое, что TApplication в DLL.
← →
ilysha (2001-12-20 10:53) [2]Алексей, присвоение Application.Handle из главного приложения библиотеке DLL решает проблему существования одного Handle - здесь все в порядке.
← →
vedmed (2001-12-20 10:54) [3]Рекомендуется устанавливать Handle объекта Application в DLL равным соответствующему Handle из исполняемого модуля, подробнее см. help по TApplication.Handle
← →
Алексей Петров (2001-12-20 11:16) [4]Вопрос не только в Application.Handle. Взаимодействие между объектами в exe и dll происходит по всем фронтам в вашем случаи.
Когда я изучал, как вся эта кухня (объекты, пакеты, и т.п.) работает, я пришел к выводу: Использование одного объекта и в DLL и в EXE корректно только при использовании Run time packages. Если пример, приведенный ниже, не достаточен для подтверждения данного утверждения - пишите, попробую обосновать подробнее.
Проведите эксперимент (без packages):
вот такую процедуру вставте в DLL и вызовите из exe c любым объектом в качестве параметра:
procedure isObject(obj: TObject);
begin
if obj is TObject then
ShowMessage("Is object")
else
ShowMessage("Is NOT object")
end;
Результат, я думаю, вас порадует :)
← →
Ura (2001-12-20 12:21) [5]Слушай а формочки в DLL у тебя MDI-шные?
Может делфя сможет сама наладить контакт при MDI приложении...
← →
ilysha (2001-12-20 12:25) [6]Результат меня убил, точнее будет сказать, что он убил мою систему. Что это означает?
И еще, Алексей, можно поподробнее о ваших собственных изысканиях.
О нашем проекте -
Существует базовый модуль - pro.exe. При запуске он проверяет присутствие модулей DLL и подгружает их командой LoadLibrary.
Из каждого модуля запускается mdi-child форма, с которой и работает пользователь.
← →
Алексей Петров (2001-12-20 13:02) [7]О моих изысканиях все никак руки не доходят написать статью :)
Вкратце смысл следующий:
Все объекты имеют системную часть VMT. Для D5 это 76 байт. Эта часть используется, в первую очередь, для поддержки RTTI. Среди всего прочего в ней прописан предок объекта. С помощью этого поля выстраивается связанный список с помощью которого можно добраться от любого класса через всех предков до TObject. именно этим полем пользуется функция TObject.ParentClass.
Все VMT, включая системную часть хранятся в сегменте кода каждого модуля (DLL, EXE, BPL).
Если Run-time пакеты не используются, в каждом модуле свой TObject, ничего не знающий о других. Соответственно иерархии объектов в каждом из модулей никак не связаны.
При использовании Runtime packs - общий TObject лежит в пакете vcl50.bpl и соответственно проблем не возникает.
Уточню утверждение: Безопасно использоване одного экземпляра в нескольких модулях только в том случаи, если объект описан в BPL, подключенном ко всем модулям, использующим объект.
Т.к. системный код и структуры системных данных, в exe и dll, если они скомпелированы одной версией Delphi, совпадает - то часто указанные проблемы не проявляются и вылезают только в редких местах, как у Вас, например.
Для справки:
TApplication, TScreen, TForm и Co описаны в vcl50.bpl. Во многих случаях достаточно подключать только один этот пакет.
Когда система уже почти готова, переделывать так врядли есть смысл, но на будующее:
Для систем, подобной вашей, чтоб обеспечить возможность дочерним окнам корректно обращаться к MDIFrame - есть смысл создать пакет, содержащий главное окно и абстрактного предка для всех MDIChild-ов.
При этом exe-шник становится минимальным - он загружает главный пакет и все.
А каждый из пакетов с MDIChild формами уже смело работает с главной формой. За счет общности VCL-ного кода, все работает так, как-будто все в одном exe-шнике сидит.
← →
ValeraVV (2001-12-20 13:50) [8]1. Результат не должен был убить систему (если конечно делалось то, что говорил Алексей Петров ©)
2. Оператор is сравнивает два указателя на класс (правда первый указатель бежит вверх по иерархии) и если эти два pointer совпали то можно сказать, что obj is TObject. Соотвественно, когда вызывается невиртуальный и не published метод объекта, точно можно сказать, что адрес метода берется из информации, сгенеренной компилятором. Если главный EXE и DLL-ки компилились отдельно, то для них это разные методы - результат не предсказуем.
3. Еще, IMHO, VMT не генерится в памяти для каждого создаваемого объекта (имеется в виду TObject, не object), а лишь дается ссылка на общую структуру для класса, тогда пункт два справедлив и для virtual methods
4. Если не используются пакеты, глобальные переменные в создаются в контексте главного thread"а, но в разных местах. В пакетах, при использовании threadvar на каждый thread одна переменная, не зависимо от модуля
5. Процедура перехода на пакеты не так уж сложна (поставить у всех проектов галочки и откомпилить) и скорее это сэкономит ресурсы, если DLL много и, к тому же, в них строятся VCL окна, а взаимодействие сводится к минимуму (иначе проблемы возникли бы раньше)
5. Если Microsoft делает огромный каталог system32 и юзает его из всех своих программ, еще в добавок для своего VC делает рантайм DLL-ки, а для своего VB тем более, то почему бы нам не использовать BPL, где не просто импортируются процедуры, но и отслеживается информация о классах, их иерархии и пр., тогда это не минус Delphi (в смысле у ilysha проблемы с Popup ShortCut"ами), а плюс.
Все что выше мои изыскания за Петрова, а к проблеме ilysha все-таки мало отношения имеет, точнее на 50%, путаница возникает либо из-за неправильного определения класса объекта из другого модуля, либо из-за неправильных/не указанных handl"ов окон (что делается через Application, Owner, Parent)
← →
Алексей Петров (2001-12-20 14:18) [9]> ValeraVV © (20.12.01 13:50)
пункт 3 - не ИМХО, а факт :) VMT генерится компилятором по одному экземпляру на каждий описанный тип объекта. Первые 4 байта экземплра любого объекта содержат как раз указатель на эту VMT
А вот п.4 - threadvar от packages никак не зависит. Там чисто виндовый механизм TLS данных исользуется.
← →
ValeraVV (2001-12-20 14:20) [10]Опоздал с изысками, еще они и неверные, сам же пользовался таким методом для plugin"ов:
создавал class"ы TPlugIn и TMainProgramm, описывал все методы как виртуальные абстрактные и юзал этот unit из главного проекта и модулей, где переписывал их методы, unit в BPL не оформлял и все работало!
Проблема с начались с VCL, например, вставка дополнительного control в главную форму вызывала ошибку Can"t assign TFont to TFont.
Короче, заборемся с флеймом флеймом, прекращаю
← →
ilysha (2001-12-21 09:00) [11]Проясняю ситуацию - если окно из DLL сделать обычным, и вызвать его из главного модуля, то все PopupMenu замечательно работают, но для нашего пакета требуется, чтобы из DLL было именно MDI-child.
Алексей, мы переделали весь проект на "Build with packages", однако проблема сохранилась и даже появилась новая - главную форму нельзя минимизировать. Может быть у вас где-нибудь завалялся пример своей работы?
← →
ValeraVV (2001-12-21 09:51) [12]Суть проблемы не в DLL!!!
ShortCut"ы в MDIChild не работают и без DLL!!!
Попробовал сам на простеньком проекте.
1. Работают только в ShowModal
2. Не работают в Show даже при отсутствии отношений MDIForm-MDIChild
То есть проблема шире, не работает даже в случае 2!
← →
ilysha (2001-12-21 10:16) [13]Браво ValeraVV !!!! Виват !!! Ура !!!
Я и стремлюсь выяснить это - почему не работает, кроме как по ShowModal. Ведь должно же быть нормальное объяснение. И это не флейм.
← →
ValeraVV (2001-12-21 10:17) [14]А минимизируется MDIForm нормально (у меня в проекте по крайней мере)
← →
ValeraVV (2001-12-21 10:25) [15]флейм - это я по поводу своих мессаг >ValeraVV © (20.12.01 14:20)
>ValeraVV © (20.12.01 13:50)
надо копать public function TCustomForm.ShowModal: Integer; virtual;
там есть "десять отличий" от Show+Activate (вариант 1) или перенаправлять нужные мессаги (windows) по списку MDIChilds (вариант 2)
← →
nikkie (2001-12-21 10:37) [16]положил на MDIChild ActionList - его shortcut"ы работают
← →
ilysha (2001-12-21 11:08) [17]Спасибо всем, кто не остался равнодушным к данной проблематике.
Более того, я выражаю искреннюю признательность Алексею Петрову за его пример, созданный и высланный нам в качестве учебного пособия. Вот теперь всё встало на свои места и работает.
Большое человеческое спасибо.
← →
ilysha (2001-12-21 11:12) [18]Пример можно сказачать по постоянному адресу:
http://www.ubb.adm.yar.ru/downloads/public/develop/delphi/mdi-BPL.zip
Файл является собственностью его автора - Алексея Петрова mailto:AKPetrov@pisem.net
← →
ilysha (2001-12-21 15:17) [19]Спасибо nikkie.
← →
ValeraVV (2001-12-21 17:10) [20]Короче,
в немодальной форме, отличной от главной
не работают shortcut"ы PopupMenu только в Delphi5
(shortcut"ы ActionList работают),
в Delphi6 shortcut"ы PopupMenu нормально работают, прям как ActionList в Delphi5
← →
ilysha (2001-12-22 13:35) [21]А знаете коллеги, что после того, как я разместил ссылку на пример работы с MDI-Child в DLL от Алексея Петрова на своем сервере, то по состоянию на 13 часов 22 декабря было произведено 2210 скачиваний.
Ура !
← →
ilysha (2001-12-22 20:07) [22]Всем, кто интересуется, на сайте Королевство Delphi по адресу http://www.delphikingdom.com/helloworld/usesdll.htm можно кое-что почитать по DLL.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2002.01.10;
Скачать: [xml.tar.bz2];
Память: 0.52 MB
Время: 0.003 c