DLL + TWinControl + THint
От: Аноним  
Дата: 26.02.03 12:30
Оценка:
Здравствуйте, господа программисты!

У меня вопрос к Вам по теме "Разработка приложений с использованием
DLL-файлов (модулей)"

На этом сайте я нашёл много чего интересного и полезного. Но всё-таки есть
подводные камни.
Мы знаем, что использование дочерних MDI-форм в DLL и вызов их в главном
ехе-приложении
даёт массу проблем из-за дублирования кодов классов в dll и ехе-файлов,
из-за своего менеджера
памяти.
И эту проблему пытаются частично урегулировать или грубо решить передачей
глобальных параметров таких как TScreen, TApplication.
Это же неполное решение проблемы.
У меня вот возникла новая проблема:
1) Не работают контролы в дочерних формах (TControl), то есть курсор
табуляции не перемещается по элементам (TEdit, TButton), расположенных на
дочерней форме, заложенной в DLL-модуле.
2) Не работают Hint'ы на элементах управления, например, на кнопках.
Выскакивает сообщение:
"Cannot assign TFont to TFont".
Я не согласен с тем автором ответа на вопрос 4777 — Михаилом, чтобы править
файл.
Его ответ такой:
-----------
27.02.2001 13:38:03
Я правил для этого graphics.pas

procedure TFont.Assign(Source: TPersistent);
begin
было
if Source is TFont then
стало
if (Source is TFont) or (Source.ClassName = 'TFont') then

----------

Я сначала поправил этот участок кода, заработал хинт на кнопках, зато
получил массу других проблем, которые не буду приводить. Поэтому не
рекомендую просто так от радости править код в файле graphics.pas, пока не
разберётесь в чём истинная проблема.

Программисты, я прошу помочь Вас поделиться со мной секретами или советами:
как заставить работать TControl's и THint's на MDIChild-формах в
DLL-модулях. Пожалуйста дайте ссылки или намёки и т.д.

Заранее благодарю за помощь.

Сергей.
Re: DLL + TWinControl + THint
От: Demiurg  
Дата: 26.02.03 12:41
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, господа программисты!


А>У меня вопрос к Вам по теме "Разработка приложений с использованием

А>DLL-файлов (модулей)"

Про хинты скорее всего вторая часть ответа
здесь
Автор: Demiurg
Дата: 26.02.03
Re[2]: DLL + TWinControl + THint
От: Аноним  
Дата: 26.02.03 14:16
Оценка:
Здравствуйте, Demiurg, Вы писали:

D>Здравствуйте, Аноним, Вы писали:


А>>Здравствуйте, господа программисты!


А>>У меня вопрос к Вам по теме "Разработка приложений с использованием

А>>DLL-файлов (модулей)"

D> Про хинты скорее всего вторая часть ответа

D> здесь
Автор: Demiurg
Дата: 26.02.03


Я этот ответ читал до Вашего ответа.
У меня так и делается передачей глобальных параметров TApplication, TScreen

initialiazation
DLLAppl:=ExeAppl;

finalization
ExeAppl:=DLLAppl;

А при создании формы
procedure CreateForm(App:TApplication)
...

Application:=App;
MDIForm:=TMDIForm.Create(Application)

Этого " Application:=App;" мало?
Здесь одинаково, что и Application.Handle:=App.Handle;
Re[3]: DLL + TWinControl + THint
От: AlexandrN Россия  
Дата: 26.02.03 14:45
Оценка:
Привет...
Как уже много раз говорилось.................
Необходимо передовать не Handle — Application, а Handle — главной формы приложения
Т.е. Application->MainForm->Handl — для ChildForm из DLL.
С уважением.
AlexandrN
Re[4]: DLL + TWinControl + THint
От: Аноним  
Дата: 27.02.03 07:29
Оценка:
Здравствуйте, AlexandrN, Вы писали:

AN>Привет...

AN>Как уже много раз говорилось.................
AN>Необходимо передовать не Handle — Application, а Handle — главной формы приложения
AN>Т.е. Application->MainForm->Handl — для ChildForm из DLL.

Александр, Вы хоть понимаете, о чём речь идёт?

У нас речь идёт о НЕМОДАЛЬНЫХ MDIChild-формах, а не о модальных формах.
Для модальных форм достаточно

function ShowForm : Integer; stdcall;
var
Form : TDLLForm;
begin
Form := TDLLForm.Create(Application);
Result := Form.ShowModal;
Form.Free;
end;

или

F>extern "C" void __declspec( dllexport) Test(HWND hMainFormWnd)

F>{
F> Application->Handle = hMainFormWnd;
F> Form1 = new TForm1(NULL);
F> Form1->ShowModal();
F> delete Form1;
F>}

А для ВАС лично пишу: для НЕМОДАЛЬНЫХ форм тут такой трюк не катится!!!

Следует обратить особое внимание на работу с дочерними формами в DLL. Если, к примеру,
в вызывающем приложении главная форма имеет значение свойства FormStyle, равным MDIForm,
то при попытке вызова из DLL MDIChild-формы, на экране появится сообщение об ошибке,
в котором будет говориться, что нет ни одной активной MDI-формы.

В тот момент, когда вы пытаетесь показать ваше дочернее окно, VCL проверяет корректность
свойства FormStyle главной формы приложения. Однако в нашем случае все вроде бы верно.
Так в чем же дело? Проблема в том, что при проведении такой проверки, рассматривается объект Application,
принадлежащий не вызывающему приложению, а собственно динамической библиотеке.
Ну, и естественно, поскольку в DLL нет главной формы, проверка выдает ошибку.
Для того чтобы избежать такой ситуации, надо назначить объекту Application динамической библиотеки
объект Application вызывающего приложения. Естественно, это заработает только в том случае,
когда вызывающая программа — VCL-приложение. Кроме того, перед выгрузкой библиотеки из памяти
необходимо вернуть значение объекта Application библиотеки в первоначальное состояние.
Это позволит менеджеру памяти очистить оперативную память, занимаемую библиотекой.
Следовательно, вам нужно сохранить указатель на «родной» для библиотеки объект Application
в глобальной переменной, которая может быть использована при восстановлении его значения.

Итак, вернемся немного назад и перечислим шаги, необходимые нам для работы с помещенным
в DLL MDIChild-формами.

В динамической библиотеке создаем глобальную переменную типа TApplication.
Сохраняем указатель на объект Application DLL в глобальной переменной.
Объекту Application динамической библиотеки ставим в соответствие указатель на Application
вызывающего приложения.
Создаем MDIChild-форму и работаем с ней.
Возвращаем в первоначальное состояние значение объекта Application динамической библиотеки
и выгружаем DLL из памяти.
Первый шаг прост. Просто помещаем следующий код в верхней части модуля DLL:
var
DllApp : TApplication;
Затем создаем процедуру, которая будет изменять значение объекта Application и создавать дочернюю форму.
Процедура может выглядеть примерно так:

procedure ShowMDIChild(MainApp : TApplication);
var
Child : TMDIChild;
begin
Application := MainApp;
Child := TMDIChild.Create(Application);
Child.Show;
end;

У меня есть код программы, разработанной для авиакомпании. Там передаются как раз TApplication (для МДИ-форм), TScreen (для работы меню и прочих контролов).


Я могу Вам дать кучу примеров-исходников, где употребляются именно эти две переменные
TApplication и TScreen.

Мне надо решить проблему глюков насчёт Табуляции и хинтов.
Вот ответ одного парня:
S hintami problem netu (esli ne prinimat vo vnimaniye bug v delphi5 v THintWindow) — vse hinti pokazivayutsa bez kakih-nibud dopolnitelnih mehanizmov).
Vse ostalniye problemi (Tab, shortcuti na knopkah i t.d.) svyazani s tem, chto MDIForm ne vidit activniy MDIChild, esli tot bil zagruzhen iz DLL. Postav F5 na TCustomForm.GetActiveMDIChild v forms.pas i ividish, chto FindControl ne nahodit ActiveMDIChild. Kakoye-to vremya nazad ya pitalsya s etim razobratsa, potom brosil (chto-to tam bilo svyazano s atomami).
V to zhe vremya esli ti peredayosh ssilku na svoyu MDIForm v DLL, poprobuy vizvat MainForm.ActiveMDIChild ottuda — vizvannoye is DLL eto svoystvo korrektno vozvraschayet ActiveMDIChild. Poprobuy peredvinut v forms.pas metod GetMdiChild is private v protected, sdelat ego virtual i override v tvoyey forme — eto dolzhno reshit chast problem, no daleko ne vse (mi ot etogo resheniya otkazalis po ochevidnim prichinam).
Re[5]: DLL + TWinControl + THint
От: AlexandrN Россия  
Дата: 27.02.03 07:58
Оценка:
Извените, я не знаю как тут у вас катит, а как некатит...
Но я уже давно работаю с разными формами из DLL, причём даже с целыми MDIMainForms, которые грузятся Application — ом, а ChildForms — грузятся из других DLL, которые загружает MDIMainForm.
Пока всё работает и Hints и ShortCut`s и просто горячие клавиши.
С уважением.
AlexandrN
Re[6]: DLL + TWinControl + THint
От: Аноним  
Дата: 27.02.03 09:27
Оценка: 36 (1)
Здравствуйте, AlexandrN, Вы писали:

AN>Извените, я не знаю как тут у вас катит, а как некатит...

AN>Но я уже давно работаю с разными формами из DLL, причём даже с целыми MDIMainForms, которые грузятся Application — ом, а ChildForms — грузятся из других DLL, которые загружает MDIMainForm.
AN>Пока всё работает и Hints и ShortCut`s и просто горячие клавиши.

Если Вы так написали, то я удивлюсь. Каким образом у Вас всё так работает? Если не трудно, то скопируйте из примеров куски кода и вставьте туда.
А почему тогда во многих примерах и книгах даже пишут так, как я сделал, а не так как у вас получилось. Каждый имеет право на ошибку.
Если не трудно, то, пожалуйста, приведите полный работающий пример. Я проанализирую его и сниму шляпу перед Вами.

С уважением, Сергей.
Re[6]: DLL + TWinControl + THint
От: Аноним  
Дата: 28.02.03 12:15
Оценка:
Здравствуйте, AlexandrN, Вы писали:

AN>Извените, я не знаю как тут у вас катит, а как некатит...

AN>Но я уже давно работаю с разными формами из DLL, причём даже с целыми MDIMainForms, которые грузятся Application — ом, а ChildForms — грузятся из других DLL, которые загружает MDIMainForm.
AN>Пока всё работает и Hints и ShortCut`s и просто горячие клавиши.

Вы наверно работаете только с C++ Builder, архитектура построения программ которого отличается от построения на Delphi.

Пример функции в dll (C++ Builder):

void ShowMDIForm(HWND _Handle)
{
Application->Handle = _Handle;
...
}

Пример вызова функции в dll из программы:

ShowMDIForm(MainForm->Handle);
Re: DLL + TWinControl + THint
От: Shap  
Дата: 01.03.03 09:13
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, господа программисты!


А>У меня вопрос к Вам по теме "Разработка приложений с использованием

А>DLL-файлов (модулей)"

А> 1) Не работают контролы в дочерних формах (TControl), то есть курсор

А>табуляции не перемещается по элементам (TEdit, TButton), расположенных на
А>дочерней форме, заложенной в DLL-модуле.
А> 2) Не работают Hint'ы на элементах управления, например, на кнопках.
А>Выскакивает сообщение:
А>"Cannot assign TFont to TFont".

Здравствуйте. Увы вряд ли смогу помочь, но хочу поделиться информацией, о том, что сам никак не могу решить аналогичную проблему. Единственное отличие в том, что hint'ы у меня все-же работают, но уж если они хоть раз за время работы с mdichild формой из dll срабатывали, то при выгрузке библиотеки из памяти возникает ошибка Access violation... Та же ситуация была с компонентом rxsplitter, пока я не заменил их на стандартные splitter.
Если Вам удастся найти решение этой проблемы, пожалуйста поделитесь им на форуме или со мной: jeka@azovprom.com Обещаю и со своей стороны поделиться полезной информацией.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.