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

 
Свой обработчик вне класса
Sl@Sh
Отправлено: 23.05.2005, 14:21


Мастер участка

Группа: Участник
Сообщений: 383



Всем привет !
Возникла такая проблема. Необходимо динамически создать объект и создать для него обработчик. Всё это происходит в консольном приложении с использованием vcl.

Создаю объект, объявляю прототип обработчика, делаю так : [объект]->[Обработчик] = [МойОбработчик]. И вот тут компилятор говорит что не может выполнить присвоение т.к. в необходимом обработчике должно как-то использоваться расширение С++ __closure.

Если делать с формой (объявлять обработчик в её классе), то всё работает ОК.

Подскажите пожалуйста, как быть.

Спасибо !
Guest
Отправлено: 23.05.2005, 14:29


Не зарегистрирован







Довольно просто так — понаследовать класс от TComponent и создать обработчик внутри такого класса.
Можете покопать в сторону TMethod (в хелпе, примерах и на форуме).
Sl@Sh
Отправлено: 23.05.2005, 14:34


Мастер участка

Группа: Участник
Сообщений: 383



Не предполагается создавать никаких классов. Или без этого никак ?
Guest
Отправлено: 23.05.2005, 14:53


Не зарегистрирован







QUOTE

...
Всё это происходит в консольном приложении с использованием vcl.
Создаю объект, ...

Вы создаете объект не как экземпляр класса?
И кроме того, раз все равно VCL уже используется, разве так сложно написать пару лишних строк?
Sl@Sh
Отправлено: 23.05.2005, 15:01


Мастер участка

Группа: Участник
Сообщений: 383



Вы наверное не так поняли. Я не новый класс объявляю, а динамически создаю компонент (TFtpServer, из ICS)
Rius
Отправлено: 23.05.2005, 15:57


Мастер участка

Группа: Участник
Сообщений: 321



создать форму, поместить компонент, создать обработчик и посмотреть, как он записан. затем в своей программе сделать такую же функцию.

з.ы. __closure описано в TNotifyEvent
Guest
Отправлено: 24.05.2005, 13:05


Не зарегистрирован







Sl@ShClass.hpp

CODE

typedef void __fastcall (__closure *TRecalcFunc)(void);

class TSl@ShClass
{
 private:
   TRecalcFunc FRecalcFunc;

 public:
   __property TRecalcFunc RecalcFunc = {read = FRecalcFunc, write = FRecalcFunc};
}


Using TSl@ShClass

CODE

void __fastcall ExternalRecalcFunc(void)
{
  //...
}

//...

TSl@ShClass *Sl@ShClass = new TSl@ShClass();

Sl@ShClass->RecalcFunc = ExternalRecalcFunc;
Doga
Отправлено: 24.05.2005, 13:09


Мастер участка

Группа: Участник
Сообщений: 575



Прошу прощения, забыл представиться. Самый последний GUEST — это я. Но только самый последний! biggrin.gif
Sl@Sh
Отправлено: 24.05.2005, 15:44


Мастер участка

Группа: Участник
Сообщений: 383



QUOTE (Rius @ 23/05/2005, 15:57)
создать форму, поместить компонент, создать обработчик и посмотреть, как он записан. затем в своей программе сделать такую же функцию.

Зачем ? В том-то и дело, что я всё так делал. Разница в том, что при форме, обработчики объявляются в её классе, а в моём случае класса нет

to Doga Зачем создавать класс. Я динамически создаю компонент. Ему пишу свой обработчик.

Отредактировано Sl@Sh — 24/05/2005, 15:49
Rius
Отправлено: 24.05.2005, 18:43


Мастер участка

Группа: Участник
Сообщений: 321



Sl@ShClass.hpp

CODE
class TSl@ShClass
{
private:
  TNotifyEvent FRecalcFunc;

__published:
  __property TNotifyEvent RecalcFunc = {read = FRecalcFunc, write = FRecalcFunc};
}



Using TSl@ShClass
CODE
void __fastcall Form1::ExternalRecalcFunc(TObject *Sender)
{
 //...
}

//...

TSl@ShClass *Sl@ShClass = new TSl@ShClass();

Sl@ShClass->RecalcFunc = ExternalRecalcFunc;

Если компонент есть на палитре компонент и виден на форме (хоть и не визуальный), то в инспекторе объектов можно создать функцию обработки.
Любую свою функцию можно объявить в классе формы, в разделе public или private, только не в IDE-managed Components

TNotifyEvent есть
CODE
typedef void __fastcall (__closure *TNotifyEvent)(System::TObjectTObject* Sender);
Doga
Отправлено: 24.05.2005, 18:47


Мастер участка

Группа: Участник
Сообщений: 575



Так Вы же не сказали какой конкретно компонент (объект) создаёте...

В таком случае, совет Rius'а должен был Вам указать правильное направление мысли smile.gif.

Тогда лучше представте свой код, поскольку как мне кажется, скорее всего ошибка где-то в другом месте...
Sl@Sh
Отправлено: 25.05.2005, 15:52


Мастер участка

Группа: Участник
Сообщений: 383



QUOTE
Так Вы же не сказали какой конкретно компонент (объект) создаёте...


Так уж не сказал ? Посмотрите выше. Повторю : TFtpServer. Компонент не родной, а из Internet Component Suite. В нём есть такой обработчик OnAuthenticate, вот его я и пытаюсь обработать. А кода я даже никакого не написал, когда с проблемой столкнулся. Я сразу написал обработчик (пустой) и просто так компильнул (привычка smile.gif ).

Если поможет, прототип обработчика :
CODE

void __fastcall ftp_Authenticate(TObject *,
                                                  TFtpCtrlSocket *, TFtpString &,
                                                  TFtpString &, bool &);
Doga
Отправлено: 25.05.2005, 17:07


Мастер участка

Группа: Участник
Сообщений: 575



Попробуйте объявить свой обработчик без "__fastcall"
Георгий
Отправлено: 26.05.2005, 00:47


Почетный железнодорожник

Группа: Модератор
Сообщений: 874



возможно чего то не понимаю, но обработчик без класса сделать не удастся по такой прстой причине, что первым аргументом в стек ложится адрес экземпляра класса smile.gif)
делай:
CODE
class dummy{void my_fucking_method(void){};};
Sl@Sh
Отправлено: 26.05.2005, 09:26


Мастер участка

Группа: Участник
Сообщений: 383



Без __fastcall не выйдет. Во-первых обработчик должен иметь идентичный оригиналу прототип, а во-вторых — проверка только что показала sad.gif

Насчёт невозможности — скорее всего так sad.gif

Прога по задуме должна быть невидимой, и форма по сути не нужна. Вот я и решил из проекта форму удалить, а WinMain подкоректировал. В итоге получилось что-то вроде консоли с вцл, только никакого окна не появляется.

Отредактировано Sl@Sh — 26/05/2005, 09:27
Doga
Отправлено: 26.05.2005, 17:03


Мастер участка

Группа: Участник
Сообщений: 575



Смоделировал Вашу ситуацию. Действительно, обработчик события, который не является членом каго либо класса, подключить не удаётся. sad.gif

Пока вижу только 1 способ решения этой проблемы:

Создать наследника от этого компонента с уже реализованным событием.

Отредактировано Doga — 26/05/2005, 17:03
Asher
Отправлено: 26.05.2005, 17:27


Мастер участка

Группа: Модератор
Сообщений: 550



Привет.
Смотрю я на эти страдания... biggrin.gif уже второй день.
Чем вариант Георгия не устраивает?
Его только слегка подправить на тему видимости, public добавить, или для того-же в struct переделать.
CODE

struct dummy{
void __fastcall ftp_Authenticate(TObject *,
                                                 TFtpCtrlSocket *, TFtpString &,
                                                 TFtpString &, bool &);
{
..Ваш код
};
};

Ну и не забыть экземпляр создать, прежде чем цеплять. biggrin.gif biggrin.gif biggrin.gif
Сразу не писал, т.к. где-то вначале проскакивало что хочется без класса. wink.gif
Gedeon
Отправлено: 26.05.2005, 18:01


Ветеран

Группа: Модератор
Сообщений: 1742



Еще можно DataModule прицепить в проект и не париться.
AVC
Отправлено: 27.05.2005, 08:01


Ветеран

Группа: Модератор
Сообщений: 1583



Тоже было интересно понаблюдать.
Вот вариант решения именно в постановке Sl@Sh — без создания класса
Form1 имитирует объект TFtpServer.
CODE

void __fastcall MyFun (void* obj, TObject *Sender)
{
Beep();
ShowMessage(IntToHex(int(obj),8));
}

//---------------------------------------------------------------------------

WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
try
{
Application->Initialize();
Application->CreateForm(__classid(TForm1), &Form1);

TForm *frm = (TForm*)Form1;
TMethod *met = (TMethod*)&(frm->OnActivate);
met->Code = &MyFun;
met->Data = Form1;

Application->Run();
}
catch (Exception &exception)
{
Application->ShowException(&exception);
}
return 0;
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------

__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)
{
ShowMessage(IntToHex(int(this),8));
}


Sl@Sh — помните второе сообщение? Это был я, думал найдете сами.

Отредактировано AVC — 27/05/2005, 15:47
Sl@Sh
Отправлено: 27.05.2005, 16:12


Мастер участка

Группа: Участник
Сообщений: 383



Спасибо всем ! Проблема решена smile.gif

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