Рисование из другого потока без мерцания
От: ObKo  
Дата: 23.09.08 06:15
Оценка:
Есть некий поток в котором бесконечно выполняется:

Monitor::Enter(this);
Draw();
Monitor::Exit(this);


Draw():

G->Clear(Color::White);
//Дальше идет рисование фигур


G — Объект Graphics, полученый методом CreateGraphics() конрола.
Все рисуется нормально, только очень сильно мерцает.
Конрол самопальный, установка Style
ControlStyles::UserPaint | ControlStyles::AllPaintingInWmPaint | ControlStyles::DoubleBuffer

Не помогает.
Пробовал рисовать в битмап, потом выводить — сильно тормозит.

У кого какие есть мысли по этому поводу?
Re: Рисование из другого потока без мерцания
От: flenov www.hackishcode.com
Дата: 23.09.08 06:50
Оценка:
Попробуй переопределить OnPaintBackground и оставить его пустым. Это событие генерируется для прорисовки фона и закрашивает контрол цветом фона, а вот после этого ты уже рисуешь свое, поэтому и мерцание
Re: Рисование из другого потока без мерцания
От: _FRED_ Черногория
Дата: 23.09.08 06:57
Оценка:
Здравствуйте, ObKo, Вы писали:

OK>Есть некий поток в котором бесконечно выполняется:

OK>Monitor::Enter(this);
OK>Draw();
OK>Monitor::Exit(this);


Чем вызвана необходимость рисовать из другого потока? В какой момент времени вы это делаете? Обработка-то WM_PAINT происходит в основном потоке…
Как и в какой момент времени вы получаете Graphics? Как начинаете рисовать?

OK>Конрол самопальный, установка Style

OK>ControlStyles::UserPaint | ControlStyles::AllPaintingInWmPaint | ControlStyles::DoubleBuffer

OK>Не помогает.

Ещё бы!

OK>Пробовал рисовать в битмап, потом выводить — сильно тормозит.


Как рисовали? В отдельном потоке? А как потом "выводили"?

OK>У кого какие есть мысли по этому поводу?


Сначала надо разобраться, что же мешает рисовать в основном потоке?
Help will always be given at Hogwarts to those who ask for it.
Re[2]: Рисование из другого потока без мерцания
От: Аноним  
Дата: 23.09.08 06:58
Оценка:
Здравствуйте, flenov, Вы писали:

F>Попробуй переопределить OnPaintBackground и оставить его пустым. Это событие генерируется для прорисовки фона и закрашивает контрол цветом фона, а вот после этого ты уже рисуешь свое, поэтому и мерцание


Пробовал, не помогло....
Re[2]: Рисование из другого потока без мерцания
От: ObKo  
Дата: 23.09.08 07:03
Оценка:
Ок.
Программа просчитывает гравитационное взаимодействие двух и более тел. В дополнительном потоке просчитывается изменение координат и выводится результат на конрол.
Re[3]: Рисование из другого потока без мерцания
От: _FRED_ Черногория
Дата: 23.09.08 07:10
Оценка:
Здравствуйте, ObKo, Вы писали:

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


В смысле, расчёты долгие и каждый раз при отрисовке их делать тяжело?

Тогда делается так: отдельный поток рассчитывает данные и сообщает потоку GUI о том, что надо отрисоваться, например через SynchronizationContext. Поток GUI вызывает по наступлению этого события Invalidate, затем в обработчике OnPaint(…) по рассчитанным данным производится отрисовка. Остаётся только не забыть о синхронизации.
Help will always be given at Hogwarts to those who ask for it.
Re[2]: Рисование из другого потока без мерцания
От: Pavel Dvorkin Россия  
Дата: 23.09.08 07:52
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Сначала надо разобраться, что же мешает рисовать в основном потоке?


А, собственно говоря, что изменится от рисования в основном потоке ? Я вообще-то особенного криминала в рисовании в другом потоке не вижу — если, конечно, их не 10 и они не пытаются одновременно рисовать. . А так — пожалуйста. Если основной поток сейчас не рисует, а рисует другой — на здоровье. Здесь WM_PAINT и не пахнет.

Тут, похоже, иное. Что за самопальный контрол и не генерирует ли он WM_PAINT (InvalidateRect) каждую секунду или около того ? Вот если так — неудивительно. Один рисует, другой перерисовывает...
With best regards
Pavel Dvorkin
Re[3]: Рисование из другого потока без мерцания
От: _FRED_ Черногория
Дата: 23.09.08 07:55
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Тут, похоже, иное.


Фон мигает, естественно, не из-за этого.

А вот о практике или опыте рисования из разных потоков мне как-то раньше слышать ничего хорошего не прихдилось
Help will always be given at Hogwarts to those who ask for it.
Re[4]: Рисование из другого потока без мерцания
От: Pavel Dvorkin Россия  
Дата: 23.09.08 08:37
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>А вот о практике или опыте рисования из разных потоков мне как-то раньше слышать ничего хорошего не прихдилось


Хм. Можем мы рисовать из разных место одного потока ? Например, на WM_LBUTTONDOWN некое рисование делается тут же, без Invalidate. Естественно, надо куда-то добавить новую фигуру для возможного WM_PAINT, но в самой такой идее нет решительно ничего криминального. Более того, если WM_PAINT медленный, то это наилучшее решение. Да что там WM_LBUTTONDOWN — по таймеру ведь рисуют!

А теперь это же, но из другого потока. И что ? То же получение HDC окна , то же рисование. Честно говоря, не вижу разницы. Скажу больше — а как на десктопе рисуют ? Он-то уж точно не окно моего потока

Вот если 2 потока одновременно рисовать начнут — тогда точно ничего хорошего не выйдет
With best regards
Pavel Dvorkin
Re[5]: Рисование из другого потока без мерцания
От: Pavel Dvorkin Россия  
Дата: 23.09.08 09:38
Оценка:
Попробовал сейчас


   public partial class Form1 : Form
    {
        public bool stop;
        public void DoWork()
        {
            Graphics g = CreateGraphics();
            Pen pen = new Pen(Color.Blue);
            for (int i = 0; i < 10000; i++)
            {
                Thread.Sleep(10);
                if (stop)
                    return;
                g.DrawEllipse(pen, new Rectangle(0, 0, i, i));
            }
                
        }
        public Form1()
        {
            InitializeComponent();
            stop = false;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            ThreadStart threadDelegate = new ThreadStart(DoWork);
            Thread newThread = new Thread(threadDelegate);
            newThread.Start();
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            stop = true;
        }
    }


Ничего криминального не вижу и ничего не мигает. Естественно, при WM_PAINT рисунок не восстановится

Сорри за некорректные действия с переменной stop — лень было писать как следует.
With best regards
Pavel Dvorkin
Re[5]: Рисование из другого потока без мерцания
От: _FRED_ Черногория
Дата: 23.09.08 09:43
Оценка: 1 (1)
Здравствуйте, Pavel Dvorkin, Вы писали:

_FR>>А вот о практике или опыте рисования из разных потоков мне как-то раньше слышать ничего хорошего не прихдилось


PD>Хм. Можем мы рисовать из разных место одного потока?


Рисовать можем. Я хотел бы знать, что в этом может быть хорошего?

PD>Например, на WM_LBUTTONDOWN некое рисование делается тут же, без Invalidate.


Где такая техника применяется?

PD>Естественно, надо куда-то добавить новую фигуру для возможного WM_PAINT, но в самой такой идее нет решительно ничего криминального.


В я не вижу смысла, и потому она кажется криминальной: ну нарисуем мы что-нибудь, а потом свёрнём-развернём окно. И кто нам заново что-то отрисует? Что значит "куда-то добавить новую фигуру"? Можно нарисовать, например, в битмап, а из WM_PAINT рисовать уже с этого битмапа. Так рисование в битмап и рисование на окне — две разные вещи. В картинку можно рисовать не только из другого потока, но и из другого процесса, не важно. Рисовать же в окне нужно из WM_PAINT.

PD>Более того, если WM_PAINT медленный, то это наилучшее решение.


Что значит "WM_PAINT медленный" Я могу понять "GDI\GDI+ медленный". А скорость WM_PAINT такая, как мы её сделаем. Если рисовать быстро не получается, значит, надо что-то думать над тем, как бы ускорить WM_PAINT, а не над тем, где бы ещё порисовать. Конечно, если кто-то всё окно на каждый WM_PAINT перересовывает, то может быть медленно. Или инвалидирует, что бы хорошо не думать, так же всё целиком, то будет не быстро. Но ведь так можно и подругому: посчитал данные, потом посчитал, в какой части экрана они отображаются, и заинвалидировал этот региончик. В обработчике рисования (там известен квадрат, в котором надо рисовать) посчитал, где те данные, которые надо перерисовать, и перерисовал только их. Эти расчёты будут намного быстрее перерисовываний, дело за хорошо подобранной моделью данных.

PD>Да что там WM_LBUTTONDOWN — по таймеру ведь рисуют!


По таймеру рисуют так: в обработчике таймера рассчитывают данные. Затем рассчитывают регион, данные которого поменялись и инвалидируют регион. Всё: остальное сделает винда, выставив WM_PAINT. Скажу больше: именно под такую схему и подобраны (назначены) приоритеты сообщений WM_TIMER и WM_PAINT в потрохах винды. Отойти от этой схемы опять же не мешает ничто, кроме незнания и недоверия общепринятой практике.

PD>А теперь это же, но из другого потока. И что ? То же получение HDC окна , то же рисование. Честно говоря, не вижу разницы. Скажу больше — а как на десктопе рисуют ? Он-то уж точно не окно моего потока


Ага, это вот как раз и есть special case, который нужно применять очень осторожно на свой страх и риск (рисование на чёжом окне). Между прочим, что мешает от окна засабклассится и рисовать из его WM_PAINT? И, кстати, можно пример серьёзного (не поделки) приложения, которое рисует на десктопе?
Help will always be given at Hogwarts to those who ask for it.
Re[6]: Рисование из другого потока без мерцания
От: Pavel Dvorkin Россия  
Дата: 23.09.08 10:27
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Рисовать можем. Я хотел бы знать, что в этом может быть хорошего?


Я хотел бы знать, что в этом может быть плохого ?

PD>>Например, на WM_LBUTTONDOWN некое рисование делается тут же, без Invalidate.


_FR>Где такая техника применяется?


Сплошь и рядом в Win32. Банальный, заурядный прием, из учебника. GetDC и т.д.

_FR>В я не вижу смысла, и потому она кажется криминальной: ну нарисуем мы что-нибудь, а потом свёрнём-развернём окно. И кто нам заново что-то отрисует?


Обработчик WM_PAINT.

>Что значит "куда-то добавить новую фигуру"? Можно нарисовать, например, в битмап, а из WM_PAINT рисовать уже с этого битмапа.


Да.

>Так рисование в битмап и рисование на окне — две разные вещи. В картинку можно рисовать не только из другого потока, но и из другого процесса, не важно. Рисовать же в окне нужно из WM_PAINT.


Ну это далеко не так. По WM_PAINT не рисуют, а отрисовывают инвалидную область. А рисовать можно где угодно. Естественно, при этом надо принять меры, чтобы в случае появления инвалидной области обработчик WM_PAINT нарисовал то же, отрисовал, иными словами. Но это еще может быть, очень нескоро будет.


PD>>Более того, если WM_PAINT медленный, то это наилучшее решение.


_FR>Что значит "WM_PAINT медленный"


Обработчик медленный. Много рисовать, и без битовой карты.

> Я могу понять "GDI\GDI+ медленный". А скорость WM_PAINT такая, как мы её сделаем. Если рисовать быстро не получается, значит, надо что-то думать над тем, как бы ускорить WM_PAINT, а не над тем, где бы ещё порисовать.


Какое это имеет отношение к вопросу ?

>Конечно, если кто-то всё окно на каждый WM_PAINT перересовывает, то может быть медленно. Или инвалидирует, что бы хорошо не думать, так же всё целиком, то будет не быстро. Но ведь так можно и подругому: посчитал данные, потом посчитал, в какой части экрана они отображаются, и заинвалидировал этот региончик. В обработчике рисования (там известен квадрат, в котором надо рисовать) посчитал, где те данные, которые надо перерисовать, и перерисовал только их. Эти расчёты будут намного быстрее перерисовываний, дело за хорошо подобранной моделью данных.


Нет. Если мне надо новый эллипс, вписанный в окно, нарисовать, то никакие прямоугольнички не получатся. Тут проще именно эллипс напрямую нарисовать, а на битовую карту его тоже положить. Это быстрее будет, чем делать копирование всей битовой карты для каждого эллипса. Последнее оставим для WM_PAINT, там никуда не денешься, придется всю картинку выводить. А здесь лишь эллипс.



PD>>Да что там WM_LBUTTONDOWN — по таймеру ведь рисуют!


_FR>По таймеру рисуют так: в обработчике таймера рассчитывают данные. Затем рассчитывают регион, данные которого поменялись и инвалидируют регион. Всё: остальное сделает винда, выставив WM_PAINT.


Сделает. Только медленно это будет.


>Скажу больше: именно под такую схему и подобраны (назначены) приоритеты сообщений WM_TIMER и WM_PAINT в потрохах винды. Отойти от этой схемы опять же не мешает ничто, кроме незнания и недоверия общепринятой практике.


Ты просто, видимо, с этой методикой не знаком. Честное слово, вполне стандартная методика в Win32.


PD>>А теперь это же, но из другого потока. И что ? То же получение HDC окна , то же рисование. Честно говоря, не вижу разницы. Скажу больше — а как на десктопе рисуют ? Он-то уж точно не окно моего потока


_FR>Ага, это вот как раз и есть special case, который нужно применять очень осторожно на свой страх и риск (рисование на чёжом окне). Между прочим, что мешает от окна засабклассится и рисовать из его WM_PAINT?


Сабклассить можно только окна своего процесса. Или хук вешай.

>И, кстати, можно пример серьёзного (не поделки) приложения, которое рисует на десктопе?


Visual Studio при старте. И другие.
With best regards
Pavel Dvorkin
Re[6]: Рисование из другого потока без мерцания
От: ObKo  
Дата: 23.09.08 11:20
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Попробовал сейчас



PD>
PD>   public partial class Form1 : Form
PD>    {
PD>        public bool stop;
PD>        public void DoWork()
PD>        {
PD>            Graphics g = CreateGraphics();
PD>            Pen pen = new Pen(Color.Blue);
PD>            for (int i = 0; i < 10000; i++)
PD>            {
PD>                Thread.Sleep(10);
PD>                if (stop)
PD>                    return;
PD>                g.DrawEllipse(pen, new Rectangle(0, 0, i, i));
PD>            }
                
PD>        }
PD>        public Form1()
PD>        {
PD>            InitializeComponent();
PD>            stop = false;
PD>        }

PD>        private void button1_Click(object sender, EventArgs e)
PD>        {
PD>            ThreadStart threadDelegate = new ThreadStart(DoWork);
PD>            Thread newThread = new Thread(threadDelegate);
PD>            newThread.Start();
PD>        }

PD>        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
PD>        {
PD>            stop = true;
PD>        }
PD>    }
PD>


PD>Ничего криминального не вижу и ничего не мигает. Естественно, при WM_PAINT рисунок не восстановится


PD>Сорри за некорректные действия с переменной stop — лень было писать как следует.
Re[6]: Рисование из другого потока без мерцания
От: Аноним  
Дата: 23.09.08 11:22
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Попробовал сейчас


PD>Ничего криминального не вижу и ничего не мигает. Естественно, при WM_PAINT рисунок не восстановится


PD>Сорри за некорректные действия с переменной stop — лень было писать как следует.



В том и проблема, что мне нужно очищать перед перересовкой!
Re[7]: Рисование из другого потока без мерцания
От: MxKazan Португалия  
Дата: 23.09.08 11:36
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Здравствуйте, _FRED_, Вы писали:


_FR>>Рисовать можем. Я хотел бы знать, что в этом может быть хорошего?

PD>Я хотел бы знать, что в этом может быть плохого ?
Да вообще-т _FRED_ привел пример, что плохого. Никакой WM_PAINT ничего нам не отрисует, если мы банальным GetDC чего-то накалякаем из другого потока.
В любом случае, обращаться к контролам и их ресурсам рекомендуется только в том же потоке, где контрол создается.
Нарушать эту рекомендацию, значит вступать в противоречие с поведением ОС.

PD>>>Например, на WM_LBUTTONDOWN некое рисование делается тут же, без Invalidate.

_FR>>Где такая техника применяется?
PD>Сплошь и рядом в Win32. Банальный, заурядный прием, из учебника. GetDC и т.д.
Я правильно понимаю, что в этом случае в WM_PAINT и в WM_LBUTTONDOWN все-таки один и тот же код рисует?

_FR>>В я не вижу смысла, и потому она кажется криминальной: ну нарисуем мы что-нибудь, а потом свёрнём-развернём окно. И кто нам заново что-то отрисует?

PD>Обработчик WM_PAINT.
>>Что значит "куда-то добавить новую фигуру"? Можно нарисовать, например, в битмап, а из WM_PAINT рисовать уже с этого битмапа.
PD>Да.
>>Так рисование в битмап и рисование на окне — две разные вещи. В картинку можно рисовать не только из другого потока, но и из другого процесса, не важно. Рисовать же в окне нужно из WM_PAINT.

PD>Ну это далеко не так. По WM_PAINT не рисуют, а отрисовывают инвалидную область. А рисовать можно где угодно. Естественно, при этом надо принять меры, чтобы в случае появления инвалидной области обработчик WM_PAINT нарисовал то же, отрисовал, иными словами. Но это еще может быть, очень нескоро будет.

Я еще не пробовал, но вроде WPF от данной проблемы избавляет. Правда ни о каких WM_PAINT'ах, GetDC и пр. там речи не идет.


>>И, кстати, можно пример серьёзного (не поделки) приложения, которое рисует на десктопе?

PD>Visual Studio при старте. И другие.
Серьезно?
Re: Рисование из другого потока без мерцания
От: ObKo  
Дата: 23.09.08 11:46
Оценка:
Все, проблему решил с помощью OnPaint и Invalidate()
Re[7]: Рисование из другого потока без мерцания
От: _FRED_ Черногория
Дата: 23.09.08 12:37
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

_FR>>Рисовать можем. Я хотел бы знать, что в этом может быть хорошего?

PD>Я хотел бы знать, что в этом может быть плохого ?

Большие проблемы в поддержке.

PD>>>Например, на WM_LBUTTONDOWN некое рисование делается тут же, без Invalidate.

_FR>>Где такая техника применяется?
PD>Сплошь и рядом в Win32. Банальный, заурядный прием, из учебника. GetDC и т.д.

Какого учебника? Давайте конкретнее. А ещё лучше, на софт. это использующий.

_FR>>В я не вижу смысла, и потому она кажется криминальной: ну нарисуем мы что-нибудь, а потом свёрнём-развернём окно. И кто нам заново что-то отрисует?

PD>Обработчик WM_PAINT.
>>Что значит "куда-то добавить новую фигуру"? Можно нарисовать, например, в битмап, а из WM_PAINT рисовать уже с этого битмапа.
PD>Да.
>>Так рисование в битмап и рисование на окне — две разные вещи. В картинку можно рисовать не только из другого потока, но и из другого процесса, не важно. Рисовать же в окне нужно из WM_PAINT.
PD>Ну это далеко не так. По WM_PAINT не рисуют, а отрисовывают инвалидную область.

Извините, но вы выдумываете: покажите-ка мне где-либо в профессиональной литературе по данному вопросу термин "отрисовка" в контексте различия с "рисованием"?

PD>А рисовать можно где угодно. Естественно, при этом надо принять меры, чтобы в случае появления инвалидной области обработчик WM_PAINT нарисовал то же, отрисовал, иными словами. Но это еще может быть, очень нескоро будет.


Я же сам сказал — что рисовать можно что угодно и где угодно, но если это не будет сделано в WM_PAINT, то толку от этого нет. Рисование в картинку в любом потоке не отменяем рисование каринки в WM_PAINT.

PD>>>Более того, если WM_PAINT медленный, то это наилучшее решение.

_FR>>Что значит "WM_PAINT медленный"
PD>Обработчик медленный. Много рисовать, и без битовой карты.

Ага, а с битовой картой обработчик получается быстрым? Значит, я прав-таки, говоря, что скорость обработчика зависит от того, как его реализовать?

>>Конечно, если кто-то всё окно на каждый WM_PAINT перересовывает, то может быть медленно. Или инвалидирует, что бы хорошо не думать, так же всё целиком, то будет не быстро. Но ведь так можно и подругому: посчитал данные, потом посчитал, в какой части экрана они отображаются, и заинвалидировал этот региончик. В обработчике рисования (там известен квадрат, в котором надо рисовать) посчитал, где те данные, которые надо перерисовать, и перерисовал только их. Эти расчёты будут намного быстрее перерисовываний, дело за хорошо подобранной моделью данных.


PD>Нет. Если мне надо новый эллипс, вписанный в окно, нарисовать, то никакие прямоугольнички не получатся. Тут проще именно эллипс напрямую нарисовать, а на битовую карту его тоже положить. Это быстрее будет, чем делать копирование всей битовой карты для каждого эллипса. Последнее оставим для WM_PAINT, там никуда не денешься, придется всю картинку выводить. А здесь лишь эллипс.


А если у вас тысяса элипсов, то всю тысячу перерисовывать будете? Я бы не перересрвывал. еденица рисование — не пиксел, а примитив. До него и надо "округлять".

>>Скажу больше: именно под такую схему и подобраны (назначены) приоритеты сообщений WM_TIMER и WM_PAINT в потрохах винды. Отойти от этой схемы опять же не мешает ничто, кроме незнания и недоверия общепринятой практике.

PD>Ты просто, видимо, с этой методикой не знаком. Честное слово, вполне стандартная методика в Win32.

Возможно. Покажите-ка описание этой методики?

>>И, кстати, можно пример серьёзного (не поделки) приложения, которое рисует на десктопе?

PD>Visual Studio при старте.

Ага, а Spy++ запустить не пробовали?

Резюмируя: если вы знаете, что есть некая методика рисования не в обработчике WM_PAINT (именно рисования на окне, а не в буфере), то не могли бы дать мне с ней ознакомиться? Интересно, как следуя такой методике повышается скорость и появляются прочие бенефиты. Методика, о которой говорю я описана как в MSDN (Painting and Drawing), так и у Рихтера.
Help will always be given at Hogwarts to those who ask for it.
Re[8]: Рисование из другого потока без мерцания
От: Pavel Dvorkin Россия  
Дата: 23.09.08 12:47
Оценка:
Здравствуйте, MxKazan, Вы писали:

MK>Здравствуйте, Pavel Dvorkin, Вы писали:


PD>>Здравствуйте, _FRED_, Вы писали:


_FR>>>Рисовать можем. Я хотел бы знать, что в этом может быть хорошего?

PD>>Я хотел бы знать, что в этом может быть плохого ?
MK>Да вообще-т _FRED_ привел пример, что плохого. Никакой WM_PAINT ничего нам не отрисует, если мы банальным GetDC чего-то накалякаем из другого потока.

Слушай. я же ясно там написал, что надо обеспечить, чтобы по WM_PAINT отрисовывалось то же.

MK>В любом случае, обращаться к контролам и их ресурсам рекомендуется только в том же потоке, где контрол создается.

MK>Нарушать эту рекомендацию, значит вступать в противоречие с поведением ОС.

PD>>>>Например, на WM_LBUTTONDOWN некое рисование делается тут же, без Invalidate.

_FR>>>Где такая техника применяется?
PD>>Сплошь и рядом в Win32. Банальный, заурядный прием, из учебника. GetDC и т.д.
MK>Я правильно понимаю, что в этом случае в WM_PAINT и в WM_LBUTTONDOWN все-таки один и тот же код рисует?

Нет. Простейший пример, первое задание, что я даю студентам. По WM_LBUTTONDOWN рисовать прямоугольники, а по WM_RBUTTONDOWN эллипсы. С backbuffer они еще не знакомы, поэтому список фигур

2 варианта

1. Рисуем по WM_?BUTTONDOWN и добавляем в список. По WM_PAINT отрисовываем весь список.
2. По WM_?BUTTONDOWN добавляем в список и InvalidateRect

В первом случае рисуется только одна фигура на нажатие кнопки. Весь список будет отрисовываться только когда будет инвалидная область. А она, мб, еще не скоро появится.
Во втором случае рисуется весь список. Всегда.

При 10-100 фигурах разницы в скорости нет. При тысячах — есть.

Естественно, в дальнейшем я их знакомлю с offscreen и битовыми картами, так что список выкидывается.

Но, конечно, рисовать они должны так, чтобы все сошлось. То есть WM_PAINT должен отрисовать список по тем же координатам и т.д, что и все WM_?BUTTONDOWN, вместе взятые.

Честно говоря, удивлен, что это надо объяснять. Это стандартная методика, еще раз говорю. Одна из двух.

MK>Я еще не пробовал, но вроде WPF от данной проблемы избавляет. Правда ни о каких WM_PAINT'ах, GetDC и пр. там речи не идет.


WPF избавляет . Он от много избавляет, в том числе от знания базовых принципов Win32. Не обижайся


>>>И, кстати, можно пример серьёзного (не поделки) приложения, которое рисует на десктопе?

PD>>Visual Studio при старте. И другие.
MK>Серьезно?

Абсолютно. Приложения, которые выводят стартовую картинку, рисуют на десктопе. GetDC(NULL). Это тоже общеизвестно. Вот, пожалуйста

http://img.meta.ua/rsdnsearch/?q=%F0%E8%F1%EE%E2%E0%F2%FC+%E4%E5%F1%EA%F2%EE%EF&amp;mode=rank&amp;group=N

А, пардон, где им еще рисовать ? Окна-то своего еще нет.

И кстати, характерный эффект. Если картинка висит достаточно долго, и за это время ее успеет перекрыть и уйти откуда-то взявшееся постороннее окно, то вместо картинки мы видим порой белый прямоугольник. Замечал такое ? В обычном окне такого не бывает — на то WM_PAINT есть. А тут просто рисование.
With best regards
Pavel Dvorkin
Re[9]: Рисование из другого потока без мерцания
От: _FRED_ Черногория
Дата: 23.09.08 12:53
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Нет. Простейший пример, первое задание, что я даю студентам. По WM_LBUTTONDOWN рисовать прямоугольники, а по WM_RBUTTONDOWN эллипсы. С backbuffer они еще не знакомы, поэтому список фигур


А, помню я такую книжку по МФЦ: там тоже в графическом редакторе рисовали гужки по левой кнопке. Но только вот это же учебник был: в следующей главе кружки уже сохранялись и рисовались в WM_PAINT.

>>>>И, кстати, можно пример серьёзного (не поделки) приложения, которое рисует на десктопе?

PD>>>Visual Studio при старте. И другие.
MK>>Серьезно?
PD>Абсолютно. Приложения, которые выводят стартовую картинку, рисуют на десктопе. GetDC(NULL). Это тоже общеизвестно. Вот, пожалуйста
PD>http://img.meta.ua/rsdnsearch/?q=%F0%E8%F1%EE%E2%E0%F2%FC+%E4%E5%F1%EA%F2%EE%EF&amp;mode=rank&amp;group=N
PD>А, пардон, где им еще рисовать ? Окна-то своего еще нет.
PD>И кстати, характерный эффект. Если картинка висит достаточно долго, и за это время ее успеет перекрыть и уйти откуда-то взявшееся постороннее окно, то вместо картинки мы видим порой белый прямоугольник. Замечал такое ? В обычном окне такого не бывает — на то WM_PAINT есть. А тут просто рисование.

Только вот как объяснить то, что можно навести сверху чужое окно, потом убрать, и оно отрисуется-таки?
Help will always be given at Hogwarts to those who ask for it.
Re[9]: Рисование из другого потока без мерцания
От: MxKazan Португалия  
Дата: 23.09.08 13:11
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

Ну, повеселились и хватит...

PD>Здравствуйте, MxKazan, Вы писали:


MK>>Здравствуйте, Pavel Dvorkin, Вы писали:


PD>>>Здравствуйте, _FRED_, Вы писали:


_FR>>>>Рисовать можем. Я хотел бы знать, что в этом может быть хорошего?

PD>>>Я хотел бы знать, что в этом может быть плохого ?
MK>>Да вообще-т _FRED_ привел пример, что плохого. Никакой WM_PAINT ничего нам не отрисует, если мы банальным GetDC чего-то накалякаем из другого потока.
PD>Слушай. я же ясно там написал, что надо обеспечить, чтобы по WM_PAINT отрисовывалось то же.

MK>>В любом случае, обращаться к контролам и их ресурсам рекомендуется только в том же потоке, где контрол создается.

MK>>Нарушать эту рекомендацию, значит вступать в противоречие с поведением ОС.
PD>>>>>Например, на WM_LBUTTONDOWN некое рисование делается тут же, без Invalidate.
_FR>>>>Где такая техника применяется?
PD>>>Сплошь и рядом в Win32. Банальный, заурядный прием, из учебника. GetDC и т.д.
MK>>Я правильно понимаю, что в этом случае в WM_PAINT и в WM_LBUTTONDOWN все-таки один и тот же код рисует?
PD>Нет. Простейший пример, первое задание, что я даю студентам. По WM_LBUTTONDOWN рисовать прямоугольники, а по WM_RBUTTONDOWN эллипсы. С backbuffer они еще не знакомы, поэтому список фигур
PD>Честно говоря, удивлен, что это надо объяснять. Это стандартная методика, еще раз говорю. Одна из двух.
Хаааа. Клааасс.. Я так и думал, что будет нечто подобное приведено. Ага, ага... только правильнее скорее описать, что это не способ рисования в Win32, а вообще просто методика рисования. И мы здесь всё же знакомы с битовыми картами

MK>>Я еще не пробовал, но вроде WPF от данной проблемы избавляет. Правда ни о каких WM_PAINT'ах, GetDC и пр. там речи не идет.

PD>WPF избавляет . Он от много избавляет, в том числе от знания базовых принципов Win32. Не обижайся
Ага, не обижаюсь. Ведь на самом деле WPF использует прицнип в чем то схожий с тем, что приведен тобой выше На даёт мне забыть! Спасибо ей

>>>>И, кстати, можно пример серьёзного (не поделки) приложения, которое рисует на десктопе?

PD>>>Visual Studio при старте. И другие.
MK>>Серьезно?
PD>Абсолютно. Приложения, которые выводят стартовую картинку, рисуют на десктопе. GetDC(NULL). Это тоже общеизвестно. Вот, пожалуйста

PD>http://img.meta.ua/rsdnsearch/?q=%F0%E8%F1%EE%E2%E0%F2%FC+%E4%E5%F1%EA%F2%EE%EF&amp;mode=rank&amp;group=N

PD>А, пардон, где им еще рисовать ? Окна-то своего еще нет.

PD>И кстати, характерный эффект. Если картинка висит достаточно долго, и за это время ее успеет перекрыть и уйти откуда-то взявшееся постороннее окно, то вместо картинки мы видим порой белый прямоугольник. Замечал такое ? В обычном окне такого не бывает — на то WM_PAINT есть. А тут просто рисование.

Окно то там вполне себе есть. А нет там стандартного message loop'а, поэтому при показе картинки, окно отрисовывают "насильно", а дальше перерисовывать уже некому, потому что приложение занято запуском.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.