События на окраске (недействительные), изменяющие порядок выполнения после периода нормальной работы (время выполнения) - PullRequest
3 голосов
/ 11 апреля 2010

У меня есть 3 графика данных, которые нарисованы через их события рисования. Когда у меня есть данные, которые мне нужно вставить в график, я вызываю команду controls invalidate ().

Событие рисования первого элемента управления фактически создает буфер растровых изображений для двух других графиков, чтобы избежать повторения длинного цикла.

Таким образом, команды аннулирования находятся в определенном порядке (1,2,3). Это работает хорошо, однако, когда графические данные достигают конца окна графика (PictureBox), где данные обычно начинают прокручиваться, события рисования начинают срабатывать в неправильном порядке (2,3,1).

кто-нибудь сталкивался с этим раньше? почему это может происходить?

Ответы [ 2 ]

5 голосов
/ 11 апреля 2010

Измените свой код таким образом, чтобы перед вызовом Invalidate для любого из трех элементов управления вы создали один общий буфер растровых изображений (предположительно в качестве статического члена вашего класса управления) и , а затем вызов Invalidate на каждом из элементов управления. В событии Paint элемента управления вы можете использовать статический буфер растрового изображения, и не имеет значения, в каком порядке запускаются события Paint.

Когда вы вызываете Invalidate для элемента управления, вы в основном говорите ОС отправить сообщение WM_PAINT этому элементу управления. Поскольку это сообщение Windows, оно гарантированно будет доставлено, когда Windows сможет это сделать. В вашем случае они обычно доставляются в полученном заказе, но иногда их просто не будет.

Еще одна вещь, которую следует учитывать в вашем коде: когда вы помещаете относительно сложный код рисования в обработчик событий Paint вашего элемента управления (или внутри метода, вызываемого непосредственно из обработчика события Paint), этот код будет выполняться всякий раз, когда элемент управления аннулирован по любой причине , что означает, что код будет запускаться при вызове Invalidate, но он также будет запускаться всякий раз, когда над элементом управления будет перетаскиваться другое окно.

Для сложной, трудоемкой графики всегда лучше выполнять сложный рендеринг на скрытом буфере (Bitmap или невидимом PictureBox или чем-либо еще), а затем в событии элемента управления Paint сделать простое скопировать из скрытого буфера в видимое окно (используя Graphics.DrawImage или BitBlt или любое другое).

Этот подход также позволяет избежать мерцания, если вы добавите второй буфер между буфером, на котором вы рисуете, и видимым окном (отсюда и «двойная буферизация»). После завершения рисования в главном буфере вы копируете его во второй буфер. В событии элемента управления Paint вы копируете из второго буфера в видимое окно.

3 голосов
/ 11 апреля 2010

Поскольку при вызове Invalidate() в элементе управления по существу запрашивается операционная система для планирования элемента управления для перерисовки, нет гарантии, что это будет сделано в определенном порядке.

Поскольку вы пытаетесь вызвать Invalidate() в определенном порядке, я предполагаю, что у вас есть один метод, который делает это. Вы можете добавить код непосредственно перед этими вызовами, чтобы нарисовать буфер растрового изображения, который затем используется недействительными элементами управления. Я не знаю, может ли это когда-либо произойти, но это также дает вам свободу не аннулировать элемент управления, когда его данные не изменяются. Кроме того, элементы управления могут быть аннулированы в любое время. Например, перемещение формы по элементу управления 1 делает ее недействительной, и в текущих настройках пересчитайте растровое изображение буфера, пока это не требуется. Таким образом, вы должны отделить эту функцию.

...