Правильное использование контекста устройства Win32

#c #msdn

#c #msdn

Вопрос:

Я уже некоторое время работаю с GDI и пытаюсь улучшить свое понимание этого, чтобы иметь возможность создать для него класс-оболочку.

  1. Почему я не могу удерживать контекст устройства window до завершения работы приложения? Становится ли оно недействительным при каком-либо из событий? Я слышал, как кто-то сказал, что после WM_SIZE контекст становится недействительным, это правда? Я никогда не сталкивался с этим, хотя я всегда кэширую контекст окна. Это значительно упрощает создание COMPATIBLEDC() и createCompatibleBitmaps() в конструкторе. Я также кэширую эти созданные DC и использую их, чтобы избежать мерцания, для рисования локальных границ кэширование операции рисования в окне минимизируется, а затем максимизируется.

  2. Почему приложение должно извлекать более 1 контекста окна одновременно? Поскольку документация жалуется на превышение предела контекста окна.

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

1. Что касается вашего второго вопроса, вы могли бы, например, использовать один DC для рисования и перенести его в window DC. Это предотвращает мерцание при рисовании непосредственно в окне DC.

2. Зависит от того, как был создан DC. Если вы получили его из BeginPaint(), то вы пожалеете, что кэшировали его, область отсечения легко устаревает. GetDC() в порядке. Кэширование полезно, если создание объекта дорого, но хранение дешево. Window DC дешев в создании, но хранится в очень ограниченной куче рабочего стола. Не стоит беспокоиться о кэшировании только одного.

3. @Hans У меня нет привычки кэшировать или использовать контексты нескольких окон, но насколько раньше моя система замедлится? Я случайно обнаружил, что постоянное создание растровых изображений без освобождения очень заметно замедляет работу вашего приложения. Это означает, что растровые изображения занимают очень много памяти.

4. @ Какой-то программист, чувак, мой второй вопрос касается только windows dc, а не памяти dc.

Ответ №1:

Помните, что в контексте, о котором вы говорите, ‘invalidate’ означает требовать перерисовки некоторой части окна, это не означает, что дескриптор, полученный из GetDC, станет непригодным для использования.

Окно с CS_HREDRAW или CS_VREDRAW потребует, по крайней мере, частичной перерисовки при любом изменении размера в указанном направлении, а также любой операции изменения размера, которая увеличивает размер окна.

Из-за ограничений на количество объектов GDI обычным шаблоном является обработка сообщений WM_PAINT и использование дескриптора, возвращаемого BeginPaint (который будет использоваться только до тех пор, пока не будет вызван EndPaint).

И, как сказал какой-то чувак-программист в комментарии, второй DC можно использовать для выполнения рисования без мерцания, отнимающее много времени рисование выполняется на внеэкранном DC, а затем просто копируется на экранный DC. И даже если это делается полностью в обработчике WM_PAINT, закадровый DC обычно освобождается после завершения операции рисования, чтобы не перегружать ресурсы GDI.

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

1. отлично. Подтверждено, что окно dc неявно становится недействительным во время кэширования. Программирование графики — это компромисс в скорости и использовании памяти. вы хотите сказать, что это достаточно быстро, чтобы создать memory dc и получить window dc, а последствия хранения / распределения ресурсов намного хуже? И второй вопрос. Являются ли графические объекты open gl или directx такими же ресурсоемкими, как gdi? Я уже знаю, что контекст opengl является производным от контекста gdi.

2. Похоже, что это должен быть новый вопрос, я не знаю ответа на этот вопрос. Я слеп и использую GDI, потому что он (особенно для текста) очень хорошо работает со средствами обеспечения доступности, где DirectX и OpenGL требуют реализации обработчиков MSAA или UIA, чтобы мой экранный ридер знал о тексте.