GDI+ быстрый вывод
От: Аноним  
Дата: 13.12.10 22:01
Оценка:
Появилась задача сделать выделение областей мышкой на форме. пробовал множество способов — у всех (кроме 1) при каждом движении курсора всё (или только линии выделения) безбожно мигает. Да и не смог нагуглить как в GDI+/c# выводить графику в реал-тайме.

Пытался глянуть исходники Paint.NET (где всё реализовано плавно и красиво), но там всё так запутано что неделя на разбор потребуется.

Нужно обновлять вывод при каждом движении мыши если левая кнопка зажата.

Способ приведённый ниже не мерцает но есть потребность в очистке от прошлых линий.
gr.Clear(Color.Transparent);
делает всё чёррным. как решить?
        protected override void OnMouseMove(MouseEventArgs e)
        {
            m_LastMouseLocation = e.Location;

            if (m_InChoosing)
            {
                Graphics gr = this.CreateGraphics();
                Pen p = new Pen(new SolidBrush(Color.Black), 0.1f);

                gr.DrawLine(p, m_ChooseBegPos, new Point(m_ChooseBegPos.X, m_LastMouseLocation.Y));
                gr.DrawLine(p, m_ChooseBegPos, new Point(m_LastMouseLocation.X, m_ChooseBegPos.Y));

                gr.DrawLine(p, new Point(m_ChooseBegPos.X, m_LastMouseLocation.Y), m_LastMouseLocation);
                gr.DrawLine(p, new Point(m_LastMouseLocation.X, m_ChooseBegPos.Y), m_LastMouseLocation);

                //base.Invalidate(new Rectangle(m_LastMouseLocation, new Size(1, 1)), false);
            }

            base.OnMouseMove(e);
        }


P.S. в Paint.NET видел, используются методы со словом Transform в Graphics.
может тут как-то можно их применить?


14.12.10 07:22: Перенесено из '.NET'
Offtop - Re: GDI+ быстрый вывод
От: Holms США  
Дата: 13.12.10 22:10
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Пытался глянуть исходники Paint.NET (где всё реализовано плавно и красиво), но там всё так запутано что неделя на разбор потребуется.

Offtop, они же вроде больше не раздают исходники?
Не поделитесь на EUGEN . RATA @ GMAIL . COM
Спасибо
... << RSDN@Home 1.2.0 alpha 4 rev. 1476>>
The life is relative and reversible.
Re: Offtop - Re: GDI+ быстрый вывод
От: Аноним  
Дата: 13.12.10 22:20
Оценка:
Здравствуйте, Holms, Вы писали:

H>Здравствуйте, <Аноним>, Вы писали:


А>>Пытался глянуть исходники Paint.NET (где всё реализовано плавно и красиво), но там всё так запутано что неделя на разбор потребуется.

H>Offtop, они же вроде больше не раздают исходники?
H>Не поделитесь на EUGEN . RATA @ GMAIL . COM
H>Спасибо

Оу, не обратил внимания, там аж 2006 год.
1я ссылка в гугле.
Re[2]: Offtop - Re: GDI+ быстрый вывод
От: Holms США  
Дата: 13.12.10 23:36
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Оу, не обратил внимания, там аж 2006 год.

А>1я ссылка в гугле.
аа, ну это у меня то-же есть, думал что-то посвежее появилось
... << RSDN@Home 1.2.0 alpha 4 rev. 1476>>
The life is relative and reversible.
Re: GDI+ быстрый вывод
От: Sinix  
Дата: 14.12.10 01:13
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Появилась задача сделать выделение областей мышкой на форме. пробовал множество способов — у всех (кроме 1) при каждом движении курсора всё (или только линии выделения) безбожно мигает. Да и не смог нагуглить как в GDI+/c# выводить графику в реал-тайме.


А>Пытался глянуть исходники Paint.NET (где всё реализовано плавно и красиво), но там всё так запутано что неделя на разбор потребуется.

Там используется свой canvas с хитрой отрисовкой. Оверкилл.

А>Способ приведённый ниже не мерцает но есть потребность в очистке от прошлых линий.
gr.Clear(Color.Transparent);
делает всё чёррным. как решить?


Только извращениями аля
http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/f8e18389-730d-4679-a622-ca411eb5d7af

Можно (и нужно) перенести отрисовку в OnPaint (или как его там).
Re: GDI+ быстрый вывод
От: samius Япония http://sams-tricks.blogspot.com
Дата: 14.12.10 04:22
Оценка: +3
Здравствуйте, Аноним, Вы писали:

А>Появилась задача сделать выделение областей мышкой на форме. пробовал множество способов — у всех (кроме 1) при каждом движении курсора всё (или только линии выделения) безбожно мигает. Да и не смог нагуглить как в GDI+/c# выводить графику в реал-тайме.

От мигания избавляются установкой стилей где-нибудь в конструкторе (ЮзерКонтрола, формы)
SetStyle(ControlStyles.ResizeRedraw | ControlStyles.OptimizedDoubleBuffer, true);


А>Нужно обновлять вывод при каждом движении мыши если левая кнопка зажата.

При движении мыши следует вычислять минимальную область для обновления и посылать эту область в метод Invalidate. Никакого рисования в хэндлерах мыши. Рисование только в Paint.

А>Способ приведённый ниже не мерцает но есть потребность в очистке от прошлых линий.
gr.Clear(Color.Transparent);
делает всё чёррным. как решить?

За очистку фона перед OnPaint отвечает метод OnPaintBackground, который трогать не надо если не планируется сложный фон. Как правило хватает свойств BackColor/BakcgroundImage. Color.Transparent нельзя использовать в качестве цвета для очистки фона.

А>
А>        protected override void OnMouseMove(MouseEventArgs e)
А>        {
А>            m_LastMouseLocation = e.Location;

А>            if (m_InChoosing)
А>            {
А>                Graphics gr = this.CreateGraphics();
А>                Pen p = new Pen(new SolidBrush(Color.Black), 0.1f);

А>                gr.DrawLine(p, m_ChooseBegPos, new Point(m_ChooseBegPos.X, m_LastMouseLocation.Y));
А>                gr.DrawLine(p, m_ChooseBegPos, new Point(m_LastMouseLocation.X, m_ChooseBegPos.Y));

А>                gr.DrawLine(p, new Point(m_ChooseBegPos.X, m_LastMouseLocation.Y), m_LastMouseLocation);
А>                gr.DrawLine(p, new Point(m_LastMouseLocation.X, m_ChooseBegPos.Y), m_LastMouseLocation);

А>                //base.Invalidate(new Rectangle(m_LastMouseLocation, new Size(1, 1)), false);
А>            }

А>            base.OnMouseMove(e);
А>        }
А>

Все что связано с Graphics в событие Paint. Graphics не создавать, брать из аргументов события.

А>P.S. в Paint.NET видел, используются методы со словом Transform в Graphics.

А>может тут как-то можно их применить?
В борьбе с безбожным миганием эти методы не помогут.
Re: GDI+ быстрый вывод
От: vit_as Россия  
Дата: 14.12.10 06:04
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Появилась задача сделать выделение областей мышкой на форме. пробовал множество способов — у всех (кроме 1) при каждом движении курсора всё (или только линии выделения) безбожно мигает. Да и не смог нагуглить как в GDI+/c# выводить графику в реал-тайме.


А>Нужно обновлять вывод при каждом движении мыши если левая кнопка зажата.


Обновление графики только в событии Paint

Чтобы не было мерцания у контрола надо поставить свойство DoubleBuffered=true
Re[2]: GDI+ быстрый вывод
От: Pavel Dvorkin Россия  
Дата: 14.12.10 06:23
Оценка:
Здравствуйте, samius, Вы писали:

А>>Нужно обновлять вывод при каждом движении мыши если левая кнопка зажата.

S>При движении мыши следует вычислять минимальную область для обновления и посылать эту область в метод Invalidate. Никакого рисования в хэндлерах мыши. Рисование только в Paint.

Почему ? В Win API эта задача (резиновый контур, если я правильно понял) решается именно рисованием на WM_MOUSEMOVE, только с установкой SetROP2/R2_NOT или R2_XORPEN

А>>Способ приведённый ниже не мерцает но есть потребность в очистке от прошлых линий.
gr.Clear(Color.Transparent);
делает всё чёррным. как решить?


Установив SetROP2, очистку получишь автоматически. Просто будет стираться старый и рисоваться новй прямоугольник. И деже double buffer здесь не нужен, потому что нет инвалидации и не приходит WM_PAINT
With best regards
Pavel Dvorkin
Re[3]: GDI+ быстрый вывод
От: samius Япония http://sams-tricks.blogspot.com
Дата: 14.12.10 06:36
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

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


А>>>Нужно обновлять вывод при каждом движении мыши если левая кнопка зажата.

S>>При движении мыши следует вычислять минимальную область для обновления и посылать эту область в метод Invalidate. Никакого рисования в хэндлерах мыши. Рисование только в Paint.

PD>Почему ? В Win API эта задача (резиновый контур, если я правильно понял) решается именно рисованием на WM_MOUSEMOVE, только с установкой SetROP2/R2_NOT или R2_XORPEN


При наличии всплывающих окон грязь гарантируется

А>>>Способ приведённый ниже не мерцает но есть потребность в очистке от прошлых линий.
gr.Clear(Color.Transparent);
делает всё чёррным. как решить?


PD>Установив SetROP2, очистку получишь автоматически. Просто будет стираться старый и рисоваться новй прямоугольник. И деже double buffer здесь не нужен, потому что нет инвалидации и не приходит WM_PAINT


Инвертированные контуры — прошлый век. Навскидку не назову ни одну современную программу, что так делает. Ну и опять таки, что бы избежать грязи на рабочем столе, нужен double buffer. А раз он нужен, то нет смысла в инвертированных контурах, кроме как если они в ТЗ обозначены.
Re[4]: GDI+ быстрый вывод
От: Pavel Dvorkin Россия  
Дата: 14.12.10 06:48
Оценка:
Здравствуйте, samius, Вы писали:


PD>>Почему ? В Win API эта задача (резиновый контур, если я правильно понял) решается именно рисованием на WM_MOUSEMOVE, только с установкой SetROP2/R2_NOT или R2_XORPEN


S>При наличии всплывающих окон грязь гарантируется


Принять меры на случай WM_PAINT — перерисовать все

А>>>>Способ приведённый ниже не мерцает но есть потребность в очистке от прошлых линий.
gr.Clear(Color.Transparent);
делает всё чёррным. как решить?


PD>>Установив SetROP2, очистку получишь автоматически. Просто будет стираться старый и рисоваться новй прямоугольник. И деже double buffer здесь не нужен, потому что нет инвалидации и не приходит WM_PAINT


S>Инвертированные контуры — прошлый век. Навскидку не назову ни одну современную программу, что так делает. Ну и опять таки, что бы избежать грязи на рабочем столе, нужен double buffer. А раз он нужен, то нет смысла в инвертированных контурах, кроме как если они в ТЗ обозначены.


Что за инвертированный контур ? Тебя не устраивает вид линии, что ли, что она будет не одного цвета ?
With best regards
Pavel Dvorkin
Re[5]: GDI+ быстрый вывод
От: samius Япония http://sams-tricks.blogspot.com
Дата: 14.12.10 06:57
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

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



PD>>>Почему ? В Win API эта задача (резиновый контур, если я правильно понял) решается именно рисованием на WM_MOUSEMOVE, только с установкой SetROP2/R2_NOT или R2_XORPEN


S>>При наличии всплывающих окон грязь гарантируется


PD>Принять меры на случай WM_PAINT — перерисовать все

Без двойного буфера это будет заметно

S>>Инвертированные контуры — прошлый век. Навскидку не назову ни одну современную программу, что так делает. Ну и опять таки, что бы избежать грязи на рабочем столе, нужен double buffer. А раз он нужен, то нет смысла в инвертированных контурах, кроме как если они в ТЗ обозначены.


PD>Что за инвертированный контур ? Тебя не устраивает вид линии, что ли, что она будет не одного цвета ?


Меня — нет. Если я заказал рисовать красную линию, то она должна быть красная, а не контекстно серо-буро-малиновая в крапинку. Такое поведение сегодня — норма. MS Офис так рисует, OpenOffice так рисует, и даже Paint так рисует. Я последний раз видел R2_NOT в действии больше чем 10 лет назад.
Re[6]: GDI+ быстрый вывод
От: Pavel Dvorkin Россия  
Дата: 14.12.10 07:13
Оценка:
Здравствуйте, samius, Вы писали:

PD>>Принять меры на случай WM_PAINT — перерисовать все

S>Без двойного буфера это будет заметно

Да, но только при уходе всплывающего окна. Не беда.

S>>>Инвертированные контуры — прошлый век. Навскидку не назову ни одну современную программу, что так делает. Ну и опять таки, что бы избежать грязи на рабочем столе, нужен double buffer. А раз он нужен, то нет смысла в инвертированных контурах, кроме как если они в ТЗ обозначены.


PD>>Что за инвертированный контур ? Тебя не устраивает вид линии, что ли, что она будет не одного цвета ?


S>Меня — нет. Если я заказал рисовать красную линию, то она должна быть красная, а не контекстно серо-буро-малиновая в крапинку. Такое поведение сегодня — норма. MS Офис так рисует, OpenOffice так рисует, и даже Paint так рисует. Я последний раз видел R2_NOT в действии больше чем 10 лет назад.


Paint.net так не рисует.




Да и нельзя так. Что за выделение у тебя получится, если красным по красному ?

Ну а если тебе уж именно так хочется, могу предложить следующее решение. Снимаем с картинки 4 битмэпа толщиной в одну линию , то есть прямоугольник в виде битмэпов. Рисуем тут же линию твоего цвета. После передвижения мышки рисуем эти битмэпы обратно, снимаем новые. Можно даже и без битмэпов — просто снять значения с помощью GetPixel, сойдет
Главное — никакой перерисовки, никаких WM_PAINT.

Хотя... Еще одна идея.

Пусть Invalidate, пусть WM_PAINT, но только чтобы областей не было, только чтобы линии рисовались. Но если WM_PAINT дать 4 линии , то она объединит их в суммарный прямоугольник и ничего не получится. А вот если скармливать линии одна за одной и делать UpdateWindow каждый раз ?

InvalidateRect(верхняя линия прямоугольника);
UpdateWindow();
InvalidateRect(левая линия прямоугольника);
UpdateWindow();
и т.д.

По идее UpdateWindow заставит немедленно перерисовать именно эту линию и снять флаг инвалидности.
With best regards
Pavel Dvorkin
Re[7]: GDI+ быстрый вывод
От: samius Япония http://sams-tricks.blogspot.com
Дата: 14.12.10 07:49
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

S>>Меня — нет. Если я заказал рисовать красную линию, то она должна быть красная, а не контекстно серо-буро-малиновая в крапинку. Такое поведение сегодня — норма. MS Офис так рисует, OpenOffice так рисует, и даже Paint так рисует. Я последний раз видел R2_NOT в действии больше чем 10 лет назад.


PD>Paint.net так не рисует.

А попробуй нарисовать в нем линию, или прямоугольник

PD>Да и нельзя так. Что за выделение у тебя получится, если красным по красному ?

Да, тут соглашусь. Выделять лучше через R2. Но сомневаюсь, что это делается в мышинном событии, когда двойной буфер все-равно используется.

PD>Ну а если тебе уж именно так хочется, могу предложить следующее решение. Снимаем с картинки 4 битмэпа толщиной в одну линию , то есть прямоугольник в виде битмэпов. Рисуем тут же линию твоего цвета. После передвижения мышки рисуем эти битмэпы обратно, снимаем новые. Можно даже и без битмэпов — просто снять значения с помощью GetPixel, сойдет

PD>Главное — никакой перерисовки, никаких WM_PAINT.

Чем так страшен WM_PAINT, если есть двойной буфер? Более того, при интенсивной прорисовке содержимого без двойного буфера сложно обходиться. Я раньше занимался ГИС-ами, потому очень четко себе представляю ситуацию, когда сидишь минуту-другую ждешь окончания прорисовки, потом всплывает аська и все заново (без буфера-то).

PD>Хотя... Еще одна идея.


PD>Пусть Invalidate, пусть WM_PAINT, но только чтобы областей не было, только чтобы линии рисовались. Но если WM_PAINT дать 4 линии , то она объединит их в суммарный прямоугольник и ничего не получится. А вот если скармливать линии одна за одной и делать UpdateWindow каждый раз ?


PD>InvalidateRect(верхняя линия прямоугольника);

PD>UpdateWindow();
PD>InvalidateRect(левая линия прямоугольника);
PD>UpdateWindow();
PD>и т.д.

PD>По идее UpdateWindow заставит немедленно перерисовать именно эту линию и снять флаг инвалидности.


А ради чего собственно выжимать такты на ровном месте? Тебя не устраивает скорость BitBlt?
Более того, я даже не уверен, что посылка нескольких InvalidateRect-ов и UpdateWindow будет быстрее BitBlt.
Re[8]: GDI+ быстрый вывод
От: Pavel Dvorkin Россия  
Дата: 14.12.10 08:10
Оценка:
Здравствуйте, samius, Вы писали:

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


S>>>Меня — нет. Если я заказал рисовать красную линию, то она должна быть красная, а не контекстно серо-буро-малиновая в крапинку. Такое поведение сегодня — норма. MS Офис так рисует, OpenOffice так рисует, и даже Paint так рисует. Я последний раз видел R2_NOT в действии больше чем 10 лет назад.


PD>>Paint.net так не рисует.

S>А попробуй нарисовать в нем линию, или прямоугольник

Не понял. Я же только о контуре говорил.

PD>>Да и нельзя так. Что за выделение у тебя получится, если красным по красному ?

S>Да, тут соглашусь. Выделять лучше через R2. Но сомневаюсь, что это делается в мышинном событии, когда двойной буфер все-равно используется.

Что-то у меня не получается посмотреть Spy++ окно paint.net. А другого ничего нет. Попробуй.


S>Чем так страшен WM_PAINT, если есть двойной буфер?


На каждый мышкин чих перерисовывать прямоугольник ?

PD>>По идее UpdateWindow заставит немедленно перерисовать именно эту линию и снять флаг инвалидности.


S>А ради чего собственно выжимать такты на ровном месте? Тебя не устраивает скорость BitBlt?


На каждое мышкино передвижение ?

S>Более того, я даже не уверен, что посылка нескольких InvalidateRect-ов и UpdateWindow будет быстрее BitBlt.


Так InvalidateRect + UpdateWindow и приведут к BitBlt, только на 4 линии. Остально-то зачем перерисовывать ?
With best regards
Pavel Dvorkin
Re[7]: GDI+ быстрый вывод
От: Sinix  
Дата: 14.12.10 08:12
Оценка: +1
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>


Очевидно, старая версия. Текущая рисует мелкозернистую инверсную границу + полупрозрачный градиент поверх выделения.
Re[8]: GDI+ быстрый вывод
От: Pavel Dvorkin Россия  
Дата: 14.12.10 08:23
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Очевидно, старая версия. Текущая рисует мелкозернистую инверсную границу + полупрозрачный градиент поверх выделения.


Версия, идущая с Windows 7.
With best regards
Pavel Dvorkin
Re[9]: GDI+ быстрый вывод
От: samius Япония http://sams-tricks.blogspot.com
Дата: 14.12.10 08:24
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

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


PD>>>Paint.net так не рисует.

S>>А попробуй нарисовать в нем линию, или прямоугольник

PD>Не понял. Я же только о контуре говорил.

Да, подтверждаю версию Sinix-а. Инверсная граница, а содержимое слегка тонировано.

PD>Что-то у меня не получается посмотреть Spy++ окно paint.net. А другого ничего нет. Попробуй.

А что ты хочешь увидешь?

S>>Чем так страшен WM_PAINT, если есть двойной буфер?


PD>На каждый мышкин чих перерисовывать прямоугольник ?



PD>>>По идее UpdateWindow заставит немедленно перерисовать именно эту линию и снять флаг инвалидности.


S>>А ради чего собственно выжимать такты на ровном месте? Тебя не устраивает скорость BitBlt?


PD>На каждое мышкино передвижение ?


S>>Более того, я даже не уверен, что посылка нескольких InvalidateRect-ов и UpdateWindow будет быстрее BitBlt.


PD>Так InvalidateRect + UpdateWindow и приведут к BitBlt, только на 4 линии. Остально-то зачем перерисовывать ?

Просто что бы не мудрить.

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

Сделал в лоб WM_PAINT-ом на каждый мышиный чих. Т.е. не блит, а вся отрисовка всех глифов с доп информацией + блит из двойного буфера (от фликов). Ну и что бы ты думал? Все отлично рисуется, правда немного поджирается процессор. Меня это не беспокоит на столько что бы заниматься экономией перерисовки на уровне пикселов. И пока у меня нет отсечения по страницам. Т.е. на каждый мышиный чих рисуется весь документ, хоть и видна лишь его часть.

Можешь сказать что из-за таких как я тормозит виндовс, но мое мнение — одиночных блитов бояться не нужно в современных интерактивных приложениях.
В более менее сложных и многослойных могут работать и множественные блиты (2 и более буферов).
Re[9]: GDI+ быстрый вывод
От: Sinix  
Дата: 14.12.10 08:57
Оценка: +1
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Версия, идущая с Windows 7.

Не, там старый добрый MsPaint. Paint.Net из коробки бывает только в кулхацкерских сборках.
Re[10]: GDI+ быстрый вывод
От: Pavel Dvorkin Россия  
Дата: 14.12.10 09:09
Оценка:
Здравствуйте, samius, Вы писали:


PD>>Что-то у меня не получается посмотреть Spy++ окно paint.net. А другого ничего нет. Попробуй.

S>А что ты хочешь увидешь?

Приходит WM_PAINT при движении контура или нет.

S>>>Чем так страшен WM_PAINT, если есть двойной буфер?


PD>>На каждый мышкин чих перерисовывать прямоугольник ?

S>




PD>>Так InvalidateRect + UpdateWindow и приведут к BitBlt, только на 4 линии. Остально-то зачем перерисовывать ?

S>Просто что бы не мудрить.

Хм. Если размер контура будет во весь экран ? Тоже тормозить не будет ? На любой видеокарте ? На машине с процессором 5-7 летней давнсти ? Не уверен.

S>Вот смотри. Сейчас собираю прототип html смотрелки со спецвозможностями (т.е. существующие не устраивают). Для отладки мне удобно выводить некоторую посторонюю информацию о лэйаутинге на то же устройство (координаты мыши, атрибуты узлов, над чьими боксами я тащу мышь, границы боксов, и т.п.).


S>Сделал в лоб WM_PAINT-ом на каждый мышиный чих. Т.е. не блит, а вся отрисовка всех глифов с доп информацией + блит из двойного буфера (от фликов). Ну и что бы ты думал? Все отлично рисуется, правда немного поджирается процессор. Меня это не беспокоит на столько что бы заниматься экономией перерисовки на уровне пикселов. И пока у меня нет отсечения по страницам. Т.е. на каждый мышиный чих рисуется весь документ, хоть и видна лишь его часть.


S>Можешь сказать что из-за таких как я тормозит виндовс, но мое мнение — одиночных блитов бояться не нужно в современных интерактивных приложениях.

S>В более менее сложных и многослойных могут работать и множественные блиты (2 и более буферов).

Ладно, давай не будем еще и здесь флейм на эту тему устраивать.
With best regards
Pavel Dvorkin
Re[11]: GDI+ быстрый вывод
От: samius Япония http://sams-tricks.blogspot.com
Дата: 14.12.10 09:31
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

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



PD>>>Что-то у меня не получается посмотреть Spy++ окно paint.net. А другого ничего нет. Попробуй.

S>>А что ты хочешь увидешь?

PD>Приходит WM_PAINT при движении контура или нет.

Да, приходит, прчем вместе с WM_ERASEBKGND и даже без контура чисто на WM_MOUSEMOVE (даже не нажатый).
Полагаю, ты немедленно избавишься от этого софта?

PD>>>Так InvalidateRect + UpdateWindow и приведут к BitBlt, только на 4 линии. Остально-то зачем перерисовывать ?

S>>Просто что бы не мудрить.

PD>Хм. Если размер контура будет во весь экран ? Тоже тормозить не будет ? На любой видеокарте ? На машине с процессором 5-7 летней давнсти ? Не уверен.

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

PD>Ладно, давай не будем еще и здесь флейм на эту тему устраивать.

Ты начал. Уверен,что в большинстве современного софта проблемы производительности растут не из-за того что рисуются лишние пиксели в WM_PAINT.
Re[12]: GDI+ быстрый вывод
От: Pavel Dvorkin Россия  
Дата: 14.12.10 09:46
Оценка:
Здравствуйте, samius, Вы писали:

PD>>Приходит WM_PAINT при движении контура или нет.

S>Да, приходит, прчем вместе с WM_ERASEBKGND и даже без контура чисто на WM_MOUSEMOVE (даже не нажатый).
S>Полагаю, ты немедленно избавишься от этого софта?

Так мне же уже Sinix объяснил, что у меня его нет


PD>>Ладно, давай не будем еще и здесь флейм на эту тему устраивать.

S>Ты начал. Уверен,что в большинстве современного софта проблемы производительности растут не из-за того что рисуются лишние пиксели в WM_PAINT.

Я лишь свои рекомендации дал.
With best regards
Pavel Dvorkin
Re[2]: GDI+ быстрый вывод
От: Аноним  
Дата: 14.12.10 15:34
Оценка:
Здравствуйте, vit_as, Вы писали:


_>Обновление графики только в событии Paint


всё мерцает. если вне события то просто не очищаются старые линии.

_>Чтобы не было мерцания у контрола надо поставить свойство DoubleBuffered=true


Двойной буффер/Оптимизированый (SetStyle) или вместе абсолютно не дают результат. что с ними что без.
Re[2]: GDI+ быстрый вывод
От: Аноним  
Дата: 14.12.10 15:44
Оценка:
Здравствуйте, samius, Вы писали:

S>За очистку фона перед OnPaint отвечает метод OnPaintBackground, который трогать не надо если не планируется сложный фон. Как правило хватает свойств BackColor/BakcgroundImage. Color.Transparent нельзя использовать в качестве цвета для очистки фона.


хех если рисовать всё в OnPaint и сделать так:
        protected override void OnPaintBackground(PaintEventArgs e)
        {
            //base.OnPaintBackground(e);
        }


то тормоза отпадают но как уже понятно не очищается ничего.

base.OnPaintBackground слишком медленно работает
Re[3]: GDI+ быстрый вывод
От: samius Япония http://sams-tricks.blogspot.com
Дата: 14.12.10 16:49
Оценка:
Здравствуйте, Аноним, Вы писали:

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


А>хех если рисовать всё в OnPaint и сделать так:

А>
А>        protected override void OnPaintBackground(PaintEventArgs e)
А>        {
А>            //base.OnPaintBackground(e);
А>        }
А>


А>то тормоза отпадают но как уже понятно не очищается ничего.


А>base.OnPaintBackground слишком медленно работает


Взял форму из стандартного шаблона, внес изменения только в From1.cs (в дизайнере ничего не менял).
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        Paint += Form1_Paint;

        SetStyle(ControlStyles.ResizeRedraw, true);
        //SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
    }

    void Form1_Paint(object sender, PaintEventArgs e)
    {
        var rect = ClientRectangle;
        using (var pen = new Pen(Color.Red, 50))
            e.Graphics.DrawLine(pen, rect.Left, rect.Top, rect.Right, rect.Bottom);
    }
}


При запуске в винде с включенной опцией "Рисовать окно при перетаскивании", рисуется красная жирная линия с безбожным фликанием во время ресайза формы. Раскомментирование второй строчки SetStyle флики убирает.
Первая строчка SetStyle нужна для того что бы организовать автоматическую перерисовку при ресайзе формы.
Re: GDI+ быстрый вывод
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 14.12.10 20:58
Оценка: 3 (1) +1
Здравствуйте, Аноним, Вы писали:

А>Появилась задача сделать выделение областей мышкой на форме. пробовал множество способов — у всех (кроме 1) при каждом движении курсора всё (или только линии выделения) безбожно мигает. Да и не смог нагуглить как в GDI+/c# выводить графику в реал-тайме.


А>
А>        protected override void OnMouseMove(MouseEventArgs e)
А>        {
А>            m_LastMouseLocation = e.Location;

А>            if (m_InChoosing)
А>            {
А>                Graphics gr = this.CreateGraphics();
А>            }

А>            base.OnMouseMove(e);
А>        }
А>


В OnMouseMove ничего рисовать нельзя, иначе мерцание побороть не удастся. OnMouseMove должен устанвливать флаг обновления.

Контролу, на котором рисуешь, надо сделать вот это
            SetStyle(
                ControlStyles.AllPaintingInWmPaint /* | ControlStyles.DoubleBuffer*/| ControlStyles.UserPaint |
                ControlStyles.Opaque |
                ControlStyles.ResizeRedraw | ControlStyles.Selectable | ControlStyles.StandardClick, true);


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

Щас скажу страшное — для простоты кода, для подавления мерцания с артефактами вся отрисовка только OnPaint в оба битмапа и на главный Graphics !!! Это если ты конечно не игру пишешь и нет никаких тяжелых анимаций.

Основной битмап обновляется крайне редко — у меня где то раз в несколько секунд или даже минут.
Вспомогательный, для мышиных операций, обновляется каждый раз когда есть выделение мышом и тд.

        private void ReCreateMainDrawing()
        {
            if (_mainDrawing == null || _mainDrawing.Width != _drawingSize.Width ||
                _mainDrawing.Height != _drawingSize.Height)
            {
                if (_mainDrawing != null)
                    _mainDrawing.Dispose();
                _mainDrawing = new Bitmap(_drawingSize.Width, _drawingSize.Height, PixelFormat.Format32bppPArgb);
                _bRedraw = true;
            }
        }


Для вспомогательного примерно так же, но см. ниже — фоном для вспомогательного будет основной.


Итого, как происходит отрисовка

0. В OnMouseMove управляем флагами для перерисовки, что нужно обновлять.
1. в OnPaint проверяем, надо ли перерисовать статический контент, если надо — перерисовать основной битмап.
2. в OnPaint проверяем, надо ли перерисовать динамический контент, если надо — перерисовываем вспомогательный битмап, в качестве фона — основной битмап.
3. в конце отрисовываем или основной битмап или вспомогательный вот такой функцией

        protected void ApplyDrawing(Bitmap drawing, PaintEventArgs e, bool bFull)
        {
            if (bFull)
                e.Graphics.DrawImageUnscaled(drawing, 0, 0);
            else
                e.Graphics.DrawImage(drawing,
                                     e.ClipRectangle,
                                     e.ClipRectangle.Left,
                                     e.ClipRectangle.Top,
                                     e.ClipRectangle.Width,
                                     e.ClipRectangle.Height,
                                     GraphicsUnit.Pixel);
        }
Re[2]: GDI+ быстрый вывод
От: samius Япония http://sams-tricks.blogspot.com
Дата: 15.12.10 04:05
Оценка:
Здравствуйте, Ikemefula, Вы писали:

I>Итого, как происходит отрисовка


I>0. В OnMouseMove управляем флагами для перерисовки, что нужно обновлять.

I>1. в OnPaint проверяем, надо ли перерисовать статический контент, если надо — перерисовать основной битмап.
I>2. в OnPaint проверяем, надо ли перерисовать динамический контент, если надо — перерисовываем вспомогательный битмап, в качестве фона — основной битмап.
I>3. в конце отрисовываем или основной битмап или вспомогательный вот такой функцией

+1
Примерно к такой же схеме я пришел когда занимался ГИС-ом, где была и статическая информация (очень много, до нескольких секунд, или даже до минуты вывода GDI средствами) и динамическая, которая всегда должна быть актуальна, даже во время длительной отрисовки статической. Т.е. паузы в отображении динамической информации быть не должно.

Отличия были в том, что динамической информации было как-правило мало, и она не требовала буферизации. Но само-собой, выводилась не на DC контрола, а в итоговый буфер, где склеивались различные буфера, после чего этот буфер копировался на DC контрола.
А статических буферов было несколько. Так же был D3D рельеф ортогонального вида, который тоже приходилось буферизовывать, т.к. рисовался он немаленьким mesh-ем.

Для комфортных Pan/Zoom/ResizeWindow приходилось держать буферы значительно превышающие размеры окна. Это позволяло при изменениях параметров вида получать превью статической информации с помощью трансформаций буферов. После завершения выбора параметров вида (т.е. когда пользователь повозит мышкой и успокоится), начиналась фоновая отрисовка статических буферов с регулярным (раз 5-10 в секунду) выбросом нарендеренной статики на девайс контрола. Динамическая информация при этом обновлялась от 20и раз в секунду.

Специально для Павла: в 2004м году вся эта кухня позволяла комфортно работать на 4м пне с 256Мб оперативки с интегрированной графикой на 1м тогда фреймворке . Работало и на 3м пне. Но там даже винда сама по себе тормозила.
Ну и как-то на фоне всего происходящего, экономить на том что бы делать Invalidate по ребрам раббера, просто в голову не приходило.
Re: GDI+ быстрый вывод
От: dsorokin Россия  
Дата: 15.12.10 07:23
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Появилась задача сделать выделение областей мышкой на форме.


1. В обработчике OnMouseMove вызывать у контрола Invalidate с заданной областью. Чем меньше и точнее область, тем лучше.

2. В обработчике OnPaint перерисовать, но только то, что пересекается с PaintEventArgs.ClipRectangle. В этот прямоугольник как раз попадет та область, которую задал при вызове Invalidate (или череде вызовов). Чем она меньше, а также чем алгоритмически лучше происходит вычисление пересечения, тем быстрее отрисовка.

3. Мерцание убрать через двойную буферизацию у контрола (установить стили через SetStyle).

4. Рисовать напрямую через CreateGraphics — часто плохая идея. Но бывают исключения. Здесь не тот случай.

Нужно понимать, что Invalidate посылает сообщение, которое ставится в очередь потока GUI. Можно вызывать Invalidate многократно. Когда OnMouseMove отработает, поток GUI достанет из очереди все накопившиеся сообщения Invalidate и сделает вызов OnPaint. Таков основной цикл.

з.ы. Очень жаль, что в WPF и Silverlight совсем не так. Оттуда безбожно вырезали этот замечательный механизм, который позволял отрисовывать десятки тысяч разбросанных графических элементов одновременно. При хороших алгоритмах и доступной памяти можно было держать и сотни тысяч элементов или даже более. Но нужно было думать. Сейчас в WPF и Silverlight думает машина
Re[3]: GDI+ быстрый вывод
От: Pavel Dvorkin Россия  
Дата: 15.12.10 07:30
Оценка:
Здравствуйте, samius, Вы писали:

S>Специально для Павла: в 2004м году вся эта кухня позволяла комфортно работать на 4м пне с 256Мб оперативки с интегрированной графикой на 1м тогда фреймворке . Работало и на 3м пне. Но там даже винда сама по себе тормозила.


Надеюсь, ты понимаешь, что объем ОП здесь едва ли при чем, так как карта у тебя DDB (я полагаю), а поэтому хранится в видеопамяти (тоже полагаю) Тем более не имеет отношения к делу версия FW — здесь работает только подлежащий слой.

S>Ну и как-то на фоне всего происходящего, экономить на том что бы делать Invalidate по ребрам раббера, просто в голову не приходило.


Вольному воля.
With best regards
Pavel Dvorkin
Re[2]: GDI+ быстрый вывод
От: Pavel Dvorkin Россия  
Дата: 15.12.10 07:44
Оценка:
Здравствуйте, dsorokin, Вы писали:

D>Нужно понимать, что Invalidate посылает сообщение, которое ставится в очередь потока GUI. Можно вызывать Invalidate многократно. Когда OnMouseMove отработает, поток GUI достанет из очереди все накопившиеся сообщения Invalidate и сделает вызов OnPaint. Таков основной цикл.


Немного уточню. В очереди не будет нескольких сообщений. WM_PAINT в очереди всегда один (В действительности там флаг на все окна потока)
Если до его обработки добавляется новая инвалидная область, то Windows модифицирует параметры WM_PAINT, установив инвалидный прямоугольник как минимальный прямоугольник, включающий все ранее взятые и новый. Иными словами, если вначале инвалидить (0,0,100,100), а потом (200,200,300,300), то в OnPaint придет (0,0,300,300)


The QS_PAINT flag is handled differently. If a window created by the thread has an invalid region, the QS_PAINT flag is turned on. When the area occupied by all windows created by this thread becomes validated (usually by a call to ValidateRect, ValidateRegion, or BeginPaint), the QS_PAINT flag is turned off. This flag is turned off only when all windows created by the thread are validated. Calling GetMessage or PeekMessage has no effect on this wake flag.
With best regards
Pavel Dvorkin
Re[2]: GDI+ быстрый вывод
От: MxMsk Португалия  
Дата: 15.12.10 07:51
Оценка: +1
Здравствуйте, dsorokin, Вы писали:

D>з.ы. Очень жаль, что в WPF и Silverlight совсем не так. Оттуда безбожно вырезали этот замечательный механизм, который позволял отрисовывать десятки тысяч разбросанных графических элементов одновременно. При хороших алгоритмах и доступной памяти можно было держать и сотни тысяч элементов или даже более. Но нужно было думать. Сейчас в WPF и Silverlight думает машина

Какой механизм?
Re[4]: GDI+ быстрый вывод
От: samius Япония http://sams-tricks.blogspot.com
Дата: 15.12.10 08:11
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

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


S>>Специально для Павла: в 2004м году вся эта кухня позволяла комфортно работать на 4м пне с 256Мб оперативки с интегрированной графикой на 1м тогда фреймворке . Работало и на 3м пне. Но там даже винда сама по себе тормозила.


PD>Надеюсь, ты понимаешь, что объем ОП здесь едва ли при чем, так как карта у тебя DDB (я полагаю), а поэтому хранится в видеопамяти (тоже полагаю) Тем более не имеет отношения к делу версия FW — здесь работает только подлежащий слой.

Карта у меня была векторная. А буферами ведал D3D. Где он их хранил — без понятия, он сам рулит. При 8М видеопамяти выбору у него много не было.
Мне это было не важно, т.к. весь мой пайплайн со склейкой буферов рельефа, статических данных карты, динамических, а так же рабберов и других инструметов взаимодействия, в том числе собственные прозрачные и всплыающие от наезда мыши панели и скроллбары, мог выкидывать 20 кадров в секунду в окне, распахнутом на весь рабочий стол.

А ты говоришь — давайте экономить и посылать на перерисовку по одному ребру раббера. Я полагаю, ты хочешь что-бы видеокарта не перегрелась, делая лишний битблит?
Re[7]: GDI+ быстрый вывод
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 15.12.10 08:38
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Да, но только при уходе всплывающего окна. Не беда.


Это не беда, это отстойный рендеринг.

PD>Ну а если тебе уж именно так хочется, могу предложить следующее решение. Снимаем с картинки 4 битмэпа толщиной в одну линию , то есть прямоугольник в виде битмэпов. Рисуем тут же линию твоего цвета. После передвижения мышки рисуем эти битмэпы обратно, снимаем новые. Можно даже и без битмэпов — просто снять значения с помощью GetPixel, сойдет

PD>Главное — никакой перерисовки, никаких WM_PAINT.

Это тянет на хороший студенческий подход

PD>InvalidateRect(верхняя линия прямоугольника);

PD>UpdateWindow();
PD>InvalidateRect(левая линия прямоугольника);
PD>UpdateWindow();
PD>и т.д.
PD>По идее UpdateWindow заставит немедленно перерисовать именно эту линию и снять флаг инвалидности.

И это говорит человек, который знает! Винапи
Re[9]: GDI+ быстрый вывод
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 15.12.10 08:44
Оценка: :)
Здравствуйте, Pavel Dvorkin, Вы писали:

S>>Чем так страшен WM_PAINT, если есть двойной буфер?

PD>На каждый мышкин чих перерисовывать прямоугольник ?

Конечно. БОлее того — это и в OnMouseMove придется делать точно так же. Потому что прямоугольник этот динамически меняется.

S>>А ради чего собственно выжимать такты на ровном месте? Тебя не устраивает скорость BitBlt?

PD>На каждое мышкино передвижение ?

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

Кроме того, почти всегда обновляется только конкретный регион.
Re[5]: GDI+ быстрый вывод
От: Pavel Dvorkin Россия  
Дата: 15.12.10 08:46
Оценка:
Здравствуйте, samius, Вы писали:

S>Карта у меня была векторная. А буферами ведал D3D.


Это значит, что у тебя был не GDI. Direct3D по крайней мере тогда работал через DirectDraw.

S>А ты говоришь — давайте экономить и посылать на перерисовку по одному ребру раббера. Я полагаю, ты хочешь что-бы видеокарта не перегрелась, делая лишний битблит?


Мне просто совсем не по нутру, когда ради того, чтобы переисовать периметр прямоугольника, перерисовавают его весь. Ну вот такой у меня характер
With best regards
Pavel Dvorkin
Re[11]: GDI+ быстрый вывод
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 15.12.10 08:47
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Хм. Если размер контура будет во весь экран ? Тоже тормозить не будет ? На любой видеокарте ? На машине с процессором 5-7 летней давнсти ? Не уверен.


Даже на 10 летнем процессоре тормозов не будет

Техника старая, как GDI32.
Re[8]: GDI+ быстрый вывод
От: Pavel Dvorkin Россия  
Дата: 15.12.10 09:06
Оценка:
Здравствуйте, Ikemefula, Вы писали:

I>Это тянет на хороший студенческий подход


Ну мы не в КСВ, дорогой. Если есть аргументы, давай. Без болтовни.

PD>>InvalidateRect(верхняя линия прямоугольника);

PD>>UpdateWindow();
PD>>InvalidateRect(левая линия прямоугольника);
PD>>UpdateWindow();
PD>>и т.д.
PD>>По идее UpdateWindow заставит немедленно перерисовать именно эту линию и снять флаг инвалидности.

I>И это говорит человек, который знает! Винапи



UpdateWindow заставляет немедленно выполниться обработчик WM_PAINT. А пока что там всего лишь один инвалидный прямоугольник шириной в 1 пиксель. После OnPaint он будет зарисован и флаг QS_PAINT в очереди сообщений снят.

MSDN: (выделено мной)

The UpdateWindow function updates the client area of the specified window by sending a WM_PAINT message to the window if the window's update region is not empty. The function sends a WM_PAINT message directly to the window procedure of the specified window, bypassing the application queue. If the update region is empty, no message is sent.

Рихтер :


The QS_PAINT flag is handled differently. If a window created by the thread has an invalid region, the QS_PAINT flag is turned on. When the area occupied by all windows created by this thread becomes validated (usually by a call to ValidateRect, ValidateRegion, or BeginPaint), the QS_PAINT flag is turned off. This flag is turned off only when all windows created by the thread are validated. Calling GetMessage or PeekMessage has no effect on this wake flag.


Последующие InvalidateRect + UpdateWindow аналогичным образом сработают на оставшиеся 3 линии.

Контраргументы есть ?
With best regards
Pavel Dvorkin
Re[6]: GDI+ быстрый вывод
От: samius Япония http://sams-tricks.blogspot.com
Дата: 15.12.10 09:11
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

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


S>>Карта у меня была векторная. А буферами ведал D3D.


PD>Это значит, что у тебя был не GDI. Direct3D по крайней мере тогда работал через DirectDraw.

О, наверное в те времена DirectDraw умел работать с 3D и GDI?
Т.е. ты считаешь, когда у D3D буфера просишь создать Graphics (или на низком уровне получить HDC), то там на самом деле работает DirectDraw, а не GDI, когда ты отправляешь Graphics.DrawString?

PD>Мне просто совсем не по нутру, когда ради того, чтобы переисовать периметр прямоугольника, перерисовавают его весь. Ну вот такой у меня характер


Это трепетное отношение к premature optimization. А к характеру имеет отношение то, что ты хочешь что бы все остальные проявляли бы к ней такую же трепетность, а от студентов еще и требуешь (судя по всему). Извини, не хотел обсуждать твой характер, но тут такая провокация!
Re[10]: GDI+ быстрый вывод
От: Pavel Dvorkin Россия  
Дата: 15.12.10 09:16
Оценка:
Здравствуйте, Ikemefula, Вы писали:

PD>>На каждый мышкин чих перерисовывать прямоугольник ?


I>Конечно. Более того — это и в OnMouseMove придется делать точно так же. Потому что прямоугольник этот динамически меняется.


Конечно меняется.

На MouseMove при использовании механизма SetROP2 перерисовывают только рамку. Внутренность не перерисовывают, потому что незачем. Следующий mousemove приведет к тому же — вот и все.


case WM_MOUSEMOVE:
{
SetROP2
Select NULL_BRUSH в hdc
Select нужное перо в hdc
Rectangle по старому прямоугольнику (запомненному в первый раз по WM_LBUTTONDOWN, а потом измененному на mousemove, см. ниже
старый прямоугольник = новый прямоугольник (левый-верхний без изменения, правый-нижний из mousemove lParam)
Rectangle по новому прямоугольнику



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


Этим не процессор, а скорее всего видеокарта занимается.
With best regards
Pavel Dvorkin
Re[7]: GDI+ быстрый вывод
От: Pavel Dvorkin Россия  
Дата: 15.12.10 09:29
Оценка:
Здравствуйте, samius, Вы писали:

PD>>Это значит, что у тебя был не GDI. Direct3D по крайней мере тогда работал через DirectDraw.

S>О, наверное в те времена DirectDraw умел работать с 3D и GDI?



Наоборот. Direct3D работал через DirectDraw, а GDI сам по себе.
DirectDraw и GDI — это два разных механизма. Подробности у Фень Юаня, там об этом много.
GDI слишком медленный для игр, поэтому-то DirectDraw и был сделан.

S>Т.е. ты считаешь, когда у D3D буфера просишь создать Graphics (или на низком уровне получить HDC), то там на самом деле работает DirectDraw, а не GDI, когда ты отправляешь Graphics.DrawString?


HDC в DirectDraw получают иным способом, через directdraw surface

http://programmersforum.ru/showthread.php?p=432552

Ты просто, видимо, не в курсе всего этого.

PD>>Мне просто совсем не по нутру, когда ради того, чтобы переисовать периметр прямоугольника, перерисовавают его весь. Ну вот такой у меня характер


S>Это трепетное отношение к premature optimization. А к характеру имеет отношение то, что ты хочешь что бы все остальные проявляли бы к ней такую же трепетность, а от студентов еще и требуешь (судя по всему). Извини, не хотел обсуждать твой характер, но тут такая провокация!


Считай как хочешь. Я иначе не могу. Тебя никто не заставляет с этим соглашаться.
With best regards
Pavel Dvorkin
Re[11]: GDI+ быстрый вывод
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 15.12.10 10:16
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>На MouseMove при использовании механизма SetROP2 перерисовывают только рамку. Внутренность не перерисовывают, потому что незачем. Следующий mousemove приведет к тому же — вот и все.


А если надо будет чтото сложнее пустого прямоугольника рисовать ?
Re[9]: GDI+ быстрый вывод
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 15.12.10 10:16
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

I>>И это говорит человек, который знает! Винапи



PD>UpdateWindow заставляет немедленно выполниться обработчик WM_PAINT. А пока что там всего лишь один инвалидный прямоугольник шириной в 1 пиксель. После OnPaint он будет зарисован и флаг QS_PAINT в очереди сообщений снят.


...

PD>Последующие InvalidateRect + UpdateWindow аналогичным образом сработают на оставшиеся 3 линии.


PD>Контраргументы есть ?


Конечно. Сделай решение для общего случая — например прямоугольник с заливкой, маркерами, подписями к маркерам и ты поймешь почему такой способ не используется.
Re[12]: GDI+ быстрый вывод
От: Pavel Dvorkin Россия  
Дата: 15.12.10 10:35
Оценка:
Здравствуйте, Ikemefula, Вы писали:


I>А если надо будет чтото сложнее пустого прямоугольника рисовать ?


Речь в задаче ТС шла о резиновом контуре, только.
With best regards
Pavel Dvorkin
Re[10]: GDI+ быстрый вывод
От: Pavel Dvorkin Россия  
Дата: 15.12.10 10:37
Оценка:
Здравствуйте, Ikemefula, Вы писали:

PD>>Контраргументы есть ?


I>Конечно. Сделай решение для общего случая — например прямоугольник с заливкой, маркерами, подписями к маркерам и ты поймешь почему такой способ не используется.


Я спросил про контраргументы насчет моего якобы незнания винапи , то есть как работает InvalidateRect и UpdateWindow. Есть что по этому поводу сказать ?
With best regards
Pavel Dvorkin
Re[8]: GDI+ быстрый вывод
От: samius Япония http://sams-tricks.blogspot.com
Дата: 15.12.10 10:48
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

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


PD>>>Это значит, что у тебя был не GDI. Direct3D по крайней мере тогда работал через DirectDraw.

S>>О, наверное в те времена DirectDraw умел работать с 3D и GDI?

PD>HDC в DirectDraw получают иным способом, через directdraw surface


PD>http://programmersforum.ru/showthread.php?p=432552


PD>Ты просто, видимо, не в курсе всего этого.


Ты видимо не в курсе того, что если я делаю вызов DrawString по HDC, полученному у IDirect3DSurface, то работает именно GDI. Ты меня уговариваешь что GDI на самом деле не было и я не в курсе и заместо GDI работал DirectDraw. Если там DirectDraw где и учавствует — то только в процесе лока. GDI он собой никак не заменяет.
Re[13]: GDI+ быстрый вывод
От: samius Япония http://sams-tricks.blogspot.com
Дата: 15.12.10 10:49
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

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



I>>А если надо будет чтото сложнее пустого прямоугольника рисовать ?


PD>Речь в задаче ТС шла о резиновом контуре, только.


Речь в задаче ТС шла о том что бы убрать флики. R2_NOT резинкой флики полностью не исключить, даже если посылать на отрисовку отдельными гранями.
Re[9]: GDI+ быстрый вывод
От: Pavel Dvorkin Россия  
Дата: 15.12.10 11:18
Оценка:
Здравствуйте, samius, Вы писали:

S>Ты видимо не в курсе того, что если я делаю вызов DrawString по HDC, полученному у IDirect3DSurface, то работает именно GDI. Ты меня уговариваешь что GDI на самом деле не было и я не в курсе и заместо GDI работал DirectDraw. Если там DirectDraw где и учавствует — то только в процесе лока. GDI он собой никак не заменяет.


Я всего лишь утверждаю, что при работе D3D работа шла через DirectDraw, Использует ли внутри себя DirectDraw GDI или нет и где именно — это другой вопрос. Да, использует.
With best regards
Pavel Dvorkin
Re[14]: GDI+ быстрый вывод
От: Pavel Dvorkin Россия  
Дата: 15.12.10 11:21
Оценка:
Здравствуйте, samius, Вы писали:

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


I>>>А если надо будет чтото сложнее пустого прямоугольника рисовать ?


PD>>Речь в задаче ТС шла о резиновом контуре, только.


S>Речь в задаче ТС шла о том что бы убрать флики. R2_NOT резинкой флики полностью не исключить, даже если посылать на отрисовку отдельными гранями.


Флики мы с тобой уже обсудили, а здесь речь идет о другом. Просто Икемефулв решил мне задачу усложнить (что будет если...), ну я ему и ответил, что усложнение не рассматривается.
With best regards
Pavel Dvorkin
Re[10]: GDI+ быстрый вывод
От: samius Япония http://sams-tricks.blogspot.com
Дата: 15.12.10 11:23
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

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


S>>Ты видимо не в курсе того, что если я делаю вызов DrawString по HDC, полученному у IDirect3DSurface, то работает именно GDI. Ты меня уговариваешь что GDI на самом деле не было и я не в курсе и заместо GDI работал DirectDraw. Если там DirectDraw где и учавствует — то только в процесе лока. GDI он собой никак не заменяет.


PD>Я всего лишь утверждаю, что при работе D3D работа шла через DirectDraw, Использует ли внутри себя DirectDraw GDI или нет и где именно — это другой вопрос. Да, использует.


Я не пытаюсь с тобой спорить, использует ли DirectDraw GDI.
До этого ты утверждал что у меня не было GDI. Я настаиваю на том, что если делается вызов GDI, то работает GDI. А DirectDraw может оперировать лишь буферами и пикселформатами, в то время как кистями, шрифтами и т.п. он не владеет. Даже растровую развертку полигона сделать средствами DirectDraw не выйдет.
Re[11]: GDI+ быстрый вывод
От: Pavel Dvorkin Россия  
Дата: 15.12.10 11:43
Оценка:
Здравствуйте, samius, Вы писали:

S>Я не пытаюсь с тобой спорить, использует ли DirectDraw GDI.

S>До этого ты утверждал что у меня не было GDI.

Я утверждал, что ты работал через DirectDraw в том, что касается получения HDC. HDC у тебя не от GDI, а от DirectDraw. То есть это иной контекст. Используются ли при работе с ним средства от GDI — я не говорил вообще.
With best regards
Pavel Dvorkin
Re[12]: GDI+ быстрый вывод
От: samius Япония http://sams-tricks.blogspot.com
Дата: 15.12.10 12:09
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

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


S>>Я не пытаюсь с тобой спорить, использует ли DirectDraw GDI.

S>>До этого ты утверждал что у меня не было GDI.

PD>Я утверждал, что ты работал через DirectDraw в том, что касается получения HDC. HDC у тебя не от GDI, а от DirectDraw. То есть это иной контекст. Используются ли при работе с ним средства от GDI — я не говорил вообще.


Иной контекст твого утверждения, я полагаю?

Это значит, что у тебя был не GDI. Direct3D по крайней мере тогда работал через DirectDraw.

Потому как контекст устройства там именно от GDI.
Re[13]: GDI+ быстрый вывод
От: Pavel Dvorkin Россия  
Дата: 15.12.10 12:19
Оценка:
Здравствуйте, samius, Вы писали:

PD>>Я утверждал, что ты работал через DirectDraw в том, что касается получения HDC. HDC у тебя не от GDI, а от DirectDraw. То есть это иной контекст. Используются ли при работе с ним средства от GDI — я не говорил вообще.


S>Иной контекст твого утверждения, я полагаю?

S>

S>Это значит, что у тебя был не GDI. Direct3D по крайней мере тогда работал через DirectDraw.

S>Потому как контекст устройства там именно от GDI.

Что-то я уже вообще не понимаю. Ты согласился вроде, что там через DirectDraw идет ?

Ну вот тебе куски моего кода 10-летней давности




LPDIRECTDRAWSURFACE4        g_pDDSBack = NULL;   // DirectDraw back surface
...

    // Get a pointer to the back buffer
    ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
    hRet = g_pDDSPrimary->GetAttachedSurface(&ddscaps, &g_pDDSBack);
...
    g_pDDSBack->Blt(NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);

...

    if (g_pDDSBack->GetDC(&hdc) == DD_OK)
    {
        SetBkMode(hdc, TRANSPARENT);
            HPEN hP = CreatePen(PS_SOLID, 1, RGB(255, 0, 0));
            HPEN hPOld = (HPEN) SelectObject(hdc, hP);

            // Small window
            for(int i = - 3; i < 4; i++)
                for(int j = - 3; j < 4; j++)
                {
                    if(i + DebLineY < 0 || j + DebLineX < 0)
                        continue;
                    COLORREF cr = GetPixel(hdc, j + DebLineX, i + DebLineY);
                    for(int a = 0; a < 8; a++)
                        for(int b = 0; b < 8; b++)
                            SetPixel(hdc, 400 + j*9+b, 200 + i*9+a, cr);


Как видишь, для получения этого hdc используется хоть и GetDC, но от LPDIRECTDRAWSURFACE4. Что не мешает потом вызывать SelectObject и SetBkMode
With best regards
Pavel Dvorkin
Re[14]: GDI+ быстрый вывод
От: samius Япония http://sams-tricks.blogspot.com
Дата: 15.12.10 12:46
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

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


PD>>>Я утверждал, что ты работал через DirectDraw в том, что касается получения HDC. HDC у тебя не от GDI, а от DirectDraw. То есть это иной контекст. Используются ли при работе с ним средства от GDI — я не говорил вообще.


S>>Иной контекст твого утверждения, я полагаю?

S>>

S>>Это значит, что у тебя был не GDI. Direct3D по крайней мере тогда работал через DirectDraw.

S>>Потому как контекст устройства там именно от GDI.

PD>Что-то я уже вообще не понимаю. Ты согласился вроде, что там через DirectDraw идет ?

Через — это значит что DirectDraw вызывает Lock, заполняет некую структуру GDI, и возвращает HDC. Больше здесь DirectDraw ни за что не отвечает.

PD>Ну вот тебе куски моего кода 10-летней давности

PD>
PD>    if (g_pDDSBack->GetDC(&hdc) == DD_OK)
PD>    {
PD>        SetBkMode(hdc, TRANSPARENT);
PD>            HPEN hP = CreatePen(PS_SOLID, 1, RGB(255, 0, 0));
PD>            HPEN hPOld = (HPEN) SelectObject(hdc, hP);
PD>


PD>Как видишь, для получения этого hdc используется хоть и GetDC, но от LPDIRECTDRAWSURFACE4. Что не мешает потом вызывать SelectObject и SetBkMode


Не мешает лишь потому что DirectDraw корректно заполнил заголовок. Всю работу SelectObject и SetBkMode делает именно GDI.
Re[15]: GDI+ быстрый вывод
От: Pavel Dvorkin Россия  
Дата: 15.12.10 12:57
Оценка:
Здравствуйте, samius, Вы писали:

PD>>Как видишь, для получения этого hdc используется хоть и GetDC, но от LPDIRECTDRAWSURFACE4. Что не мешает потом вызывать SelectObject и SetBkMode


S>Не мешает лишь потому что DirectDraw корректно заполнил заголовок. Всю работу SelectObject и SetBkMode делает именно GDI.


А я спорю ? Делает GDI, делает. Я же всего-то сказал, что HDC ты получмшь он DD, и хотя он бесспорно HDC, но относится к поверхности, созданной иными средствами — DirectDraw. И блиттинг там свой —

STDMETHOD(Blt)(THIS_ LPRECT,LPDIRECTDRAWSURFACE, LPRECT,DWORD, LPDDBLTFX) PURE;



            hRes = g_pDDSCopy->Blt(&r, g_pDDSBack, &r, DDBLT_WAIT, NULL);
With best regards
Pavel Dvorkin
Re[16]: GDI+ быстрый вывод
От: samius Япония http://sams-tricks.blogspot.com
Дата: 15.12.10 13:12
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

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


PD>>>Как видишь, для получения этого hdc используется хоть и GetDC, но от LPDIRECTDRAWSURFACE4. Что не мешает потом вызывать SelectObject и SetBkMode


S>>Не мешает лишь потому что DirectDraw корректно заполнил заголовок. Всю работу SelectObject и SetBkMode делает именно GDI.


PD>А я спорю ? Делает GDI, делает.

Я думал что ты споришь с тем, что там работает GDI.

>Я же всего-то сказал, что HDC ты получмшь он DD, и хотя он бесспорно HDC, но относится к поверхности, созданной иными средствами — DirectDraw. И блиттинг там свой —

GDI как раз поровну, чем там делана поверхность, хоть пальцем.

PD> STDMETHOD(Blt)(THIS_ LPRECT,LPDIRECTDRAWSURFACE, LPRECT,DWORD, LPDDBLTFX) PURE;

Логично, что там блиттинг свой
Re[4]: GDI+ быстрый вывод
От: Аноним  
Дата: 15.12.10 13:16
Оценка:
Здравствуйте, samius, Вы писали:

S>Взял форму из стандартного шаблона, внес изменения только в From1.cs (в дизайнере ничего не менял).

S>
S>public partial class Form1 : Form
S>{
S>    public Form1()
S>    {
S>        InitializeComponent();
S>        Paint += Form1_Paint;

S>        SetStyle(ControlStyles.ResizeRedraw, true);
S>        //SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
S>    }

S>    void Form1_Paint(object sender, PaintEventArgs e)
S>    {
S>        var rect = ClientRectangle;
S>        using (var pen = new Pen(Color.Red, 50))
S>            e.Graphics.DrawLine(pen, rect.Left, rect.Top, rect.Right, rect.Bottom);
S>    }
S>}
S>


S>При запуске в винде с включенной опцией "Рисовать окно при перетаскивании", рисуется красная жирная линия с безбожным фликанием во время ресайза формы. Раскомментирование второй строчки SetStyle флики убирает.

S>Первая строчка SetStyle нужна для того что бы организовать автоматическую перерисовку при ресайзе формы.

А если так

public partial class TestForm : System.Windows.Forms.Form
    {
        Point m_ChooseBegPos;
        Point m_LastMouseLocation;
        bool m_InChoosing;

        public TestForm()
        {
            InitializeComponent();
            Paint += Form1_Paint;

            SetStyle(ControlStyles.ResizeRedraw, true);
            SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
        }

        void Form1_Paint(object sender, PaintEventArgs e) //или OnPaint(PaintEventArgs e) с вызовом base.OnPaint в конце
        {
            if(m_InChoosing)
            using (var p = new Pen(Color.Red, 5))
            {
                Graphics gr = e.Graphics;
                gr.DrawLine(p, m_ChooseBegPos, new Point(m_ChooseBegPos.X, m_LastMouseLocation.Y));
                gr.DrawLine(p, m_ChooseBegPos, new Point(m_LastMouseLocation.X, m_ChooseBegPos.Y));

                gr.DrawLine(p, new Point(m_ChooseBegPos.X, m_LastMouseLocation.Y), m_LastMouseLocation);
                gr.DrawLine(p, new Point(m_LastMouseLocation.X, m_ChooseBegPos.Y), m_LastMouseLocation);
            }

        }

        protected override void OnMouseDown(MouseEventArgs e)
        {
            m_ChooseBegPos = e.Location;
            m_InChoosing = true;

            base.OnMouseDown(e);
        }

        protected override void OnMouseUp(MouseEventArgs e)
        {
            m_InChoosing = false;

            Invalidate();
            base.OnMouseUp(e);
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            m_LastMouseLocation = e.Location;

            if (m_InChoosing)
            {
                Invalidate();
            }

            base.OnMouseMove(e);
        }
    }


то мерцает ещё особенно если форма на весь экран.
добавил
SetStyle(ControlStyles.AllPaintingInWmPaint, true);

Мерцания прекратились но всё ещё заметно как линии не успевают за курсором. в windows explorerе или любом графическом редакторе так сильно не отстают.
Re[17]: GDI+ быстрый вывод
От: Pavel Dvorkin Россия  
Дата: 15.12.10 13:22
Оценка:
Здравствуйте, samius, Вы писали:

S>Я думал что ты споришь с тем, что там работает GDI.


Да нет... В конце концов где там что в ядре в win32k.sys + драйвер видеокарты — черт разберется.

>>Я же всего-то сказал, что HDC ты получмшь он DD, и хотя он бесспорно HDC, но относится к поверхности, созданной иными средствами — DirectDraw. И блиттинг там свой —

S>GDI как раз поровну, чем там делана поверхность, хоть пальцем.

Верно, но свойства у этого HDC иные, недели у созданного через CreateCompatibleDC/GetDC, к примеру.

PD>> STDMETHOD(Blt)(THIS_ LPRECT,LPDIRECTDRAWSURFACE, LPRECT,DWORD, LPDDBLTFX) PURE;

S>Логично, что там блиттинг свой

Поэтому и быстрее. По крайней мере так пишут.
With best regards
Pavel Dvorkin
Re[11]: GDI+ быстрый вывод
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 15.12.10 13:27
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

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


PD>Этим не процессор, а скорее всего видеокарта занимается.


В том то и дело. А вот если ты начнешь свои примитивы херачить, то аппаратное ускорение поможет только в GDI32. GDI+ это уже софтверный рендеринг, какие то клочки используют акселерацию от GDI32.

Так что твои мега-алгоритмы рисовавния пустых прямоугольников вполне могут кушать _больше_ процессора, нежели в случае с битмапами.
Re[5]: GDI+ быстрый вывод
От: samius Япония http://sams-tricks.blogspot.com
Дата: 15.12.10 13:34
Оценка:
Здравствуйте, Аноним, Вы писали:

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


S>>Взял форму из стандартного шаблона, внес изменения только в From1.cs (в дизайнере ничего не менял).


S>>При запуске в винде с включенной опцией "Рисовать окно при перетаскивании", рисуется красная жирная линия с безбожным фликанием во время ресайза формы. Раскомментирование второй строчки SetStyle флики убирает.

S>>Первая строчка SetStyle нужна для того что бы организовать автоматическую перерисовку при ресайзе формы.

А>А если так


А>
А>public partial class TestForm : System.Windows.Forms.Form
А>

да, так моргает

А>то мерцает ещё особенно если форма на весь экран.

А>добавил
А>SetStyle(ControlStyles.AllPaintingInWmPaint, true);

А>Мерцания прекратились но всё ещё заметно как линии не успевают за курсором. в windows explorerе или любом графическом редакторе так сильно не отстают.

Открыл Paint, там резиновая R2Not рамка, как Павел советует. И отстает от курсора, но меньше. И моргает.
Открыл Paint.NET, там рамка с затемнением. Не моргает, но отстает от курсора сильнее.
Re[14]: GDI+ быстрый вывод
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 15.12.10 13:34
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:


    if (g_pDDSBack->GetDC(&hdc) == DD_OK)
    {
..
            // Small window
            for(int i = - 3; i < 4; i++)
                for(int j = - 3; j < 4; j++)
                {
                    if(i + DebLineY < 0 || j + DebLineX < 0)
                        continue;
                    COLORREF cr = GetPixel(hdc, j + DebLineX, i + DebLineY);
                    for(int a = 0; a < 8; a++)
                        for(int b = 0; b < 8; b++)
                            SetPixel(hdc, 400 + j*9+b, 200 + i*9+a, cr);


Ну и код, вложенность от 5 и выше и куча констант в коде Ты его один что ли писал ?
Re[6]: GDI+ быстрый вывод
От: Аноним  
Дата: 15.12.10 13:43
Оценка:
Здравствуйте, samius, Вы писали:

S>Открыл Paint, там резиновая R2Not рамка, как Павел советует. И отстает от курсора, но меньше. И моргает.

S>Открыл Paint.NET, там рамка с затемнением. Не моргает, но отстает от курсора сильнее.

Значит мне кажется что больше
Re[15]: GDI+ быстрый вывод
От: Pavel Dvorkin Россия  
Дата: 15.12.10 13:45
Оценка:
Здравствуйте, Ikemefula, Вы писали:

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



I>
I>    if (g_pDDSBack->GetDC(&hdc) == DD_OK)
I>    {
I>..
I>            // Small window
I>            for(int i = - 3; i < 4; i++)
I>                for(int j = - 3; j < 4; j++)
I>                {
I>                    if(i + DebLineY < 0 || j + DebLineX < 0)
I>                        continue;
I>                    COLORREF cr = GetPixel(hdc, j + DebLineX, i + DebLineY);
I>                    for(int a = 0; a < 8; a++)
I>                        for(int b = 0; b < 8; b++)
I>                            SetPixel(hdc, 400 + j*9+b, 200 + i*9+a, cr);

I>


I>Ну и код, вложенность от 5 и выше и куча констант в коде Ты его один что ли писал ?


Размеры циклов посмотри. В байте, видишь ли, 8 бит
With best regards
Pavel Dvorkin
Re[16]: GDI+ быстрый вывод
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 15.12.10 14:18
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

I>>
I>>    if (g_pDDSBack->GetDC(&hdc) == DD_OK)
I>>    {
I>>..
I>>            // Small window
I>>            for(int i = - 3; i < 4; i++)
I>>                for(int j = - 3; j < 4; j++)
I>>                {
I>>                    if(i + DebLineY < 0 || j + DebLineX < 0)
I>>                        continue;
I>>                    COLORREF cr = GetPixel(hdc, j + DebLineX, i + DebLineY);
I>>                    for(int a = 0; a < 8; a++)
I>>                        for(int b = 0; b < 8; b++)
I>>                            SetPixel(hdc, 400 + j*9+b, 200 + i*9+a, cr);

I>>


I>>Ну и код, вложенность от 5 и выше и куча констант в коде Ты его один что ли писал ?


PD>Размеры циклов посмотри. В байте, видишь ли, 8 бит


Интересный аргумент — в байте 8 бит и поэтому вложенность 5 и всякие константы это нормально
Re[17]: GDI+ быстрый вывод
От: Pavel Dvorkin Россия  
Дата: 15.12.10 14:31
Оценка:
Здравствуйте, Ikemefula, Вы писали:


I>Интересный аргумент — в байте 8 бит и поэтому вложенность 5 и всякие константы это нормально


Во-первых, не 5, а все же 4. Во-вторых, это тест (стану я сюда что-то иное постить!). В третьих, в байте 8 бит, а окно это под байт

А в четвертых, надоел.
With best regards
Pavel Dvorkin
Re[18]: GDI+ быстрый вывод
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 15.12.10 14:34
Оценка: :)
Здравствуйте, Pavel Dvorkin, Вы писали:

I>>Интересный аргумент — в байте 8 бит и поэтому вложенность 5 и всякие константы это нормально


PD>Во-первых, не 5, а все же 4.


5 = if + 4 for

В своем же коде не можешь вложенность посчитать А еще рассказываешь какие нынче плохие программисты.

>Во-вторых, это тест (стану я сюда что-то иное постить!). В третьих, в байте 8 бит, а окно это под байт


Для теста еще сгодится. А с байтом всетаки не ясно " 400 + j*9+b, 200 + i*9+a"
Re[6]: GDI+ быстрый вывод
От: Pavel Dvorkin Россия  
Дата: 16.12.10 07:03
Оценка:
Здравствуйте, samius, Вы писали:


А>>Мерцания прекратились но всё ещё заметно как линии не успевают за курсором. в windows explorerе или любом графическом редакторе так сильно не отстают.

S>Открыл Paint, там резиновая R2Not рамка, как Павел советует. И отстает от курсора, но меньше. И моргает.
S>Открыл Paint.NET, там рамка с затемнением. Не моргает, но отстает от курсора сильнее.

Вот здесь

http://files.rsdn.ru/187/BLOKOUT2.C

пример из Петцольда. Если можешь, попробуй его и скажи, мигает или нет и как насчет отставания курсора

Компилировать без Unicode. 1995 год, однако

P.S. В примере ошибка — неправильно берутся координаты при выходе курсора влево от окна или выше. Исправляется элементарно.
With best regards
Pavel Dvorkin
Re[7]: GDI+ быстрый вывод
От: samius Япония http://sams-tricks.blogspot.com
Дата: 16.12.10 07:17
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

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


S>>Открыл Paint, там резиновая R2Not рамка, как Павел советует. И отстает от курсора, но меньше. И моргает.

S>>Открыл Paint.NET, там рамка с затемнением. Не моргает, но отстает от курсора сильнее.

PD>Вот здесь


PD>http://files.rsdn.ru/187/BLOKOUT2.C


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

Скомпилил в best-optimization на GCC, запустил.
Мигает безбожно. Курсор отстает. Менее заметно, чем в Paint.NET, но не меньше чем в MS Paint. При быстром движении курсора легко отстает пикселов на 10-15. Машина не новая, но и не тормоз. C2D E6600 Win7.

PD>Компилировать без Unicode. 1995 год, однако


PD>P.S. В примере ошибка — неправильно берутся координаты при выходе курсора влево от окна или выше. Исправляется элементарно.

Оно мне надо? Своих хватает.
Re[8]: GDI+ быстрый вывод
От: Pavel Dvorkin Россия  
Дата: 16.12.10 12:51
Оценка:
Здравствуйте, samius, Вы писали:

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

S>Скомпилил в best-optimization на GCC, запустил.
S>Мигает безбожно. Курсор отстает. Менее заметно, чем в Paint.NET, но не меньше чем в MS Paint. При быстром движении курсора легко отстает пикселов на 10-15. Машина не новая, но и не тормоз. C2D E6600 Win7.

Любопытно.

На моей машине Phenom 955 / GeForce 9600 тоже мигает безбожно, более того, линии не всегда прорисовываются, так что иногда вместо видно только 3 стороны (конечно, тут же исправится, но заметно) А вот на работе старенький Athlon 4200/ GeForce 6150, что у нас в учебном классе стоит, не мигает, не отстает и вообще ведет себя замечательно.
Надо будет поисследовать.
With best regards
Pavel Dvorkin
Re[2]: GDI+ быстрый вывод
От: Silver_S Ниоткуда  
Дата: 19.12.10 09:41
Оценка:
Здравствуйте, Ikemefula, Вы писали:

I>В OnMouseMove ничего рисовать нельзя, иначе мерцание побороть не удастся. OnMouseMove должен устанвливать флаг обновления.


А можно поподробнее, какие проблемы с рисованием в OnMouse... ? Если AllPaintingInWmPaint, чем плохо в мышином обработчике делать синхронный Refresh() (или Invalidate+Update), вместо отложенного Invalidate ?
Re[3]: GDI+ быстрый вывод
От: Silver_S Ниоткуда  
Дата: 19.12.10 09:46
Оценка:
Здравствуйте, Silver_S, Вы писали:

Хотя если ты имел ввиду в мышином обработчике this.CreateGraphics() , то понятно.
Для вызовов из OnMouseMove, Update (а из него OnPaint) — с этим противопоказаний нет?
Re[3]: GDI+ быстрый вывод
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 19.12.10 12:02
Оценка: :)
Здравствуйте, Silver_S, Вы писали:

I>>В OnMouseMove ничего рисовать нельзя, иначе мерцание побороть не удастся. OnMouseMove должен устанвливать флаг обновления.


S_S> А можно поподробнее, какие проблемы с рисованием в OnMouse... ? Если AllPaintingInWmPaint, чем плохо в мышином обработчике делать синхронный Refresh()

(или Invalidate+Update), вместо отложенного Invalidate ?

Refresh это очень дорогое удовольствое, т.к. перерисовыват всю клиентскую область и все дочерние контролы. Update тоже недалеко ушел — это принудительный вызов OnPaint. В треде выше предлагалось вызывать не Update а рисовать прямо на экран. Во это и есть проблема.

Можно словить кое какие артефакты. Например Graphics, созданый явно руками, по мелочевке все равно отличается от того, что придет в OnPaint. Вроде все доступные проперти одинковые, а в отрисовке есть небольшая разница и это сильно раздражает. Ну и мерцание это отдельнй вопрос. Полностью подавить его можно только отрисовывая в битмап который в свою очередь нужно рисовать в OnPaint.

Кроме того, разделяя логику поведения и отрисовки код упрощается до безобразия. Но это конечно если ты понимаешь такие концепции как MVC
Re[4]: GDI+ быстрый вывод
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 19.12.10 12:11
Оценка:
Здравствуйте, Silver_S, Вы писали:

S_S>Хотя если ты имел ввиду в мышином обработчике this.CreateGraphics() , то понятно.

S_S>Для вызовов из OnMouseMove, Update (а из него OnPaint) — с этим противопоказаний нет?

Есть, это будет как минимум лишнее или же просядет перформанс. Напримерй в свей проге я такое просто не могу себе позволить
Не ясно, зачем тебе Update этот. Мне хватает одного Invalidate в OnMouseMove.
Re[4]: GDI+ быстрый вывод
От: Silver_S Ниоткуда  
Дата: 19.12.10 14:36
Оценка:
Здравствуйте, Ikemefula, Вы писали:

I>Можно словить кое какие артефакты. Например Graphics, созданый явно руками, по мелочевке все равно отличается от того, что придет в OnPaint. Вроде все доступные проперти одинковые, а в отрисовке есть небольшая разница и это сильно раздражает.


Что за разница? WinAPI.BeginPaint очищает фон и устанавливает Clip, в чем еще отличаи от WinAPI.GetDC, что-то связанное с фонтами и палитрами?
Если я рисую через Direct2D/3D а GDI используется только чтобы сбросить Bitmap на экран (иногда, если карточка слабая и надо обновить только маленький участок, поскольку DX10/11 умеет только все окно обновлять).
Какие-то проблемы могут быть? Не видел никаких артефактов.
Если код примерно такой:
            _Texture.CopySubresourceRegionFrom(0, 0, 0, 0, backBuffer, 0, BoxMake.From2D(rect));
            IntPtr hdc = GDIInterop.GetDC(_WindowHandle);
            var mapped = _Texture.Map(0, Staging_MapMode.Read, false);

            var rs = new SizeU(mapped.SystemMemoryPitch / 4, _CurSize.Height);
            GDIInterop.SetDIBitsToDevice_BGRX(hdc, mapped.SystemMemory ,rs, true,
                new Point2U(rect.Left, rect.Top), new RectU(0,0,rect.Width,rect.Height)
                );

            _Texture.Unmap(0);
            GDIInterop.ReleaseDC(_WindowHandle, hdc);


I>Кроме того, разделяя логику поведения и отрисовки код упрощается до безобразия.

Одно другому не мешает. Разделить всегда можно.
Re[5]: GDI+ быстрый вывод
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 19.12.10 14:47
Оценка:
Здравствуйте, Silver_S, Вы писали:

I>>Можно словить кое какие артефакты. Например Graphics, созданый явно руками, по мелочевке все равно отличается от того, что придет в OnPaint. Вроде все доступные проперти одинковые, а в отрисовке есть небольшая разница и это сильно раздражает.


S_S> Что за разница? WinAPI.BeginPaint очищает фон и устанавливает Clip, в чем еще отличаи от WinAPI.GetDC, что-то связанное с фонтами и палитрами?


Да, шрифты и палитры.

S_S> Если я рисую через Direct2D/3D а GDI используется только чтобы сбросить Bitmap на экран (иногда, если карточка слабая и надо обновить только маленький участок, поскольку DX10/11 умеет только все окно обновлять).

S_S> Какие-то проблемы могут быть? Не видел никаких артефактов.

Мало ли чего ты не видел Но если ты рисуешь чисто битмапы, то проблем быть не должно. Но вот зачем это делать в OnMouseMove — ума не приложу.

S_S> Если код примерно такой:


Код я скипнул, т.к. мне непонятны названия и операции.


I>>Кроме того, разделяя логику поведения и отрисовки код упрощается до безобразия.

S_S> Одно другому не мешает. Разделить всегда можно.

Ну да, все в одном обработчике и это называется разделение Если тебе нужно прорабатывать сложный бехевиор типа драг-дроп со всякими феньками и тд, то рисование в OnMouseMove просто невозможно отладить.
Re[5]: GDI+ быстрый вывод
От: Silver_S Ниоткуда  
Дата: 19.12.10 16:35
Оценка:
Здравствуйте, Ikemefula, Вы писали:

I>Есть, это будет как минимум лишнее или же просядет перформанс. Напримерй в свей проге я такое просто не могу себе позволить

I>Не ясно, зачем тебе Update этот. Мне хватает одного Invalidate в OnMouseMove.

Почему здесь экран не перерисовывается пока мышка не остановится? 10 секунд ждать обновления экрана это нормальный перфоманс?


 public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();            
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            SetStyle(ControlStyles.Opaque, true);
            SetStyle(ControlStyles.ResizeRedraw, true);
            SetStyle(ControlStyles.OptimizedDoubleBuffer,true);

        }       
        public Point p;
        private void Form1_MouseMove(object sender, MouseEventArgs e)
        {
            p = e.Location;
            System.Threading.Thread.Sleep(10);
            Invalidate();
            //Update();            
        }
        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            e.Graphics.Clear(Color.White);
            e.Graphics.DrawLine(Pens.Black, new Point(p.X, p.Y), new Point(p.X, p.Y + 100));
        }       
    }
Re[6]: GDI+ быстрый вывод
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 19.12.10 16:55
Оценка: +1
Здравствуйте, Silver_S, Вы писали:

I>>Не ясно, зачем тебе Update этот. Мне хватает одного Invalidate в OnMouseMove.


S_S>Почему здесь экран не перерисовывается пока мышка не остановится? 10 секунд ждать обновления экрана это нормальный перфоманс?


Ты прав, Update и Refresh хороши аккурат для Sleep в OnMouseMove.
Re[7]: GDI+ быстрый вывод
От: Silver_S Ниоткуда  
Дата: 20.12.10 05:02
Оценка:
Здравствуйте, Ikemefula, Вы писали:

I>Ты прав, Update и Refresh хороши аккурат для Sleep в OnMouseMove.


HitTesting от Sleep чем нибудь отличаются?
Ты предлагаешь делать(неявно) BeginPaint, перед HitTest и если не надо обновлять то return?
Да и где гарантии что перерисовка не станет залипать даже если OnMouseMove только флажок устанавливает.
И за счет чего должен перфоманс повыситься — за счет потери некоторых кадров (Inbalidate'ов) ?
Где гарантии что они будут теряться именно как надо?
По какому принципу теряются кадры при Invalidate не ясно, исходников нет, в документации это подробно не описано.
Зачем полагаться на такой скользкий функционал.
Re[8]: GDI+ быстрый вывод
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 20.12.10 08:48
Оценка:
Здравствуйте, Silver_S, Вы писали:

Не ясно, что у тебя за софтина с отрисовкой

S_S>HitTesting от Sleep чем нибудь отличаются?


Конечно. Правильно написаный хиттест много времени не отнимает. Проверено примерно на 100-200 тыс объектов.

S_S>Ты предлагаешь делать(неявно) BeginPaint, перед HitTest и если не надо обновлять то return?


Я этого не предлагаю Нужен хиттест — напиши его правильно.

S_S>Да и где гарантии что перерисовка не станет залипать даже если OnMouseMove только флажок устанавливает.


Перерисовка может замерзнуть, я про это писал. В своей проге например Hover пришлось отключить, потому что он влечет полную перерисовку в силу ряда причин.

S_S> И за счет чего должен перфоманс повыситься — за счет потери некоторых кадров (Inbalidate'ов) ?


Перформанс проседать не должен. Про повышение никто не говорил. Если тебе надо какие то клочки рисовать и насрать на побочные эффекты — рисуй где хочешь.

S_S>Где гарантии что они будут теряться именно как надо?


У тебя какая задача, что ты хочешь отрисовывать и какой хочешь бехевиор мышиный ?

S_S> По какому принципу теряются кадры при Invalidate не ясно, исходников нет, в документации это подробно не описано.


Какие еще выпадения кадров ?

S_S>Зачем полагаться на такой скользкий функционал.


Ты придумал какого то коня в вакууме. Я ведь вроде про русски написал :

"Это если ты конечно не игру пишешь и нет никаких тяжелых анимаций. Основной битмап обновляется крайне редко — у меня где то раз в несколько секунд или даже минут.
Вспомогательный, для мышиных операций, обновляется каждый раз когда есть выделение мышом и тд."

Функционал никакой не скользкий. Техника старая ка GDI32.
Re[9]: GDI+ быстрый вывод
От: Silver_S Ниоткуда  
Дата: 20.12.10 11:28
Оценка:
Здравствуйте, Ikemefula, Вы писали:

I>Какие еще выпадения кадров ?

Залипания. Когда не каждый MouseMove+Invalidate вызывает перерисовку, некоторые пропускаются.
Не вижу причин удалять Update, не уговоришь
Re[10]: GDI+ быстрый вывод
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 20.12.10 11:33
Оценка:
Здравствуйте, Silver_S, Вы писали:

I>>Какие еще выпадения кадров ?

S_S> Залипания. Когда не каждый MouseMove+Invalidate вызывает перерисовку, некоторые пропускаются.

В каком софте критичны эти кадры ?

S_S>Не вижу причин удалять Update, не уговоришь


Не удаляй, мне фиолетово чего у тебя в коде творится.
Re[11]: GDI+ быстрый вывод
От: Silver_S Ниоткуда  
Дата: 20.12.10 11:38
Оценка:
Здравствуйте, Ikemefula, Вы писали:

I>Не удаляй, мне фиолетово чего у тебя в коде творится.

Я привел пример когда вариант без Update может быть хуже.
Можешь привести пример когда с Update будет хуже? Я пока такого не видел.
Re[12]: GDI+ быстрый вывод
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 20.12.10 12:23
Оценка:
Здравствуйте, Silver_S, Вы писали:

I>>Не удаляй, мне фиолетово чего у тебя в коде творится.

S_S>Я привел пример когда вариант без Update может быть хуже.

Ты хорошо русский язык понимаешь ?

Ты хорошо понимаешь, что для разных приложений оптимальной будут разные схемы отрисовки ?

S_S>Можешь привести пример когда с Update будет хуже? Я пока такого не видел.


Ты много чего не видел вероятно. Если у тебя Invalidate вызывается исключительно в OnMouseMove и рисовать нужно мелочевку, то и ежу понятно, что в этом случае без разницы, как будет вызываться отрисовка — принудительно или нет. Дворкин привел хорший пример с отрисовкой четырех линий.

Своим Update ты только увеличиваешь частоту отрисовок, это в первую очередь ест перформанс. При этом нет никакой гарантии что твои кадры не будут пропадать.

Пример — надо отрисовывать чтото серьезное и Invalidate вызывается не только в OnMouseMove(бекграунд подгружается в фоне и тд). Получается не сильно приятная картина — от твоих Update никакого толку нет, т.к. все равно тоже самое надо отобразить обычным способм.

Второй пример — ты наводишь мышом на объект и он меняет стиль с Regular на Hovered. Убираешь мышь — стиль меняется на старый. Какой ректангл надо перерисовать ? Если ты можешь локализовать изменения, то только один объект. Если нет — перерисовывай всю сцену. Итого — Gdi+ сожрет все 100% ядра при движении мыша, потоу что аппаратного ускорения в Gdi+ почти что нет,

Спрошу еще раз, на всякий — ты хорошо русский язык понимаешь ?

Ты хорошо понимаешь, что для разных приложений оптимальной будут разные схемы отрисовки ?
Re[13]: GDI+ быстрый вывод
От: Silver_S Ниоткуда  
Дата: 20.12.10 13:36
Оценка:
Здравствуйте, Ikemefula, Вы писали:

I>Ты хорошо русский язык понимаешь ?

Намекаешь, что пытался на русском написать?

I>... Убираешь мышь — стиль меняется на старый. Какой ректангл надо перерисовать ? Если ты можешь локализовать изменения, то только один объект. Если нет — перерисовывай всю сцену.

Не понимаю как ректангл связан с отложенной перерисовкой.

I>... что для разных приложений оптимальной будут разные схемы отрисовки ?

Я про разные не спрашивал, а только про тот где не стоит Update вызывать.

Ладно. Все ясно.
Re[14]: GDI+ быстрый вывод
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 20.12.10 13:43
Оценка:
Здравствуйте, Silver_S, Вы писали:

I>>... Убираешь мышь — стиль меняется на старый. Какой ректангл надо перерисовать ? Если ты можешь локализовать изменения, то только один объект. Если нет — перерисовывай всю сцену.

S_S> Не понимаю как ректангл связан с отложенной перерисовкой.

Не понимаешь, зато советуешь именно этот способ. Неудивительно.
Re: GDI+ быстрый вывод
От: Undying Россия  
Дата: 21.12.10 09:59
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Появилась задача сделать выделение областей мышкой на форме. пробовал множество способов — у всех (кроме 1) при каждом движении курсора всё (или только линии выделения) безбожно мигает.


Вот такая панелька точно работает без мигания при отрисовке в обработчиках события OnPaint.

  public class VirtualPanel : Panel
  {
    public VirtualPanel() :
      base()
    {
      base.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint |
        ControlStyles.UserPaint, true);
    }
  }
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.