Подсказка отслеживания вызывает серый след мучительно медленной перерисовки

Позвольте мне сначала описать симптомы проблемы. Затем я приведу дополнительные факты и объясню свой вопрос.

Симптомы

Я написал собственный элемент управления Windows. Элемент управления рисует себя в ответ на сообщение WM_PAINT. Он также использует подсказки отслеживания (то есть функцию отслеживания TOOLTIPS_CLASS общего элемента управления).

Когда я перетаскиваю мышь по элементу управления, всплывающая подсказка хорошо следует за мышью. Проблема в том, что он оставляет после себя серую полосу. Эта полоса требует заметного количества времени для перерисовки — как вы можете видеть из прикрепленного изображения, я смог нажать PRNTSCRN и сделать снимок экрана до того, как элемент управления успел перерисовать себя.

Обратите внимание на серый след, где когда-то была всплывающая подсказка.

(Что еще более странно, так это то, что обработчик WM_PAINT, похоже, не запускался ни разу. Но обратите внимание, что код, который вызывает отслеживание всплывающей подсказки, находится в WM_MOUSEMOVE, и он, очевидно, отлично реагирует.)

Факты

  • Предположим, что ванильный C использует библиотеки Win32.
  • The WM_PAINT handler is actually very fast. The control has a number of features that require repainting the entire client area, and this is imperceptible to the user.
    • Indeed, some features run animations that repaint the whole client area at 15-24fps.
    • Он также довольно эффективен и не перерисовывает намного больше, чем прямоугольник обновления при любой перерисовке.
  • The WM_ERASEBKGND handler does nothing and simply returns 1.
    • I never erase the background, I simply paint over it.
  • The window has the following style bits set:
    • ws: WS_CHILD | WS_VISIBLE
    • ex: WS_EX_COMPOSITED
    • cs: CS_DBLCLKS
  • The parent window is a top-level window with the following style bits set:
    • ws: WS_TILEDWINDOW | WS_CLIPSIBLINGS | WS_VISIBLE
    • ex: WS_EX_WINDOWEDGE
    • cs: CS_REDRAW | CS_DBLCLKS
  • Фоновая кисть класса окна элемента управления — GetStockObject(NULL_BRUSH).
  • Единственный другой способ, который я нашел для создания такого же «следа», - это перетаскивание другого окна верхнего уровня поверх моего элемента управления. Та область, которая временно закрыта перетаскиваемым окном верхнего уровня, оставляет тот же след.
  • Предоставление классу окна элемента управления стиля CS_SAVEBITS, похоже, не имеет никакого значения. Я все еще получаю тот же заметный след медленных перекрасок.

Вопросы

  1. Почему я вообще получаю серый цвет, особенно если я установил CS_SAVEBITS?
  2. What can I do to make the grey go away?
    • Should I call UpdateWindow() each time I move the tooltip?
      • But this doesn't solve the issue of other top-level windows being dragged over top of my control.
    • Помощь!

person 0xbe5077ed    schedule 11.06.2013    source источник
comment
Проблема, по-видимому, заключается в том, что Windows отправляет сообщения WM_ERASEBKGND родительскому окну верхнего уровня, не отправляя соответствующее сообщение WM_PAINT дочернему окну управления. Если я нанесу вред обработчику WM_ERASEBKGND (возвращая 1 без каких-либо действий), проблема с отставанием отрисовки исчезнет, ​​но фон окна также не будет отрисовываться! Как я могу заставить Windows сказать дочернему элементу управления рисовать!?   -  person 0xbe5077ed    schedule 12.06.2013
comment
Примечание. Сначала я подумал, что проблема связана с описанной здесь проблемой региона обновления (см. заголовок Full Drag), но это решение не помогло.   -  person 0xbe5077ed    schedule 12.06.2013


Ответы (1)


Добавление бита стиля WS_CLIPCHILDREN в родительское окно устранило эту проблему.

По какой-то причине, когда окно частично скрыто, а затем открывается, ОС очень щедра на WM_ERASEBKGND сообщения и очень скупа на WM_PAINT сообщения. Происходило то, что родительский обработчик WM_ERASEBKGND стирал поверх моего контроля. Добавление WS_CLIPCHILDREN приводит к тому, что родительское окно обрезает его стирание.

Как ни странно, это решение сработало для моего элемента управления, который просто игнорирует сообщение WM_ERASEBKGND, но не работал для стандартных элементов управления BUTTON со стилем BS_GROUPBOX. Я ожидаю, что это из-за той же щедрой политики WM_ERASEBKGND. Стандартная кнопка управления, вероятно, добросовестно стирает свой фон при обработке этого сообщения, а затем тщетно ждет сообщения WM_PAINT.

person 0xbe5077ed    schedule 11.06.2013