Форум: "Основная";
Поиск по всему сайту: delphimaster.net;
Текущий архив: 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.




Форум: "Основная";
Поиск по всему сайту: delphimaster.net;
Текущий архив: 2002.01.10;
Скачать: [xml.tar.bz2];




Наверх





Память: 0.78 MB
Время: 0.029 c
1-28499           nevidimie             2001-12-23 13:44  2002.01.10  
Обработка Memo


1-28482           Валик                 2001-12-21 18:38  2002.01.10  
Создание Wizard`а


14-28540          savva                 2001-11-15 12:28  2002.01.10  
Поздравляем сегодня человека с ником Jey - у него сегодня день ВАРЕНЬЯ!!! (и подружнее товариши:)))


3-28431           Alex_sh               2001-12-10 07:37  2002.01.10  
Обьясните


3-28412           Yakudza               2001-12-06 13:02  2002.01.10  
Fast Report.