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 — это я. Но только самый последний!
|
|
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'а должен был Вам указать правильное направление мысли .
Тогда лучше представте свой код, поскольку как мне кажется, скорее всего ошибка где-то в другом месте...
|
|
Sl@Sh |
Отправлено: 25.05.2005, 15:52 |
|
Мастер участка
Группа: Участник
Сообщений: 383
|
QUOTE | Так Вы же не сказали какой конкретно компонент (объект) создаёте... |
Так уж не сказал ? Посмотрите выше. Повторю : TFtpServer. Компонент не родной, а из Internet Component Suite. В нём есть такой обработчик OnAuthenticate, вот его я и пытаюсь обработать. А кода я даже никакого не написал, когда с проблемой столкнулся. Я сразу написал обработчик (пустой) и просто так компильнул (привычка ).
Если поможет, прототип обработчика :
CODE |
void __fastcall ftp_Authenticate(TObject *,
TFtpCtrlSocket *, TFtpString &,
TFtpString &, bool &); |
|
|
Doga |
Отправлено: 25.05.2005, 17:07 |
|
Мастер участка
Группа: Участник
Сообщений: 575
|
Попробуйте объявить свой обработчик без "__fastcall"
|
|
Георгий |
Отправлено: 26.05.2005, 00:47 |
|
Почетный железнодорожник
Группа: Модератор
Сообщений: 874
|
возможно чего то не понимаю, но обработчик без класса сделать не удастся по такой прстой причине, что первым аргументом в стек ложится адрес экземпляра класса )
делай:CODE | class dummy{void my_fucking_method(void){};}; | |
|
Sl@Sh |
Отправлено: 26.05.2005, 09:26 |
|
Мастер участка
Группа: Участник
Сообщений: 383
|
Без __fastcall не выйдет. Во-первых обработчик должен иметь идентичный оригиналу прототип, а во-вторых — проверка только что показала
Насчёт невозможности — скорее всего так
Прога по задуме должна быть невидимой, и форма по сути не нужна. Вот я и решил из проекта форму удалить, а WinMain подкоректировал. В итоге получилось что-то вроде консоли с вцл, только никакого окна не появляется.
Отредактировано Sl@Sh — 26/05/2005, 09:27
|
|
Doga |
Отправлено: 26.05.2005, 17:03 |
|
Мастер участка
Группа: Участник
Сообщений: 575
|
Смоделировал Вашу ситуацию. Действительно, обработчик события, который не является членом каго либо класса, подключить не удаётся.
Пока вижу только 1 способ решения этой проблемы:
Создать наследника от этого компонента с уже реализованным событием.
Отредактировано Doga — 26/05/2005, 17:03
|
|
Asher |
Отправлено: 26.05.2005, 17:27 |
|
Мастер участка
Группа: Модератор
Сообщений: 550
|
Привет.
Смотрю я на эти страдания... уже второй день.
Чем вариант Георгия не устраивает?
Его только слегка подправить на тему видимости, public добавить, или для того-же в struct переделать.
CODE |
struct dummy{
void __fastcall ftp_Authenticate(TObject *,
TFtpCtrlSocket *, TFtpString &,
TFtpString &, bool &);
{
..Ваш код
};
};
|
Ну и не забыть экземпляр создать, прежде чем цеплять.
Сразу не писал, т.к. где-то вначале проскакивало что хочется без класса.
|
|
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
|
Спасибо всем ! Проблема решена
|
|