Здравствуйте ain, Вы писали:
ain>Интересно каким образом определять какие объекты надо перерисовывать, создавать отдельный список объектов попавших в недействительный регион или в каждый объект добавить свойство определяющие надо его перерисовывать или нет, мне кажется лучше первое ?
Вроде бы все так просто.
Предположим, перетаскивается фигура. Чтобы отобразить изменение, достаточно перерисовать объединение ее старого и нового региона. Т.е. элементарно посылаются ::InvalidateRect/::InvalidateRgn. К тебе приходят сообщения WM_PAINT с HDC на проставленным clipping-region. Заморачиваться с обсчетом пересечения этого региона с твоими фигурами не стоит — как показывает практика, GDI делает это даже быстрее.
Или я не правильно понял вопрос???
При использовании другого графического API, я не думаю, что такая модель там не будет поддерживаться.
Интересный момент появляется, когда удобно не инвалидировать некоторую область, а руками рисовать прямо на dc. Причем отрисовка должна происходить порциями. Заводится некоторый класс Updator, у которого два рода клиентов: рисующие агенты (они оставляют заявки на перерисовку) и представитель GDI (к которому идут запросы на инвалидацию).
Паттерн Команда здесь идеально подходит
struct IUpdateCommand
{
virtual void Apply (canvas&) const = 0;
virtual ~IUpdateCommand () {}
};
struct IUpdator
{
virtual void Apply (IUpdateCommand*) = 0;
};
struct UpdatorEvents
{
virtual void NeedDrawOver () = 0;
};
class Updator
: public IUpdator
{
public:
Updator (UpdatorEvents*);
void Apply (IUpdateCommand*);
void DrawOver (canvas &);
~Updator ();
private:
UpdatorEvents *_sink;
typedef std::vector<IUpdateCommand*> Queue;
typedef Queue::const_iterator QCI;
typedef Queue::iterator QI;
Queue _queue;
void _purge ();
};
Updator::Updator (UpdatorEvents *ev)
: _sink (ev)
{
}
void Updator::Apply (IUpdateCommand *cmd)
{
_queue.push_back (cmd);
_sink->NeedDrawOver ();
}
void Updator::DrawOver (canvas & c)
{
for (QCI it = _queue.begin (); it != _queue.end (); it++)
(*it)->Apply (c);
_purge ();
}
void Updator::_purge ()
{
for (QI it = _queue.begin (); it != _queue.end (); it++)
delete *it;
_queue.clear ();
}
Updator::~Updator ()
{
_purge ();
}
Я думаю, предназначение этого куска кода очевидно.