Конференция "WinAPI" » Как правильно отрисовать в WM_PAINT?
 
  • Тимохов (10.05.08 21:01) [0]
    Здравствуйте.

    Предпосылки моей проблемы
    Мне нужно написать компонент, который представляет собой грид (матрицу из примоугольников). Грид содерит только статическую информацию: никакого ввода.
    Одной из задач является создание возможности объединения ячеек по горизонтали. Ну т.е. как в Екселе.

    Как я делал
    Рассмотрим такой грид:

    -----
    |A|B|
    -----
    |C|D|
    -----


    Ячейки C и D объеденены. Т.е. ячейка C является головой объединения.
    Я перекрыл метод Paint и отрисовываю там свой грид.
    Я не обращаю внимание на регион клипинга, т.е. рисую во всей области компонента (отрисовка тривиальная и быстрая, незачем экономить).

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

    Проблемы
    Если в рассмотренном примере чем-то инвалидейтить область ячейки D (например, провести по ней другим окном), но не затронуть ячейку C, то ячейка D отрисовывается некорректно (либо мусор, либо затирается). Если же затронуть ячейку C, то и C и D коорректно перерисовываются.

    Почему такое получается я более-менее понимаю. Т.е. теорию вопроса про инвалидацию, валидаци, клипинг, WM_PAINT и пр. я знаю неплохо - сегодня прочел соответствующий раздел. Хотя, видимо, не до конца понимаю :)

    Вопросы
    1. Теоретический. Когда портится область ячейки D, то происходит инвалидация, потом WM_PAINT, причем регион клипиинга ограничивается только испорченной областью (т.е. не затрагивает ячейку С). Однако в WM_PAINT я делаю полную перерисовку области компонента и ячейки С (и как следствие области, занимаемой ячейкой В) в том числе. Почему не видно изменение ячейки D?
    2. Практический. Что делать?
  • Тимохов (10.05.08 21:57) [1]
    Немного ошибся в формулировке вопроса :(
    Надо так

    1. Теоретический. Когда портится область ячейки D, то происходит инвалидация, потом WM_PAINT, причем регион клипиинга ограничивается только испорченной областью (т.е. не затрагивает ячейку С). Однако в WM_PAINT я делаю полную перерисовку области компонента и ячейки С (и как следствие области, занимаемой ячейкой D) в том числе. Почему не видно изменение ячейки D?
  • {RASkov} © (10.05.08 22:17) [2]
    Написано слов много, а ведь в тумане все это... :(
    ВинАПИ, Грид, Ячейки.... почему, что, как?
  • Тимохов (10.05.08 22:54) [3]
    слуш, давай по делу. вопрос сформулирован вполне четко.
    объясни, если сможешь, поведение системы (ОС, в смысле) в указанном случае? почему так?

    я думаю, если пойму, то и проблему решу.
  • DVM © (10.05.08 23:48) [4]

    > Тимохов

    Ты можешь привести упрощенный вариант кода (желательно рабочий), на котором повторяется такой глюк? Без этого очень сложно судить о твоей проблеме (она скорее всего в твоем коде).
  • Тимохов (10.05.08 23:54) [5]

    > DVM ©   (10.05.08 23:48) [4]


    Ок, попробую.

    Еще раз перечитал Painting and drawing :) Я тоже начинаю приходить к мнению, что это в коде что-то такое есть, что не дает перерисовывать правильно.

    Вообще изначально код был взят года 4 назад из TCustomGrid. Путем жесткой кастрации он был преобразован к текущему виду. Работает уже года 2, но только сегодня я захотел сделать span. Вот и напоролся.

    В общем - попробую упростить код.
  • {RASkov} © (11.05.08 00:25) [6]
    > .... Почему не видно изменение ячейки D?

    > [3] Тимохов   (10.05.08 22:54)
    > вопрос сформулирован вполне четко.

    Согласен.... Вопрос более чем четкий.
    Тогда вот ответ: Потому что она не перерисовывается.)

    Сорри... но присоединяюсь к [4] посту...
    Грид - на то он и содержит ячейки и рисует их по отдельности... стала ячейка инвалидом - перерисовали ее только.... но если она рисуется в другом месте - то нужно это учитывать...

    Да видел я:

    > Однако в WM_PAINT я делаю полную перерисовку области компонента
    > и ячейки С

    ...тут как запрограммируешь, так и будет.... и ничего другого не бывает....
  • Германн © (11.05.08 00:50) [7]

    > Тимохов   (10.05.08 21:57) [1]
    >
    > Немного ошибся в формулировке вопроса :(
    > Надо так
    >
    > 1. Теоретический. Когда портится область ячейки D, то происходит
    > инвалидация, потом WM_PAINT, причем регион клипиинга ограничивается
    > только испорченной областью (т.е. не затрагивает ячейку
    > С). Однако в WM_PAINT я делаю полную перерисовку области
    > компонента и ячейки С (и как следствие области, занимаемой
    > ячейкой D) в том числе. Почему не видно изменение ячейки
    > D?
    >

    Что-то похожее тут на форуме как-то было. То бишь был вопрос про "объединение ячеек грида". Правда там была работа со стандартным гридом, а не с собственным компонентом.

    > Вообще изначально код был взят года 4 назад из TCustomGrid.
    >  Путем жесткой кастрации он был преобразован к текущему
    > виду.

    Вот в этом участке кода скорее всего собака и порылась.
  • тимохов (11.05.08 13:22) [8]
    Да, видимо, где-то в коде есть что-то :)
    Буду искать.

    Потому как вроде не должно себя вести так: WM_PAINT приходит, перерисовку я делаю полную, поэтому полюбому D должен перерисовать.
  • тимохов (11.05.08 13:58) [9]
    Прошу прощения, за шум. Я все понял.

    Если интересно, то я разобрался в чем дело.

    Мой компонент - это когда-то сильно кастрированный TCustomGrid.
    Вчера я в него дописывал объединения ячеек. Делал это в функции DrawCells в методе TCustomGrid.Paint.

    Алгоритм отрисовки я уже писал выше: видя, что ячейка С - голова объединения я присоединял к ней прямоугольник ячейки D. Потом отрисовывал C в новом прямоугольнике, а D вообще пропускал.

    В функции DrawCell есть проверка
    if (Where.Right > Where.Left) and RectVisible(Canvas.Handle, Where) then ...


    Собсно ошибка была моя в том, что у меня Where - это область исходной ячейки С, без присоединенной D. А т.к. RectVisible возвращает True, если Where внутри региона клипинга, то, если портить только D, то отрисовки C вообще не было. Отсюда и мусор в ячейке D, так как ее область вообще не отрисовывалась.

    В общем я во всем разобрался. Никаких чудес.

    ЗЫ
    Блин, в голову не могло, что RectVisible имеет какое-то отношение к клипингу. Назвали бы ее что-ли как-то удачней :)
 
Конференция "WinAPI" » Как правильно отрисовать в WM_PAINT?
Есть новые Нет новых   [134433   +22][b:0][p:0.001]