Графический объект GDI не отражает изменение размера окна

#winforms #resize #gdi #hwnd

#winforms #изменение размера #gdi #hwnd

Вопрос:

У меня следующая проблема. Я рисую на поверхности панели формы Windows, используя собственный GDI (алгоритм рисования находится внутри собственной библиотеки DLL, вызываемой P / Invoke). Все в порядке, но только до тех пор, пока не изменится размер панели. Если он уменьшен, он отображается правильно. Однако, если он увеличен, GDI перерисовывает только ту часть области панели, которая соответствует ее первоначальному размеру.

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

Комментарии:

1. Вероятно, в коде используется Graphics::FromHWND() . Это распространенная ошибка — сохранять этот объект и повторно использовать его позже. Рисуйте только тогда, когда Windows попросит вас об этом, используйте графический объект, который вы получаете в аргументах события. У него всегда будет соответствующая область клипа.

2. Почему это так? Мне приходится создавать много объектов GDI во время рисования, поэтому я сохраняю их и повторно использую позже, а также сам графический объект. AFAIR, я где-то читал в документах MSDN, что это нужно сделать, чтобы предотвратить ненужные (дорогостоящие, с точки зрения производительности) операции с памятью.

3. Вы выяснили, почему, графический объект больше не соответствует состоянию окна. Вы предполагаете, что его создание дорого. Это не так, это стоит всего пару десятков микросекунд. Хранить его дорого, без необходимости используя память. В любом случае, вам нужно воссоздать его при изменении состояния окна.

4. Жаль, что вы ответили в форме комментария, а не обычного ответа, потому что я не могу принять его сейчас (с точки зрения stackoverflow, конечно) 🙂

Ответ №1:

Ответил Ханс Пассант в комментарии:

You found out why, the Graphics object no longer matches the state of the window. You are assuming that it is expensive to create. It isn't, it only costs couple of dozen microseconds. It is only expensive to keep it around, needlessly using memory. Anyhoo, you need to recreate it when the window state changes.

Ответ №2:

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

Попробуй позвонить .Становится недействительным на панели при изменении ее размера.

Комментарии:

1. Я рисую в переопределенном методе OnPaint. Добавление Invalidate ничего не меняет, перерисованная область по-прежнему обрезается до исходного размера окна. Для ясности: сам элемент управления перерисовывается. Проблема в том, что перерисованная область обрезается до исходного размера элемента управления.