Здравствуйте, limax, Вы писали:
L>А зачем всё это? Чем лучше предыдущего варианта? Комментарии?
Поддержка нескольких обработчиков для обного сообщения. Они будут вызваны в порядке перечисления в списке обработчиков. Причем если один из обработчиков сказал что он обработал это сообщение то другие его(сообщение)не получат. Можно еще исключения глушить... но я подумал что это не нужно.
L>Кстати, lboss-овскую неявную карту сообщений прикрутить не захотел? Я использую уже.
Мне показалось что это не очень удобно. Ибо у меня нет жилания в каждом обработчике писать return. Вот если будут статические конструкторы и шаблонные typedef'ы тогда другое дело.
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, 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?
Правда всё равно не вижу, зачем такая цепочка может понадобиться.
Здравствуйте, 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) А. Эйнштейн
Здравствуйте, WolfHound, Вы писали:
L>>Кстати, ещё можно и со специализацией MsgOut (MsgResult в оригинале) поизвращаться. L>>Очень гибкая схема получается. Вот только проблема всех гибкостей — найти применение. WH>А чего там можно еще прикрутить?
Хз. Если б знал — не гадал бы.
WH>Даже есль забыть что __COUNTER__ это не стандарт то это всеравно не скомпилится ибо функции различаются только возвращаемым значением.
Тьфу, забыл. Сморозил.
А так?
Здравствуйте, WolfHound, Вы писали:
WH>Поддержка нескольких обработчиков для обного сообщения. Они будут вызваны в порядке перечисления в списке обработчиков. Причем если один из обработчиков сказал что он обработал это сообщение то другие его(сообщение)не получат. Можно еще исключения глушить... но я подумал что это не нужно.
А зачем несколько обработчиков?! Интересно а как ты BeginPaint откатишь? Не проще ли одну функцию на класс заводить и вызывать из неё несколько своих?
Здравствуйте, limax, Вы писали:
L>Здравствуйте, lboss, Вы писали: L>>>Для OnCommand ещё одну карту создаёшь?
L>>Нет — поюзал виртуальность... L>Каким образом? Поподробнее, если можно.
Просто создал базовый класс с виртуальной функцией — она проосто процессит сообщение и говорит смогла или нет. А в карте сообщений заменил map на std::hash_map<UINT, std::list<VMessageProcessorBase *> >. Ну ещё приоритеты добавил...
Здравствуйте, lboss, Вы писали:
L>Просто создал базовый класс с виртуальной функцией — она проосто процессит сообщение и говорит смогла или нет. А в карте сообщений заменил map на std::hash_map<UINT, std::list<VMessageProcessorBase *> >. Ну ещё приоритеты добавил...
Может выложишь что у тебя получилось, а мы посмотрим.
... << RSDN@Home 1.0 beta 6a >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, lboss, Вы писали:
L>Нет — там целая библиотека...
В смысле? Не имеешь права или боишся что не влезет? Если второе то заархивируй и загрузи на сервер.
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, WolfHound, Вы писали:
WH>Здравствуйте, lboss, Вы писали:
L>>Нет — там целая библиотека... WH>В смысле? Не имеешь права или боишся что не влезет? Если второе то заархивируй и загрузи на сервер.
А зачем это? Просто у меня есть своя библиотека (vlib) там много кода (в том числе и эксперементального) — оформлять и вычищать это нет времени — а вам эта куча мало что даст... Основные принципы работы с сообщениями я уже в флейме указал — так, что зачем выгружать всё библиотеку?!
L>А зачем это? Просто у меня есть своя библиотека (vlib) там много кода (в том числе и эксперементального) — оформлять и вычищать это нет времени — а вам эта куча мало что даст... Основные принципы работы с сообщениями я уже в флейме указал — так, что зачем выгружать всё библиотеку?!
Достаточно пары файлов касающихся окон — не беда если это прямо не будет компилиться,
просто чем больше кода — тем понятнее, конечно у каждого накоплено много своего
кода и обычно в виде *.lib — файла, если ты не хочешь все публиковать — будет интересно
посмотреть часть, касаюэуюся SWL-modified.
Итак в ветке были рассмотрены три основных архитектуры обработки сообщений
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) определить перегрузил ли пользователь функцию в дочернем классе. Это позволит неявно создавать карты сообщений и вкусить удобство от нормальных сигнатур обработчиков
Честно говоря это первая из реализаций, которая мне пришла в голову, но подумав я её отбросил по причинам:
1. Сообщений много — инстанциирование шаблона будет происходить каждый раз — это сделает процесс компиляции невыносимым...
2. Проблемма наследника от наследника: например диалог наследник окна. Но ведь от диалого тоже кто-то отнаследуется... В общем получается, что весь код — это шаблон (а-ля WTL) — это терпимо на не больших проектах, но становится невыносимым при укреплении проекта... А учитывая п.1 вообще нежизненно... Плюс отсутсвие нормального полиморфизма — иногда очень бесит. В общем стиль на любителя...