Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > Вывод растрового изображения


Автор: yngwie19 10.3.2009, 16:55
Всем привет. У меня вопрос по поводу вывода в главное окно растровое изображение. Приведу пример моего кода и по нему задам пару вопросов.
Допустим есть файл pict.bmp (определенный в файле ресурсов как Image BITMAP "pict.bmp"), который Я хочу вывести на экран. Делаю так:
Код

HBITMAP hBitMap = (HBITMAP)LoadImage(hInstance,"Image",IMAGE_BITMAP,0,0,0);

По этому участку кода:
1) Функция LoadImage() создает область совместимой памяти, загружает туда изображение и возвращает на него дескриптор. Так?
2) Можно ли в эту область пямяти загружать несколько изображений и вообще разумно ли это?
Код

BITMAP bm;
GetObject(hBitMap,sizeof(BITMAP),&bm);

3) Здесь вроде все понятно. Получаем характеристики изображения для правильного вывода изображения с помощью функции BitBlt().
Код

HDC hdc = GetDC(hwnd);
hdcMem = CreateCompatibleDC(hdc);

4) Вот здесь немного не ясно. С помощью функции CreateCompatibleDC() мы создаем совместимый контекст пямяти. Зачем нам его создавать, разве мы его не создавали функцией LoadImage() ? см. п.1
5) Поясните пожалуйста, что конкретно мы сдесь делаем?
Код

SelectBitMap(hdcMem,hBitMap)

6) Здесь мы выбираем в совместимы контекст памяти дескриптор изображения созданный ранее функцией LoadImge(), туда можно загрузить только одно изображение, точно также как и шрифты и тому подобное?   

Автор: nns2009 10.3.2009, 21:43
Лично по моему GDI уже устарел, лично я при создании графики пользуюсь GDI+.
Там и скорость выше(в книге так было написано по крайней мере) и программировать в нём удобнее(в одной книге видел графику GDI, она по сложнее).

Автор: yngwie19 10.3.2009, 21:59
nns2009,  smile 

Автор: GremlinProg 11.3.2009, 00:36
по-простому:
HDC - объект графического вывода, которое имеет, как бы набор слотов:

слот памяти (HBITMAP)
слот шрифта (HFONT)
слот кисти (HBRUSH)
слот карандаша (HPEN)
и т.п.

объект каждого слота требуется в определенный момент, но практически всегда требуется сразу несколько объектов, поэтому, чтобы не утруждать пользователя постоянно передавать кипу дополнительных параметров, HDC и держит их все сам, предлагая взамен просто менять объекты в своих слотах, если нужно

в каждый слот можно вcтавить только один объект
по-умолчанию, при создании нового HDC, он уже настроен определенным образом, т.е. в каждом слоте у него уже находится свой объект (системный), который желательно вернуть на место, если производится обращение к слотам

чтобы сменить объект слота, нужно воспользоваться функцией SelectObject, которая устанавливает переданный ей объект в слот и возвращает объект, который был в слоте ранее, таким образом, довольно просто получается вклиниваться в процедуру рисования со своими настройками:
Код

hOldPen = ::SelectObject(hdc,hMySpecialPen);
::Ellipse(hdc,l,t,r,b);
::SelectObject(hdc,hOldPen);

ну, и так же просто их восстановить, даже особо не вникая в то, что там было уже вставлено

HBITMAP - ключевой объект, поскольку он задает формат графики и ее содержание, именно битмап модифицируется после любой видимой графической операции, поэтому к нему особое отношение

HDC может быть как серым, так и экранным
экранный - связанный с дескриптором окна(WindowFromDC) и, соответственно с некоторой областью графической памяти (с которой постоянно снимается слепок экрана(ов) )
такие девайсы получают с помощью оконных API: GetDC, GetWindowDC, CreateDevice("DISPLAY"... и т.п
число таких девайсов ограничено потому что писать в одну область памяти одновременно все не могут (именно поэтому и говорят: для каждого GetDC должна быть парная ей ReleaseDC)
для экранных HDC слот памяти трогать не нужно, поскольку система сама уже его настраивает, в соответствии с позицией и размерами окна, при вызове одной из вышеперечисленных функций

серый HDC, или девайс в памяти (memory DC) - это простое граф. устройство, которое напрямую не связано с экраном, но которое может взаимодействовать с экранным HDC, которое, в свою очередь, с ним уже связано (перед работой с таким девайсом, необходимо обязательно настроить его слот памяти HBITMAP)

совместимый девайс - это один HDC, формат которого совместим (или просто равен) формату другого HDC
да, HDC тоже имеет свой формат, как и HBITMAP, а смысл такого повтора в том, что девайсы умеют вполне адекватно работать (работать, как правило, аппаратно, т.е. быстро) с памятью разных форматов, что позволяет экономить ресурсы на переводе битмапов между форматами, но при работе с экранным HDC требуется строгое соответствие формата (это формат рабочего стола) , который соблюдают все "настольные" приложения (экранная память ведь одна, тут не должно быть несоответствия)
чтобы автоматически назначить такой формат для заданного HDC, и применяется функция CreateCompatibleDC

совместимый битмап - это HBITMAP, формат которого входит в набор поддерживаемых форматов для заданного совместимого девайса
проще говоря, это такой битмап, который можно вставить в слот определенного девайса (не все можно)
чтобы автоматически назначить такой формат для заданного HDC, и применяется функция CreateCompatibleBitmap

LoadImage - создает объект HBITMAP на основе файла, или ресурса, т.е., по сути, предоставляет формат рисунка и его содержимое
чтобы перенести этот битмап на экран, его нужно сначала вставить в слот memory DC, после чего, уже работать с двумя девайсами: "в памяти" и "экранным", они ведь только друг-друга понимают

вот поэтому и нужен еще один HDC

Цитата(nns2009 @  10.3.2009,  23:43 Найти цитируемый пост)
Лично по моему GDI уже устарел, лично я при создании графики пользуюсь GDI+.

ну, это врятли, чтобы он устарел, требуется как минимум более новая версия GDIAPI, а GDI+ к системному API, на сколько я знаю, пока ни как не относится

Автор: yngwie19 11.3.2009, 07:45
GremlinProg, Большое спасибо за подробное оъяснение!

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)