Почему сообщения рисования теряются даже после вызова UpdateWindow ()? - PullRequest
0 голосов
/ 05 февраля 2010

У меня есть приложение со следующей иерархией окон:

W1
  -W2  (Child of W1)
    - W3 ( Child of W2)

--------------------|
| W1|------------|  |
|   |W2 |------| |  |
|   |   |W3    | |  |
|   |   |------| |  |
|   |------------|  | 
|-------------------|

Когда в W2 происходит определенное событие, я звоню UpdateWindow:

W2::onCertainEvent()
{
        Invalidate(NULL);
        UpdateWindow();
}

Обработка OnPaint в W2 выглядит следующим образом:

   W2::onPaint()
  {
    //W2 logic goes here
    W3.Invalidate(NULL); //So that paint messages are given to W3
  }

Но иногда сообщения о рисовании теряются в W2. Хотя UpdateWindow вызывается, соответствующая OnPaint () не вызывается.

Если я добавлю свойство WS_EX_TRANSPARENT к W1 (родителю W2), то всегда получаются сообщения рисования @ W2.

Но проблема с добавлением флага WS_EX_TRANSPARENT состоит в том, что он создает много мерцания при изменении размера окна W1.

Мои вопросы: 1. Что не так в W2, что сообщения Paint теряются? 2. Почему добавление WS_EX_TRANSPARENT решает проблему рисования. 3. Как решить проблему мерцания, если используется флаг.

Спасибо

Ответы [ 2 ]

2 голосов
/ 05 февраля 2010

WM_PAINT "сообщения" на самом деле не являются сообщениями в обычном смысле этого слова. Они ведут себя как флаги в конце очереди сообщений каждого окна. Они не проходят через очередь сообщений потока, у них нет позиции в очереди сообщений Windows. Они генерируются, когда вы пытаетесь получить сообщение из очереди сообщений Windows, и других сообщений нет. В это время рассматриваются все различные недействительные данные и генерируется один или несколько (!) WM_PAINT.

В результате после W2::onCertainEvent() будет установлен флаг «Окно недействительно». Отсюда следует, что в конечном итоге будет вызван WM_PAINT, но сгенерированный тогда WM_PAINT не будет предназначен исключительно для этого «определенного события».

Историческая справка состоит в том, что вы не хотите тратить слишком много времени на рисование окна, если было много ожидающих сообщений, поскольку они, вероятно, в любом случае просто сделают ваше окно недействительным. Лучше сначала обновите свою модель, а затем делайте просмотр.

2 голосов
/ 05 февраля 2010

Flicker
Мерцание можно разрешить, передав WM_ERASEBKGND и убедившись, что оно ничего не делает. Мерцание может возникать, потому что каждое окно обрабатывает это сообщение перед каждой краской, чтобы стереть недопустимую область, используя свой цвет фона. Если вы обрабатываете это и ничего не делаете, стирание не происходит - просто убедитесь, что ваш обработчик WM_PAINT закрашивает всю недействительную область, или вы оставите артефакты из предыдущей краски.

Однако, в этом случае, я полагаю, мерцание происходит, потому что W1 рисует себя сначала, затем W2, затем W3 на каждой краске. Это говорит о том, что WS_EX_TRANSPARENT не является способом решения проблемы, с которой вы столкнулись.

Отсутствует WM_PAINT
Трудно понять, как это отследить. В .NET это происходит потому, что дочерние окна скрывают всю клиентскую область элемента управления, и поэтому сообщение рисования не распространяется, но я считаю, что это специфическое поведение .NET. Если бы вы могли предоставить пример проекта или пример кода, который демонстрирует проблему, это было бы большой помощью.

Тем временем вы можете удалить W3, чтобы W2 не был скрыт, и посмотреть, все ли сообщения рисования вернутся. Также обратите внимание, что CWnd::Invalidate не принимает значение NULL в качестве опции, оно принимает BOOL (TRUE или FALSE).

...