Я думаю, что ваша проблема в том, что вы зацикливались на именах Microsoft для вещей, имени Microsoft «контекст устройства» и именах вызовов, таких как «CreateCompatibleDC».
«Контекст устройства» - это плохое имя. Документация Win32 скажет вам, что контекст устройства - это структура данных для хранения состояния конкретного устройства, используемого для визуализации графических команд. Это только частично правда. Посмотрите на различные виды DC, которые существуют: (1) контексты устройства экрана, (2) контексты устройства принтера, (3) контекст устройства, используемый растровым изображением в памяти, и (4) контексты устройства метафайла. Из них только (1) или (2) фактически делают именно то, о чем заявляет документация. В других случаях контексты устройства служат целью для рисования вызовов, но не являются контейнерами для состояния некоторого физического устройства. (Это действительно заметно в случае с метафайлами DC: метафайлы были старыми Win32-объектами, которые в основном просто кэшировали входящие в них вызовы GDI для последующего воспроизведения, что-то вроде грубого векторного формата.)
В гипотетической объектно-ориентированной версии Win32 контексты устройства могут быть экземплярами некоторого класса, который реализует интерфейс, который предоставляет вызовы графического рисования. Лучшим названием для такого класса было бы что-то вроде «Графика», и действительно в GDI + это то, что фактически называется аналогичной конструкцией. Когда мы «создаем» - через CreateDC, CreateCompatibleDC и т. Д. - мы создаем один из этих объектов. Когда мы получаем GetDC, мы берем такой объект, который уже существует.
Чтобы ответить на ваши вопросы:
Является ли контекст устройства ТИПом отображения или МГНОВЕНИЕ графических данных, которые могут быть отображены.
Они в этом смысле являются типами дисплеев. Вы можете думать о них как о экземплярах класса объектов с частными реализациями, которые предоставляют открытый интерфейс, представляющий команды рисования.
Почему мы не можем использовать GetDC () с NULL или с hwndDesktop вместо этого?
Вы не можете использовать GetDC (NULL) в качестве контекста устройства, в котором вы собираетесь выбрать растровое изображение в памяти, потому что в такой ситуации вам необходимо создать контекст устройства, который еще не существует; GetDC (NULL) похож на одноэлементный экземпляр, который уже используется.
Таким образом, вместо этого вы обычно используете CreateCompatibleDC (NULL) или CreateCompatibleDC (hdcScreen). Снова CreateCompatibleDC (...) - запутанное имя. Представьте себе гипотетическую объектно-ориентированную версию происходящего здесь. Скажем, есть интерфейс IGraphics, который реализован в RasterGraphics, PrinterGraphics и MetafileGraphics. Представьте, что класс "RasterGraphics" используется как для экрана, так и для растровых изображений в памяти. Тогда CreateCompatibleDC (...) будет выглядеть как вызов фабрики Graphics.CreateFrom (IGraphics g), который возвращает новый экземпляр того же конкретного типа с возможно инициализированными переменными состояния.
Почему мы не можем кэшировать контекст устройства вместо его повторного создания?
Можно. Вам не нужно удалять контексты устройства через вызовы функций. Единственная причина, по которой люди часто делают это, заключается в том, что они являются общим и ограниченным ресурсом, а их создание обходится дешево. На самом деле, я думаю, что они были очень ограничены в старых версиях Windows, поэтому старые программисты на Win32, как правило, не кэшировали их из мышц памяти старых времен, начиная с Windows 95 дней.
Если на машине имеется только одно устройство отображения, а мы рисуем только окна, зачем нам постоянно согласовывать растровые изображения и контексты устройства?
Не думайте, что «совместимость» в CreateCompatibleDC (...) подразумевает «гармонизацию с экраном», это означает «хорошо, Windows, я хочу создать один из ваших объектов графического интерфейса и хочу, чтобы вроде как этот, который является обычной растровой графикой, а не для принтеров или метафайлов. "