joynter |
Отправлено: 08.09.2004, 12:23 |
|
Станционный диспетчер
Группа: Участник
Сообщений: 137
|
в либе создаю форму, на форму кладу кнопку далее
button->OnClick = button_click;
...
void button_click()
{
ShowMessage("...");
}
компилятор говорит "not an allowed type"
как правильно оформить в библиотеке реакцию на нажатие кнопки?
|
|
Guest |
Отправлено: 08.09.2004, 12:48 |
|
Не зарегистрирован
|
использовать closure, TNotifyEvent или можно почитать здесь |
|
Asher |
Отправлено: 08.09.2004, 12:56 |
|
Мастер участка
Группа: Модератор
Сообщений: 550
|
void __factcall button_click(TObject* Sender) не пробовал?
А вообще если это у тебя DLL то могут быть большие проблемы с передачей указателя между адресными пространствами (это когда будешь компилить без dinamic RTL)
|
|
joynter |
Отправлено: 08.09.2004, 13:50 |
|
Станционный диспетчер
Группа: Участник
Сообщений: 137
|
оказалось всё просто, как три рубля:
TMethod Method;
Method.Code= button_click;
button->OnClick = *(TNotifyEvent*)&Method;
void button_click()
{
ShowMessage("...");
}
|
|
Guest |
Отправлено: 08.09.2004, 14:17 |
|
Не зарегистрирован
|
Что то с памятью твоей станет ... |
|
joynter |
Отправлено: 08.09.2004, 14:40 |
|
Станционный диспетчер
Группа: Участник
Сообщений: 137
|
2Guest:
ты какую имеешь в виду? |
|
Konstantine |
Отправлено: 08.09.2004, 14:40 |
|
Мастер участка
Группа: Модератор
Сообщений: 545
|
QUOTE (joynter @ 08/09/2004, 14:52) | оказалось всё просто, как три рубля... |
Лучше послушай Asher-а он дело говорит:
Функцию объяви как
CODE | void __factcall button_click(TObject* Sender)
| и всё станет на свои места. А преобразование типа тем более ф-ции к добру не приведёт!!!
|
|
joynter |
Отправлено: 08.09.2004, 14:58 |
|
Станционный диспетчер
Группа: Участник
Сообщений: 137
|
люди добрые, объясните, почему
CODE | void __fastcall button_click(TObject* Sender) |
лучше, чем
где тут сермяжная правда? |
|
Asher |
Отправлено: 08.09.2004, 15:06 |
|
Мастер участка
Группа: Модератор
Сообщений: 550
|
Для того, чтобы так поступить
QUOTE | TMethod Method;
Method.Code= button_click;
button->OnClick = *(TNotifyEvent*)&Method; |
вам TMethod вовсе не нужен.
Если посмотреть в справку, то видим, что
QUOTE | struct TMethod
{
void *Code;
void *Data;
}; |
после чего разименованный указатель приводится к требуемому типу.
QUOTE | typedef void __fastcall (__closure *TNotifyEvent)(System::TObject* Sender); |
в вашем случае просто нехватало __fastcall и TObject* Sender в качестве параметров.
В принципе не понял где здесь DLL, но не суть важно.
при __fastcall первые три параметра передаются через регистры. (не все, но тоже не важно) и подпрограмма в праве ожидать их там. а без __fastcall все передает через стек. Это хорошо, что в вашем конкретном случае входных параметров нет. Инече можно было бы огрести по полной.
|
|
Asher |
Отправлено: 08.09.2004, 15:10 |
|
Мастер участка
Группа: Модератор
Сообщений: 550
|
QUOTE | люди добрые, объясните, почему
void __fastcall button_click(TObject* Sender)
лучше, чем
void button_click()
где тут сермяжная правда? |
просто OnClick типа TNotifyEvent
QUOTE |
__property Classes::TNotifyEvent OnClick = {read=FOnClick, write=FOnClick, stored=
IsOnClickStored}; |
|
|
joynter |
Отправлено: 08.09.2004, 16:07 |
|
Станционный диспетчер
Группа: Участник
Сообщений: 137
|
спасибо за подробный ответ |
|
Nick |
Отправлено: 09.09.2004, 08:33 |
|
Машинист паровоза
Группа: Участник
Сообщений: 247
|
"Что то с памятью твоей станет..."
Прошу прощения
не знал об 3 параметрах
при __fastcall первые три параметра передаются через регистры. (не все, но тоже не важно) и подпрограмма в праве ожидать их там. а без __fastcall все передает через стек. Это хорошо, что в вашем конкретном случае входных параметров нет. Инече можно было бы огрести по полной.
я имел ввиду чудеса со стеком |
|
joynter |
Отправлено: 09.09.2004, 09:11 |
|
Станционный диспетчер
Группа: Участник
Сообщений: 137
|
извините за назойливость, но у меня происходит еще одна непонятная мне штука, а именно:
при закрытии формы, вызванной из библиотеки, закрыватся и главная форма (хотя в процессах она по-прежнему есть).
не могли бы господа программисты объяснить мне суть этого явления?
вот библиотекаCODE | //---------------------------------------------------------------------------
#include <vcl.h>
#include <windows.h>
#include <Forms.hpp>
#pragma hdrstop
//---------------------------------------------------------------------------
#pragma argsused
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
return 1;
}
//---------------------------------------------------------------------------
extern "C" void __declspec(dllexport) CreateForm(TApplication*);
//---------------------------------------------------------------------------
void __fastcall button_click(TObject* Sender)
{
ShowMessage("кнопка нажата");
}
//***********************
void CreateForm(TApplication* any_application)
{
Application = any_application;
TForm *form = new TForm(Application);
form->Caption = "форма из библиотеки";
form->Height = 200;
form->Width = 300;
form->Position=poDefaultPosOnly;
TButton *button = new TButton(form);
button->Parent = form;
button->Height = 25;
button->Width = 76;
button->Top = form->Height — button->Height — 35;
button->Left = (form->Width — button->Width)/2;
button->Caption = "кнопка";
void *buffer;
buffer = button_click;
button->OnClick = *(TNotifyEvent*)&buffer;
form->ShowModal();
delete form;
}
|
вот вызывающая ее форма CODE | //---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
typedef void __declspec(dllimport) DLL_Addr(TApplication*);
HMODULE hDLL=LoadLibrary("DLL_Project.dll");
if(hDLL)
{
DLL_Addr *CreateForm = (DLL_Addr*)GetProcAddress(hDLL, "_CreateForm");
if(CreateForm)
CreateForm(Application);
else
ShowMessage("функция CreateForm не найдена в DLL_Project.dll");
FreeLibrary(hDLL);
}
else ShowMessage("не могу загрузить DLL_Project.dll");
}
//--------------------------------------------------------------------------- | |
|
pagan |
Отправлено: 09.09.2004, 09:51 |
|
Ученик-кочегар
Группа: Участник
Сообщений: 22
|
Сначала перепишите свой код :
CODE | static TApplication *AppDLL;
#pragma argsused
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
case DLL_PROCESS_DETACH: Application = AppDLL;
Application->Handle = NULL;
return 1;
}
//---------------------------------------------------------------------------
void CreateForm(void *AppMain)
{
if (! AppDLL)
{
Application->Handle = ((TApplication *)AppMain)->Handle;
AppDLL = Application;
Application = (TApplication *)AppMain;
}
// ... |
Объяснения чуть позже ...
Отредактировано pagan — 09/09/2004, 10:54 |
|
joynter |
Отправлено: 09.09.2004, 11:01 |
|
Станционный диспетчер
Группа: Участник
Сообщений: 137
|
подозреваю, что CODE |
switch (reason)
{
case DLL_PROCESS_DETACH: Application = AppDLL;
Application->Handle = NULL;} |
но после этих изменений ShowMessage("функция CreateForm не найдена в DLL_Project.dll");
|
|
pagan |
Отправлено: 09.09.2004, 11:41 |
|
Ученик-кочегар
Группа: Участник
Сообщений: 22
|
Объяснения (как и обещал) : Во-первых я бы не рекомендовал вам передавать указатели на объекты VCL в явном виде, по причине того, что DLL с VCL мягко говоря не очень ладят. Лучше передавать их как безтиповые (void), а потом преобразовывать.
Важно понять, что у приложения свой тип GUI приложения (т.е. экземпляр TApplication), а у DLL свой (в отличие от пакетов packages, ну это уже другая история) ! Поэтому их необходимо, как бы сказать "дружить".
Далее — при передачи экземпляра TApplication — приложения в библиотеку нам нужно направить его на TApplication — этой библиотеки. Предварительно сохранив значение типа GUI нашей DLL в какую-нть переменную.
При выходе из DLL (FreeLibrary) нам остается только вернуть ей ее же значение TApplication. Надеюсь объяснил понятно.
Также советую ознакомиться (позволит понять основные принципы):http://borland.xportal.ru/forum/viewtopic.php?t=3130
З.Ы. то что вы не можете найти адресс своей ф-и говорит о том, что где-то неправильно дано ее объявление — проверьте хвост этой ф-и в *.cpp своего приложения — должно быть ...(void *). Удачи! |
|
joynter |
Отправлено: 09.09.2004, 13:07 |
|
Станционный диспетчер
Группа: Участник
Сообщений: 137
|
спасибо еще раз |
|