Нужно ли CreateCompatibleDC () работать с окнами на одном дисплее? - PullRequest
2 голосов
/ 26 мая 2019

Этот пример кода вручную читает файл растрового изображения, использует CreateDIBSection(), чтобы GDI выделил для него память, и создает дескриптор hbitmap.Затем он использует MemoryDC для рисования растрового изображения в окне DC:

ftp: //ftp.oreilly.com/examples/9781572319950/cd_contents/Chap15/DibSect/DibSect.c

hdc = BeginPaint (hwnd, &ps) ;
...
hdcMem = CreateCompatibleDC (hdc) ;

Почему мы не можем использовать GetDC() с NULL или с hwndDesktop вместо этого?Почему мы не можем кэшировать контекст устройства вместо его повторного создания?

Если на машине есть только одно устройство отображения, а мы рисуем только окна, зачем нам постоянно согласовывать битовые карты и контексты устройства?Как только пиксельные данные копируются в буфер, предоставленный GDI, обновляет ли GDI его, когда этот HBITMAP загружается в DC и рисуется?Если пользователь также хочет использовать его, необходимо ли синхронизировать доступ?(Сначала вызывая GDIFlush()?)

Трудно понять это, когда большинство всех свойств объекта непрозрачны и абстрагированы.Я прочитал почти все связанные MSDN, много книг Петцольда и некоторые статьи:

Контексты устройства отображения

CreateCompatibleDC ()

CreateDIBSection ()

Контексты устройства памяти

Руководство по памяти Win32 DC

Руководство по WIN32 Paint для промежуточных продуктов

Программирование Windows®, пятое издание

Редактировать:

Я думаюМой вопрос сводится к следующему:

Является ли контекст устройства ТИПом отображения или МГНОВЕННОСТЬ графических данных, которые могут быть отображены.Компьютер обычно имеет только несколько дисплеев, но на нем могут отображаться сотни вещей.

Ответы [ 2 ]

1 голос
/ 26 мая 2019

GetDC(NULL) - это экран HDC, а экран является общим ресурсом, поэтому вы должны выполнять операции чтения / запроса только на этом HDC.Запись в этот HDC не является хорошей идеей в Vista и выше из-за DWM .

Поскольку HDC может содержать только одну битовую карту, одну кисть и одну ручку, Windows / приложения, очевидно, нуждаютсяболее одного HDC, предоставленного графическим движком.

Вы можете рассчитывать на CreateCompatibleDC как относительно дешевую операцию, и я считаю, что в Windows есть кэш DC, которые она может раздавать.Если вы создаете приложение типа игры / анимации, вы можете кэшировать некоторые из этих графических объектов самостоятельно, но обычное приложение не должно этого делать.

Обычно вы не вызываете GDIFlush, если вы не разделяете объекты GDI в нескольких потоках.Вы можете использовать SetDIBits, если хотите смешать необработанные пиксельные байты и GDI.

На самом деле я не получаю аргумент «один раз на экране», Windows поддерживает несколько мониторов начиная с Windows 98, и вы ничего не можете сделать, чтобы запретить пользователю подключать другой монитор.

0 голосов
/ 27 мая 2019

Я думаю, что ваша проблема в том, что вы зацикливались на именах 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, я хочу создать один из ваших объектов графического интерфейса и хочу, чтобы вроде как этот, который является обычной растровой графикой, а не для принтеров или метафайлов. "

...