Re[3]: По мотивам SWL
От: WolfHound  
Дата: 16.05.03 11:32
Оценка:
Здравствуйте, limax, Вы писали:

L>А зачем всё это? Чем лучше предыдущего варианта? Комментарии?

Поддержка нескольких обработчиков для обного сообщения. Они будут вызваны в порядке перечисления в списке обработчиков. Причем если один из обработчиков сказал что он обработал это сообщение то другие его(сообщение)не получат. Можно еще исключения глушить... но я подумал что это не нужно.

L>Кстати, lboss-овскую неявную карту сообщений прикрутить не захотел? Я использую уже.

Мне показалось что это не очень удобно. Ибо у меня нет жилания в каждом обработчике писать return. Вот если будут статические конструкторы и шаблонные typedef'ы тогда другое дело.
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[4]: По мотивам SWL
От: limax Эстония http://mem.ee
Дата: 16.05.03 12:25
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Поддержка нескольких обработчиков для обного сообщения. Они будут вызваны в порядке перечисления в списке обработчиков. Причем если один из обработчиков сказал что он обработал это сообщение то другие его(сообщение)не получат. Можно еще исключения глушить... но я подумал что это не нужно.

Тоже интересно, только не могу придумать, где это может понадобиться. Всё равно ведь для базового класса пишешь вызов ||Window::ProcessMessage(msg);
А вот overhead карты растёт.

L>>Кстати, lboss-овскую неявную карту сообщений прикрутить не захотел? Я использую уже.

WH>Мне показалось что это не очень удобно. Ибо у меня нет жилания в каждом обработчике писать return.
На мой взгляд, возращать везде bool нагляднее, чем устанавливать флажок в Msg.
Кстати, ещё можно и со специализацией MsgOut (MsgResult в оригинале) поизвращаться.
Очень гибкая схема получается. Вот только проблема всех гибкостей — найти применение.

Ха! Задействовав вместо map аналог multimap можно организовать те же цепочки. Хе-хе, причём как! Просто учитывая порядок декларации обработчиков. Интересно, С++ гарантирует конструирование шаблонов возвращяемых значений в порядке декларации методов класса или нет?
MsgOut<This,WM_USER,__COUNTER__> onMsg(Msg<WM_USER>&);
MsgOut<This,WM_USER,__COUNTER__> onMsg(Msg<WM_USER>&);//в каком порядке будут сконструированы MsgOut?

Правда всё равно не вижу, зачем такая цепочка может понадобиться.
Have fun: Win+M, Ctrl+A, Enter
Re[5]: По мотивам SWL
От: WolfHound  
Дата: 16.05.03 15:27
Оценка:
Здравствуйте, limax, Вы писали:

L>Тоже интересно, только не могу придумать, где это может понадобиться.

Я тоже но просто тренеруюсь.
L>Всё равно ведь для базового класса пишешь вызов ||Window::ProcessMessage(msg);
В смысле? Ведь если сообщение перехвачено то в базовый класс оно не пойдет.
L>А вот overhead карты растёт.
Да какой там оверхед особенно если учесть что большенство обработчаков будут давольно тяжолыми.

L>На мой взгляд, возращать везде bool нагляднее, чем устанавливать флажок в Msg.

Не флажок надо заменить на метод.
L>Кстати, ещё можно и со специализацией MsgOut (MsgResult в оригинале) поизвращаться.
L>Очень гибкая схема получается. Вот только проблема всех гибкостей — найти применение.
А чего там можно еще прикрутить?

L>Ха! Задействовав вместо map аналог multimap можно организовать те же цепочки. Хе-хе, причём как!

Ха! С неявной картой не выдет!
L>Просто учитывая порядок декларации обработчиков. Интересно, С++ гарантирует конструирование шаблонов возвращяемых значений в порядке декларации методов класса или нет?
Не знаю.
L>
L>MsgOut<This,WM_USER,__COUNTER__> onMsg(Msg<WM_USER>&);
L>MsgOut<This,WM_USER,__COUNTER__> onMsg(Msg<WM_USER>&);//в каком порядке будут сконструированы MsgOut?
L>

Даже есль забыть что __COUNTER__ это не стандарт то это всеравно не скомпилится ибо функции различаются только возвращаемым значением.
... << RSDN@Home 1.0 beta 6a >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[6]: По мотивам SWL
От: limax Эстония http://mem.ee
Дата: 16.05.03 15:56
Оценка:
Здравствуйте, WolfHound, Вы писали:

L>>Кстати, ещё можно и со специализацией MsgOut (MsgResult в оригинале) поизвращаться.

L>>Очень гибкая схема получается. Вот только проблема всех гибкостей — найти применение.
WH>А чего там можно еще прикрутить?
Хз. Если б знал — не гадал бы.

WH>Даже есль забыть что __COUNTER__ это не стандарт то это всеравно не скомпилится ибо функции различаются только возвращаемым значением.

Тьфу, забыл. Сморозил.
А так?
MultiMsgOut<This,WM_USER,1> onMsg(MultiMsg<WM_USER,1>&);
MultiMsgOut<This,WM_USER,2> onMsg(MultiMsg<WM_USER,2>&);

Из взломщика вызывать не onMsg(Msg<...>), а onMsg(MultiMsg<...>), и т.д.
Можно использовать другой метод унификации. Дома додумаю...
Have fun: Win+M, Ctrl+A, Enter
Re[7]: По мотивам SWL
От: WolfHound  
Дата: 16.05.03 16:24
Оценка:
Здравствуйте, limax, Вы писали:

L>
L>MultiMsgOut<This,WM_USER,1> onMsg(MultiMsg<WM_USER,1>&);
L>MultiMsgOut<This,WM_USER,2> onMsg(MultiMsg<WM_USER,2>&);
L>

L>Из взломщика вызывать не onMsg(Msg<...>), а onMsg(MultiMsg<...>), и т.д.
L>Можно использовать другой метод унификации. Дома додумаю...
#define MESSAGE__(class, id, id2)\
MultiMsgOut<class,id,id2> onMsg(MultiMsg<id,id2>& msg);
#define MESSAGE_(class, id, id2)MESSAGE__(class, id, id2)
#define MESSAGE(id)MESSAGE_(CUR_CLASS, id, __COUNTER__)

А использовать так
class Test
{
    #define CUR_CLASS Test
    MESSAGE(WM_PAINT)
    {
        return false;
    }
    MESSAGE(WM_PAINT)
    {
        return false;
    }
    #undef CUR_CLASS
};

Но всеравно жутко смотрится.
... << RSDN@Home 1.0 beta 6a >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[5]: По мотивам SWL
От: lboss Россия  
Дата: 19.05.03 04:35
Оценка:
Здравствуйте, limax, Вы писали:

L>Кстати, ещё можно и со специализацией MsgOut (MsgResult в оригинале) поизвращаться.


Кстати я у себя MsgResult переименовал в OnMessage — так по моему наглядней:


 OnMessage<WM_CLOSE>  onMsg(Msg<WM_CLOSE> & msg);
 OnCommand<IDOK>  onMsg(Msg<WM_COMMAND> & msg);
С уважением Вадим.
Re[4]: По мотивам SWL
От: lboss Россия  
Дата: 19.05.03 04:44
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Поддержка нескольких обработчиков для обного сообщения. Они будут вызваны в порядке перечисления в списке обработчиков. Причем если один из обработчиков сказал что он обработал это сообщение то другие его(сообщение)не получат. Можно еще исключения глушить... но я подумал что это не нужно.


А зачем несколько обработчиков?! Интересно а как ты BeginPaint откатишь? Не проще ли одну функцию на класс заводить и вызывать из неё несколько своих?



OnMessage<WM_PAINT>  onMsg(Msg<WM_PAINT> & msg)
{
  return myFirstPaint(msg) || mySecondPaint(msg);
}
С уважением Вадим.
Re[6]: По мотивам SWL
От: limax Эстония http://mem.ee
Дата: 19.05.03 07:21
Оценка:
Здравствуйте, lboss, Вы писали:
L> OnMessage<WM_CLOSE>  onMsg(Msg<WM_CLOSE> & msg);
L> OnCommand<IDOK>  onMsg(Msg<WM_COMMAND> & msg);

А куда название класса дел? Или справился с вызовом инициализатора?
OnMessage<This,WM_CLOSE> ...
Have fun: Win+M, Ctrl+A, Enter
Re[7]: По мотивам SWL
От: lboss Россия  
Дата: 20.05.03 07:39
Оценка:
Здравствуйте, limax, Вы писали:

L>Здравствуйте, lboss, Вы писали:

L>
L>> OnMessage<WM_CLOSE>  onMsg(Msg<WM_CLOSE> & msg);
L>> OnCommand<IDOK>  onMsg(Msg<WM_COMMAND> & msg);
L>

L>А куда название класса дел? Или справился с вызовом инициализатора?
L>OnMessage<This,WM_CLOSE> ...

Нет просто упростил — я всё таки макросы заюзал:

#define VMessageMap(ThisClassName, BaseClassName)\
    typedef ThisClassName ThisClass;\
    virtual    bool    processMessage(MsgData & msg)\
    {\
        return MsgProcessor<ThisClass>::getInstance().processMessage(this, msg) || BaseClassName::processMessage(msg);\
    }

#define VOnMessage(MessageId)\
    OnMessage<ThisClass, MessageId> onMsg(Msg<MessageId> & msg)

#define VOnCommand(CommandId)\
    OnCommand<ThisClass, CommandId> onMsg(CommandMsg<CommandId> & msg)


Получается код:


class Test1 : public    Wnd
{
public:
    VMessageMap(Test1, Wnd);
        VOnMessage(WM_PAINT)
        {
            puts("VOnMessage(WM_PAINT)");
            return true;
        }
        VOnCommand(IDOK)
        {
            EndDialog(IDOK);
            return true;
        }

};
С уважением Вадим.
Re[8]: По мотивам SWL
От: limax Эстония http://mem.ee
Дата: 28.05.03 19:39
Оценка:
Здравствуйте, lboss, Вы писали:
L>#define VOnCommand(CommandId)\
L>    OnCommand<ThisClass, CommandId> onMsg(CommandMsg<CommandId> & msg)

Для OnCommand ещё одну карту создаёшь?
Have fun: Win+M, Ctrl+A, Enter
Re[9]: По мотивам SWL
От: lboss Россия  
Дата: 29.05.03 12:20
Оценка:
Здравствуйте, limax, Вы писали:

L>Здравствуйте, lboss, Вы писали:

L>
L>>#define VOnCommand(CommandId)\
L>>    OnCommand<ThisClass, CommandId> onMsg(CommandMsg<CommandId> & msg)
L>

L>Для OnCommand ещё одну карту создаёшь?

Нет — поюзал виртуальность...
С уважением Вадим.
Re[10]: По мотивам SWL
От: limax Эстония http://mem.ee
Дата: 29.05.03 18:41
Оценка:
Здравствуйте, lboss, Вы писали:
L>>Для OnCommand ещё одну карту создаёшь?

L>Нет — поюзал виртуальность...

Каким образом? Поподробнее, если можно.
Have fun: Win+M, Ctrl+A, Enter
Re[11]: По мотивам SWL
От: lboss Россия  
Дата: 30.05.03 03:49
Оценка:
Здравствуйте, limax, Вы писали:

L>Здравствуйте, lboss, Вы писали:

L>>>Для OnCommand ещё одну карту создаёшь?

L>>Нет — поюзал виртуальность...

L>Каким образом? Поподробнее, если можно.

Просто создал базовый класс с виртуальной функцией — она проосто процессит сообщение и говорит смогла или нет. А в карте сообщений заменил map на std::hash_map<UINT, std::list<VMessageProcessorBase *> >. Ну ещё приоритеты добавил...
С уважением Вадим.
Re[12]: По мотивам SWL
От: WolfHound  
Дата: 30.05.03 09:02
Оценка:
Здравствуйте, lboss, Вы писали:

L>Просто создал базовый класс с виртуальной функцией — она проосто процессит сообщение и говорит смогла или нет. А в карте сообщений заменил map на std::hash_map<UINT, std::list<VMessageProcessorBase *> >. Ну ещё приоритеты добавил...


Может выложишь что у тебя получилось, а мы посмотрим.
... << RSDN@Home 1.0 beta 6a >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[13]: По мотивам SWL
От: lboss Россия  
Дата: 02.06.03 09:57
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Может выложишь что у тебя получилось, а мы посмотрим.


Нет — там целая библиотека...
С уважением Вадим.
Re[14]: По мотивам SWL
От: WolfHound  
Дата: 02.06.03 11:55
Оценка:
Здравствуйте, lboss, Вы писали:

L>Нет — там целая библиотека...

В смысле? Не имеешь права или боишся что не влезет? Если второе то заархивируй и загрузи на сервер.
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[15]: По мотивам SWL
От: lboss Россия  
Дата: 03.06.03 03:52
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Здравствуйте, lboss, Вы писали:


L>>Нет — там целая библиотека...

WH>В смысле? Не имеешь права или боишся что не влезет? Если второе то заархивируй и загрузи на сервер.

А зачем это? Просто у меня есть своя библиотека (vlib) там много кода (в том числе и эксперементального) — оформлять и вычищать это нет времени — а вам эта куча мало что даст... Основные принципы работы с сообщениями я уже в флейме указал — так, что зачем выгружать всё библиотеку?!
С уважением Вадим.
Re[16]: По мотивам SWL
От: yaroslav_v http://yaroslav-v.chat.ru
Дата: 03.06.03 07:12
Оценка:
L>А зачем это? Просто у меня есть своя библиотека (vlib) там много кода (в том числе и эксперементального) — оформлять и вычищать это нет времени — а вам эта куча мало что даст... Основные принципы работы с сообщениями я уже в флейме указал — так, что зачем выгружать всё библиотеку?!

Достаточно пары файлов касающихся окон — не беда если это прямо не будет компилиться,
просто чем больше кода — тем понятнее, конечно у каждого накоплено много своего
кода и обычно в виде *.lib — файла, если ты не хочешь все публиковать — будет интересно
посмотреть часть, касаюэуюся SWL-modified.
Re[17]: Альтернативные раелизации
От: Kluev  
Дата: 03.06.03 18:04
Оценка:
Итак в ветке были рассмотрены три основных архитектуры обработки сообщений
1 — явные карты сообщений
2 — неявные карты сообщений
3 — базовый класс с виртуальными функциями-обработчиками
Третья была сразу отброшена как устаревщая и неэффективная.

Есть еще (как минимум) один пропущенный вариант: использования псевдо-виртуальныех функций
template <class T>
// базовый класс
struct WndBase {

    void msg_handle( UINT id, WPARAM w, LPARAM l ) {
        T *p = static_cast<T*>( this );
        switch ( id ) {
            case WM_PAINT: p->wm_paint(); break;
            case WM_MOVE: p->wm_move(LOWORD(l),HIWORD(l)); break;
            case WM_CREATE: p->wm_create(*(CREATESTRUCT*)l); break;
            // .... все виндовые сообщения
        }
    }

    void wm_paint() {}
    void wm_create( CREATESTRUCT&) {}
    void wm_move(int x, int y) {}
    // .... все виндовые сообщения
};

// производный
struct MyWnd : public WndBase<MyWnd> {
    void wm_move( int x, int y ) {
        // ....
    }
};

В этой реализации нет таких накладных расходов как при использовании виртуальных функций. Недостатки: необходимость обьявления всех обработчиков в базовом классе и switch в функции msg_handle (слишком длинный получится) Плюсом является то, что отпадает геморой связаный с использованием макросов и написанием завернутых сигнатур сообщений типа MsgResult<MyClass,WM_PAINT> onMsg( Msg<WM_PAINT>& ) и открывается путь к использованию нормальных сигнатур функций обработчиков wm_move(int x, int y).

В этой реализации всю картину портит свитч по всем виндовым сообщениям. От него можно отказатся так как помещение всех обработчиков в базовый класс открывает новые возможности к созданию карты сообщений. В частности можно путем сравнения указателей (&WndBase::wm_paint == &T::wm_paint) определить перегрузил ли пользователь функцию в дочернем классе. Это позволит неявно создавать карты сообщений и вкусить удобство от нормальных сигнатур обработчиков

struct WindowBase {
    void wm_paint()        { assert(0); } // не для вызова
    void wm_ncpaint()    { assert(0); }
    void wm_create()    { assert(0); }
    void wm_nccreate()    { assert(0); }
    void wm_size()        { assert(0); }
    void wm_move()        { assert(0); }
    // добавить все остальные сообщения
    void def_handler() {
        printf("def_handler\n");
    }

    virtual void msg_handle( UINT msg )    = 0;
};

typedef void (WindowBase::*XMFn)();

#define XANDLER_CHK( xfn, id ) if ( (XMFn)&T::xfn != (XMFn)&WindowBase::xfn ) { mmp[id] = (XMFn)&T::xfn; }

template <class T>
class Window : public WindowBase {
    typedef std::map<UINT,XMFn>    mp_id2xf;
public:

    void msg_handle( UINT msg ) {
        static mp_id2xf mmp;
        static bool init = true;
        if ( init ) {
            init = false;
            XANDLER_CHK( wm_paint, WM_PAINT );
            XANDLER_CHK( wm_ncpaint, WM_NCPAINT );
            XANDLER_CHK( wm_create, WM_CREATE );
            XANDLER_CHK( wm_nccreate, WM_NCCREATE );
            XANDLER_CHK( wm_size, WM_SIZE );
            XANDLER_CHK( wm_move, WM_MOVE );
        // добавить все остальные сообщения
        }
        mp_id2xf::iterator x = mmp.find( msg );
        if ( mmp.end() == x ) {
            def_handler();
        }
        else {
            WindowBase &p = *this;
            (p.*x->second)();
        }
            
    }

};

struct MyWnd : Window<MyWnd> {
    void wm_paint() {
        printf("paint\n");
    }
    void wm_move() {
        printf("move\n");
    }

};

void test() {
    MyWnd wnd;
    wnd.msg_handle( WM_PAINT ); // MyWnd::wm_paint
    wnd.msg_handle( WM_MOVE );  // MyWnd::wm_move 
    wnd.msg_handle( WM_CREATE );// WindowBase::def_handler
}


По идее, конечно, надо хранить в карте указатель не на обработчик, а на взломщик из которого уже будет вызыватся функция-обработчик:
void wm_crak_size( WPARAM, LPARAM l ) {
    T *p = static_cast<T*>(this);
    p->wm_size( LOWORD(l), HIWORD(l) );
}
Re[18]: Альтернативные раелизации
От: lboss Россия  
Дата: 04.06.03 04:10
Оценка:
Здравствуйте, Kluev, Вы писали:

<Skipped...>

Честно говоря это первая из реализаций, которая мне пришла в голову, но подумав я её отбросил по причинам:

1. Сообщений много — инстанциирование шаблона будет происходить каждый раз — это сделает процесс компиляции невыносимым...
2. Проблемма наследника от наследника: например диалог наследник окна. Но ведь от диалого тоже кто-то отнаследуется... В общем получается, что весь код — это шаблон (а-ля WTL) — это терпимо на не больших проектах, но становится невыносимым при укреплении проекта... А учитывая п.1 вообще нежизненно... Плюс отсутсвие нормального полиморфизма — иногда очень бесит. В общем стиль на любителя...
С уважением Вадим.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.