Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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.51 MB
Время: 0.003 c
3-28441
Sergey Karagodin
2001-12-10 09:28
2002.01.10
Как вернуть результат хранимой процедуры?


6-28527
PVK
2001-10-16 17:38
2002.01.10
Проблема с получением имени хоста по его адресу


1-28466
GorA
2001-12-21 15:18
2002.01.10
T(Rx)RichEdit


6-28515
Woolen
2001-10-13 09:52
2002.01.10
Определение URL


7-28550
Eduard1
2001-09-28 14:04
2002.01.10
Hook - Help me





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский