C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
Создать обработчик событий в dll, для компонентов из Exe
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
- не работает !!!



User Attached Image Скачать файл
menu.zip


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 работает.

User Attached Image Скачать файл
MenuDLL.zip


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)


User Attached Image Скачать файл
lib.zip


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. Спасибо.

Вернуться в Вопросы программирования в C++Builder