Admin |
Отправлено: 02.01.2004, 18:35 |
|
Владимир
Группа: Администратор
Сообщений: 1190
|
Есть программа с главной формой, на которой распологается MainMenu
и есть dll (прилинковывается статически), в которой
создаются динамически новые пункты меню для этой главной формы
Упрощенно это выглядит так:
(в exe)
CODE |
extern "C" void __declspec(dllimport) GetRepMenuItems(TMenuItem* NMP);
void __fastcall TForm1::Button1Click(TObject *Sender)
{
// N5 — некий пункт MainMenu, к которому надо создать
// в dll пункты подменю и повесить обработчики событий
GetRepMenuItems(N5);
}
|
(в dll):
CODE |
extern "C" void __declspec(dllexport) GetRepMenuItems(TMenuItem* NMP);
//---------------------------------------------------------------------------
void GetRepMenuItems(TMenuItem* NMP)
{
NMP->Clear();
for(int i=0; i<10; i++){
TMenuItem* Itm = new TMenuItem(NMP);
Itm->Caption = "Меню"+IntToStr(i+1);
Itm->Tag = i;
// Itm->OnClick = MenuClick; ??????
NMP->Add(Itm);
}
}
//---------------------------------------------------------------------------
|
Пункты меню успешно создаются, а вот задать обработчики
событий OnClick для них в этой dll не получается.
Как создать/задать обработчик события onClick в dll для
этих пунктов MainMenu из Exe ???
(Конечно чтобы работало)
|
|
fellow |
Отправлено: 02.01.2004, 19:00 |
|
Не зарегистрирован
|
Наверное, задать обработчик (осуществить присвоение OnClick) всё же получается, а вот его вызов из главного модуля не проходит. Не так ли?
Если так, то, мне кажется, дело в том, что объявление обработчика внутри dll препятствует его вызову извне, т.к. он оказывается чисто внутренней, неэкспортируемой функцией. А если объявить его как экспортируемый? Получится ли тогда присвоение? |
|
Admin |
Отправлено: 03.01.2004, 14:14 |
|
Владимир
Группа: Администратор
Сообщений: 1190
|
Именно так все и обстоит.
Как объявить ее экспортируемой ?
В dll она выглядит вот так:
(там есть форма FormDll)
CODE |
void __fastcall TFormDll::RepClick(TObject* Sender)
{
frReport1->LoadFromFile("Report.frf");
frReport1->ShowReport();
}
|
Отредактировано Admin — 03/01/2004, 15:36
|
|
fellow |
Отправлено: 03.01.2004, 16:31 |
|
Не зарегистрирован
|
Казалось бы обычным способом: extern "C" void __declspec(dllexport).
Только вот, боюсь, этот номер не пройдёт, т.к. сигнатура получившейся функции будет отличаться от той, что ожидает компилятор. И он будет ругаться. Может быть, стоит создать заметсителя (proxy) в главном модуле для реакции на добавленные пункты меню, а dll регистрировала бы свои переходные функции у этих заместителей. Переходные функции, обявленные как extern "C" void __declspec(dllexport) вызывали бы реальные обработчики. |
|
Admin |
Отправлено: 04.01.2004, 14:58 |
|
Владимир
Группа: Администратор
Сообщений: 1190
|
Не работает. (переходные функции)
Причем, если пункты меню создаются в exe и обработчик
назначается в Exe — все работает,
(но надо-то все это перенести в dll)
если пункты меню создаются в dll, то неважно где назначается
обработчик OnClick и где он находится — в exe или в dll
- не работает !!!
|
|
fellow |
Отправлено: 04.01.2004, 16:45 |
|
Не зарегистрирован
|
Исходник Ваш скачал, но открыть не смог, т.к. у меня билдер пятый. Просмотрел код, советую вместо App->CreateForm(__classid(TFormAddRep), &FormAddRep); сделать просто FormAddRep = new TFormAddRep(NULL);
ещё вместо TMenuItem* Itm = new TMenuItem(NMPrint); TMenuItem* Itm = new TMenuItem(this); |
|
Admin |
Отправлено: 04.01.2004, 20:05 |
|
Владимир
Группа: Администратор
Сообщений: 1190
|
Возможно так и лучше, но к сожалению на результат не влияет,
OnClick не работает.
|
|
fellow |
Отправлено: 05.01.2004, 15:32 |
|
Не зарегистрирован
|
Вчера у меня работал. Только вот пример этот не сохранился. Сегодня, если время будет, заново его набросаю и отправлю Вам для экспериментов. |
|
fellow |
Отправлено: 05.01.2004, 20:33 |
|
Дежурный стрелочник
Группа: Участник
Сообщений: 33
|
Вот попробуйте этот примерчик. Он, конечно, упрощён донельзя, но OnClick работает.
|
|
Admin |
Отправлено: 06.01.2004, 20:44 |
|
Владимир
Группа: Администратор
Сообщений: 1190
|
Да, спасибо, попробовал, пример работает.
К сожалению, то что мне нужно — все равно через dll
работает плохо.
Вышел из ситуации — создал не dll, а библиотеку — .lib файл
туда и вставил то что нужно, все работает нормально.
|
|
Admin |
Отправлено: 07.01.2004, 13:02 |
|
Владимир
Группа: Администратор
Сообщений: 1190
|
А этот lib просто 'AddToProject' к любому проекту.
То что получилось в C++Builder 6
(должны стоять FIBPlus+FastReport+FR_RIB+FR_BDE)
|
|
fellow |
Отправлено: 08.01.2004, 05:32 |
|
Дежурный стрелочник
Группа: Участник
Сообщений: 33
|
lib к проекту практически равносильно включению исходников. Если первоначальной Вашей целью было достижения определённой степени модульности приложения, то вместо dll можно ещё было бы попробовать package. Не рассматривали такой вариант? |
|
Admin |
Отправлено: 08.01.2004, 10:40 |
|
Владимир
Группа: Администратор
Сообщений: 1190
|
QUOTE | lib к проекту практически равносильно включению исходников. |
Только они проверены и уже откомпилированы.
Это может быть библиотека своих часто используемых
в приложениях функций и форм.
Надо лишь 'AddToProject' и указать эту (или другую) библиотеку .lib
и эти функции будут доступны в программе.
Что касается dll то здесь ситуация почти та-же — в исходном коде
все равно надо вызывать функции из dll и заботиться о
загрузке/выгрузке dll (если она не цепляется статически),
таскать ее за собой (копировать вместе с exe) на другие компы.
Так что конечно все зависит от конкретной задачи.
Для моей задачи удобней оказывается lib. Спасибо.
|
|