Re[4]: Использование паттерна Decorator
От: Anton V. Kolotaev  
Дата: 07.10.02 07:48
Оценка:
Здравствуйте 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 ();
    }


Я думаю, предназначение этого куска кода очевидно.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.