winapi: от HDC к HBITMAP

Я хотел бы сделать что-то, что я считаю довольно простым, но, поскольку я новичок в winapi, я нахожу много проблем. В основном у меня есть HDC (который я BitBlitting из загруженного растрового изображения), и я рисую на нем прямоугольник. Затем я хотел бы использовать BitBlt этот HDC в новый объект HBITMAP, но, увы, пока безрезультатно.

Вот мой код, который я пытаюсь заставить работать уже пару часов.

BITMAPINFO info;
Bitmap *tempbmp = Bitmap::FromFile(L"C:\\Users\\abelajc\\Pictures\\BackgroundImage.png", false);
HBITMAP loadedbackground;
tempbmp->GetHBITMAP(NULL, &loadedbackground);

HBRUSH hRed = CreateSolidBrush(RGB(255, 0, 0));

HDC pDC = GetDC(0);
HDC TmpDC = CreateCompatibleDC(pDC); //main DC on which we will paint on

HDC dcBmp = CreateCompatibleDC(TmpDC); //DC for the loadedbackground HBitmap
HGDIOBJ TmpObj2 = SelectObject(dcBmp , tempbmp); //Selecting Bitmap in DC
BitBlt(TmpDC, 0, 0, 512, 512, dcBmp, 0, 0, SRCCOPY);
SelectObject(dcBmp, TmpObj2); //Deselecting Bitmap from DC
DeleteDC(dcBmp);

RECT rectangle;
SetRect(&rectangle, 5, 5, 20, 20);
FillRect(TmpDC, &rectangle, hRed);

HDC hCompDC = CreateCompatibleDC(TmpDC);
HBITMAP hBmp = CreateCompatibleBitmap(TmpDC, 512, 512);
HBITMAP hOld = (HBITMAP)SelectObject(hCompDC, hBmp);
BitBlt(hCompDC, 0, 0, 512, 512, TmpDC, 0, 0, SRCCOPY);
SelectObject(hCompDC, hOld);
DeleteDC(hCompDC);

Bitmap *image = new Bitmap(hBmp, NULL);

person Jean Claude Abela    schedule 23.06.2015    source источник
comment
Похоже, вы вообще не выполняете проверку ошибок. Возможно, один из ваших вызовов API не работает. Это винап 101.   -  person David Heffernan    schedule 23.06.2015
comment
Не CreateCompatibleDC() с памятью DC. Я помню, что у меня были некоторые проблемы с этим.   -  person ikh    schedule 23.06.2015


Ответы (1)


Я думаю, вам просто нужно немного пояснений по поводу GDI.
DC — это именно то, что подразумевает его название: контекст устройства. Это просто контекст, ничего конкретного. Некоторые контроллеры домена являются контекстом реального графического устройства, некоторые другие (контроллеры домена памяти) являются контекстом виртуальной графической поверхности в памяти. Контроллеры домена, которые вы создаете с помощью CreateCompatibleDC, являются контроллерами домена памяти, но создание контроллера домена создает только контекст, а не поверхность памяти. Как говорится в документации MSDN:

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

Вам необходимо связать HBITMAP с контроллером домена. После этого вы можете считать, что рисование в DC — это, по сути, рисование в растровом изображении. Контроллер памяти — это «окно» для растрового изображения.

Как только вы это поймете, вы увидите, что вашу программу можно значительно сократить. Не стесняйтесь комментировать, если у вас все еще есть проблемы.

person ElderBug    schedule 23.06.2015
comment
Большое спасибо за это объяснение, я чувствую, что с ним я понял одну из важнейших частей рисования с использованием winapi, с которой я боролся. Мне также удалось исправить свой код, используя то, что я узнал из этого объяснения :) - person Jean Claude Abela; 23.06.2015
comment
@JeanClaudeAbela Не за что :) Эта часть GDI действительно немного неясна. В прошлом у меня также были проблемы с пониманием того, как это работает на самом деле. - person ElderBug; 23.06.2015