Как можно ускорить кастомную отрисовку в WinForms?
От: Gepard_vvk  
Дата: 25.04.14 07:32
Оценка:
Работаю на WinForms приложением, в котором нужно реализовать проверку правописания.

Для перерисовки формы использую перехват Windows message.

        /// <summary>
        /// Processes Windows messages.
        /// </summary>
        /// <param name="msg">
        /// A Windows Message object.
        /// </param>
        protected override void WndProc(ref Message msg)
        {
            switch (msg.Msg)
            {
                case WM_PAINT:
                    Invalidate();
                    base.WndProc(ref msg);

                    if (IsSpellingAutoEnabled)
                    {
                        CustomPaint();
                    }

                    break;

            ...

                default:
                    base.WndProc(ref msg);
                    break;
            }
        }



Метод CustomPaint() выглядит так:
private void CustomPaint()
        {
            Bitmap tempBitmap;
            Graphics bufferGraphics;

            tempBitmap = new Bitmap(Width, Height);
            bufferGraphics = Graphics.FromImage(tempBitmap);
            bufferGraphics.Clip = new Region(ClientRectangle);

            _textBoxGraphics = CreateGraphics();
            bufferGraphics.Clear(Color.Transparent);

            foreach (var wordStartIndex in UnderlinedSections.Keys)
            {
                UnderlineWords(wordStartIndex, bufferGraphics);
            }

            _textBoxGraphics.DrawImageUnscaled(tempBitmap, 0, 0);
        }


В UnderlineWords в буфер добавляются линии, которые нужно нарисовать с пом. такого метода:
private void DrawWave(Graphics bufferGraphics, Point startOfLine, Point endOfLine)
        {
            startOfLine.Y--;
            en
            // kvv: Определяем цвет линий подчеркивания.dOfLine.Y--;

            var pen = Pens.Red;

            if ((endOfLine.X - startOfLine.X) >= 4)
            {
                var points = new ArrayList();
                for (int i = startOfLine.X; i <= (endOfLine.X - 2); i += 4)
                {
                    points.Add(new Point(i, startOfLine.Y));
                    points.Add(new Point(i + 2, startOfLine.Y + 2));
                }

                var p = (Point[])points.ToArray(typeof(Point));
                bufferGraphics.DrawLines(pen, p);
            }
        }


При работе этого кода на тексте размером больше 500 символов начинаются сильные тормоза и подвисания приложения. Как можно от этого избавиться? В какую сторону копать?
Re: Как можно ускорить кастомную отрисовку в WinForms?
От: btn1  
Дата: 25.04.14 16:30
Оценка:
Здравствуйте, Gepard_vvk, Вы писали:

G_>Работаю на WinForms приложением, в котором нужно реализовать проверку правописания.


G_>Для перерисовки формы использую перехват Windows message.


Интересно, а причём тут правописание (в текстовом контроле же, да?) и форма? Не у TextBox ли должна быть отрисовка?

G_> protected override void WndProc(ref Message msg)


А переопределить OnPaint — не?

G_> switch (msg.Msg)

G_> {
G_> case WM_PAINT:
G_> Invalidate();

А зачем в _рисовании_ нужно ещё раз делать изображение контрола invalid??

G_> bufferGraphics = Graphics.FromImage(tempBitmap);


Мои тесты с "ручным буфером" показали ужасный результат — всё стало ещё медленнее. Не знаю почему, мож какие "оптимизации" Проверьте, что "прямой" метод работает медленнее.

G_>private void DrawWave(Graphics bufferGraphics, Point startOfLine, Point endOfLine)

G_> for (int i = startOfLine.X; i <= (endOfLine.X — 2); i += 4)
G_> {
G_> points.Add(new Point(i, startOfLine.Y));
G_> points.Add(new Point(i + 2, startOfLine.Y + 2));

Не многовато точек для такой функции? Почему не использовать ОДНУ линию подо всем словом? "червячок" — это же не must have? Можно сделать пунктир. На крайняк — перо из картинки.
Re: Как можно ускорить кастомную отрисовку в WinForms?
От: VladFein США  
Дата: 25.04.14 16:36
Оценка:
Здравствуйте, Gepard_vvk, Вы писали:

G_>Работаю на WinForms приложением, в котором нужно реализовать проверку правописания.


G_>Для перерисовки формы использую перехват Windows message.


G_>При работе этого кода на тексте размером больше 500 символов начинаются сильные тормоза и подвисания приложения. Как можно от этого избавиться? В какую сторону копать?


Не понятно, почему правильнописание надо проверять в WM_PAINT?
Re[2]: Как можно ускорить кастомную отрисовку в WinForms?
От: Gepard_vvk  
Дата: 28.04.14 08:54
Оценка:
Здравствуйте, btn1, Вы писали:

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


G_>>Работаю на WinForms приложением, в котором нужно реализовать проверку правописания.


G_>>Для перерисовки формы использую перехват Windows message.


B>Интересно, а причём тут правописание (в текстовом контроле же, да?) и форма? Не у TextBox ли должна быть отрисовка?


G_>> protected override void WndProc(ref Message msg)


B>А переопределить OnPaint — не?


G_>> switch (msg.Msg)

G_>> {
G_>> case WM_PAINT:
G_>> Invalidate();

B>А зачем в _рисовании_ нужно ещё раз делать изображение контрола invalid??


G_>> bufferGraphics = Graphics.FromImage(tempBitmap);


B>Мои тесты с "ручным буфером" показали ужасный результат — всё стало ещё медленнее. Не знаю почему, мож какие "оптимизации" Проверьте, что "прямой" метод работает медленнее.


G_>>private void DrawWave(Graphics bufferGraphics, Point startOfLine, Point endOfLine)

G_>> for (int i = startOfLine.X; i <= (endOfLine.X — 2); i += 4)
G_>> {
G_>> points.Add(new Point(i, startOfLine.Y));
G_>> points.Add(new Point(i + 2, startOfLine.Y + 2));

B>Не многовато точек для такой функции? Почему не использовать ОДНУ линию подо всем словом? "червячок" — это же не must have? Можно сделать пунктир. На крайняк — перо из картинки.

1. Если убрать Invalidate(), то подчеркивания, естественно, будут рисоваться не корректно: при скроле, изменении масштабирования, при вставке нового текста — линии будут отрисовываться не сразу, что не допустимо.
2. Подчеркивание нужно именно волнистой линией, никак иначе.
Re[2]: Как можно ускорить кастомную отрисовку в WinForms?
От: Gepard_vvk  
Дата: 28.04.14 08:57
Оценка:
Здравствуйте, VladFein, Вы писали:

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


G_>>Работаю на WinForms приложением, в котором нужно реализовать проверку правописания.


G_>>Для перерисовки формы использую перехват Windows message.


G_>>При работе этого кода на тексте размером больше 500 символов начинаются сильные тормоза и подвисания приложения. Как можно от этого избавиться? В какую сторону копать?


VF>Не понятно, почему правильнописание надо проверять в WM_PAINT?

Есть другие идеи?
Re[3]: Как можно ускорить кастомную отрисовку в WinForms?
От: VladFein США  
Дата: 28.04.14 14:08
Оценка:
Здравствуйте, Gepard_vvk, Вы писали:

VF>>Не понятно, почему правильнописание надо проверять в WM_PAINT?

G_>Есть другие идеи?

Конечно. Проверять когда текст изменился (что-то напечатано, ыдалено, вставленно, и т.д.)
Re[4]: Как можно ускорить кастомную отрисовку в WinForms?
От: Gepard_vvk  
Дата: 28.04.14 14:24
Оценка:
Здравствуйте, VladFein, Вы писали:

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


VF>>>Не понятно, почему правильнописание надо проверять в WM_PAINT?

G_>>Есть другие идеи?

VF>Конечно. Проверять когда текст изменился (что-то напечатано, ыдалено, вставленно, и т.д.)

При любом из перечисленный действий происходит перерисовка компонента (Привет, WM_Paint).
Re[5]: Как можно ускорить кастомную отрисовку в WinForms?
От: VladFein США  
Дата: 28.04.14 14:26
Оценка:
Здравствуйте, Gepard_vvk, Вы писали:

VF>>>>Не понятно, почему правильнописание надо проверять в WM_PAINT?

G_>>>Есть другие идеи?

VF>>Конечно. Проверять когда текст изменился (что-то напечатано, ыдалено, вставленно, и т.д.)

G_>При любом из перечисленный действий происходит перерисовка компонента (Привет, WM_Paint).

Но не при любом WM_PAINT произошло изменение текста!
Re[3]: Как можно ускорить кастомную отрисовку в WinForms?
От: Rinbe Россия  
Дата: 28.04.14 17:03
Оценка:
Здравствуйте, Gepard_vvk, Вы писали:

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


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


G_>>>Работаю на WinForms приложением, в котором нужно реализовать проверку правописания.


G_>>>Для перерисовки формы использую перехват Windows message.


G_>>>При работе этого кода на тексте размером больше 500 символов начинаются сильные тормоза и подвисания приложения. Как можно от этого избавиться? В какую сторону копать?


VF>>Не понятно, почему правильнописание надо проверять в WM_PAINT?

G_>Есть другие идеи?

Можно идти стандартным путем: наследовать от TextBox и переопределение метода OnPaint.
Re[6]: Как можно ускорить кастомную отрисовку в WinForms?
От: Gepard_vvk  
Дата: 29.04.14 07:46
Оценка:
Здравствуйте, VladFein, Вы писали:

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


VF>>>>>Не понятно, почему правильнописание надо проверять в WM_PAINT?

G_>>>>Есть другие идеи?

VF>>>Конечно. Проверять когда текст изменился (что-то напечатано, ыдалено, вставленно, и т.д.)

G_>>При любом из перечисленный действий происходит перерисовка компонента (Привет, WM_Paint).

VF>Но не при любом WM_PAINT произошло изменение текста!

Да, верно. Решается дополнительной проверкой на изменение текста. Но на результате это никак не отражается.
Re[4]: Как можно ускорить кастомную отрисовку в WinForms?
От: Gepard_vvk  
Дата: 29.04.14 07:50
Оценка:
Здравствуйте, Rinbe, Вы писали:

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


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


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


G_>>>>Работаю на WinForms приложением, в котором нужно реализовать проверку правописания.


G_>>>>Для перерисовки формы использую перехват Windows message.


G_>>>>При работе этого кода на тексте размером больше 500 символов начинаются сильные тормоза и подвисания приложения. Как можно от этого избавиться? В какую сторону копать?


VF>>>Не понятно, почему правильнописание надо проверять в WM_PAINT?

G_>>Есть другие идеи?

R>Можно идти стандартным путем: наследовать от TextBox и переопределение метода OnPaint.

Компонент наследуется от TextBoxBase. Если его(компонент) размещать на форме, то код не заходит в переопределенный OnPaint компонента, поэтому и реализовано через WM_PAINT.
Re[7]: Как можно ускорить кастомную отрисовку в WinForms?
От: VladFein США  
Дата: 29.04.14 13:56
Оценка:
Здравствуйте, Gepard_vvk, Вы писали:

VF>>Но не при любом WM_PAINT произошло изменение текста!

G_>Да, верно. Решается дополнительной проверкой на изменение текста. Но на результате это никак не отражается.

Это решается обработкой EN_CHANGE notification code.
Оставьте WM_PAINT в покое!
Re: Как можно ускорить кастомную отрисовку в WinForms?
От: Danchik Украина  
Дата: 29.04.14 14:52
Оценка:
Здравствуйте, Gepard_vvk, Вы писали:

G_>Работаю на WinForms приложением, в котором нужно реализовать проверку правописания.


[Skip]

G_>При работе этого кода на тексте размером больше 500 символов начинаются сильные тормоза и подвисания приложения. Как можно от этого избавиться? В какую сторону копать?


Invalidate в WM_PAINT это абсурд.
Вызывайте Invalidate при изменении текста, или еще лучше InvalidateRect с точной позицией линии.
Re: Как можно ускорить кастомную отрисовку в WinForms?
От: TATAPuH США  
Дата: 02.05.14 21:01
Оценка:
Здравствуйте, Gepard_vvk, Вы писали:

G_>При работе этого кода на тексте размером больше 500 символов начинаются сильные тормоза и подвисания приложения. Как можно от этого избавиться? В какую сторону копать?


создайте прозрачную битмапу высотой 2-3 пикселя и шириной в размер экрана
нарисуйте ваше подчёркивание один раз и закешируйте результат

в момент рендеринга просто блитайте кусок закешированного битмапа с "волнистой линией" на основную

вот и всё
Re[8]: Как можно ускорить кастомную отрисовку в WinForms?
От: Gepard_vvk  
Дата: 12.05.14 08:53
Оценка:
Здравствуйте, VladFein, Вы писали:

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


VF>>>Но не при любом WM_PAINT произошло изменение текста!

G_>>Да, верно. Решается дополнительной проверкой на изменение текста. Но на результате это никак не отражается.

VF>Это решается обработкой EN_CHANGE notification code.

VF>Оставьте WM_PAINT в покое!
Не подходит ровно как и определение логики перерисовки в событии изменения текста, т.к. при любом скроле текста пройдет перерисовка компонента и линии подчеркивания исчезнут...Поэтому WM_PAINT оставить в покое не получается...
Re[2]: Как можно ускорить кастомную отрисовку в WinForms?
От: Gepard_vvk  
Дата: 12.05.14 08:54
Оценка:
Здравствуйте, Danchik, Вы писали:

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


G_>>Работаю на WinForms приложением, в котором нужно реализовать проверку правописания.


D>[Skip]


G_>>При работе этого кода на тексте размером больше 500 символов начинаются сильные тормоза и подвисания приложения. Как можно от этого избавиться? В какую сторону копать?


D>Invalidate в WM_PAINT это абсурд.

D>Вызывайте Invalidate при изменении текста, или еще лучше InvalidateRect с точной позицией линии.
Если убрать Invalidate, то при любом скроле текста линии подчеркивания исчезнут...
Re[2]: Как можно ускорить кастомную отрисовку в WinForms?
От: Gepard_vvk  
Дата: 12.05.14 08:54
Оценка:
Здравствуйте, TATAPuH, Вы писали:

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


G_>>При работе этого кода на тексте размером больше 500 символов начинаются сильные тормоза и подвисания приложения. Как можно от этого избавиться? В какую сторону копать?


TAT>создайте прозрачную битмапу высотой 2-3 пикселя и шириной в размер экрана

TAT>нарисуйте ваше подчёркивание один раз и закешируйте результат

TAT>в момент рендеринга просто блитайте кусок закешированного битмапа с "волнистой линией" на основную


TAT>вот и всё


Вы представляете как это будет выглядеть на словах разной длины?..
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.