#c #winapi
#c #winapi
Вопрос:
Мне приходится рисовать растровое изображение несколько раз. Он загружен из файла. Я могу перезагружать его каждый раз, когда мне нужно его использовать SelectObject
следующим образом:
void drawBitmap(HWND hWnd, int xPos, int yPos) {
HBITMAP hBmp = (HBITMAP) LoadImage(NULL, "image.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
HDC hDC = GetDC(hWnd);
HDC hdcMem = CreateCompatibleDC(hDC);
SelectObject(hdcMem, hBmp);
BitBlt(hDC, xPos, yPos, 7, 7, hdcMem, 0, 0, SRCCOPY);
}
drawBitmap(hMainWnd, 0, 0);
drawBitmap(hMainWnd, 14, 0);
drawBitmap(hMainWnd, 28, 0);
Но возможно ли также сделать что-то подобное?
HBITMAP hBmp = (HBITMAP) LoadImage(NULL, "image.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
void drawBitmap(HWND hWnd, int xPos, int yPos) {
HBITMAP hBmp2 = hBmp;
HDC hDC = GetDC(hWnd);
HDC hdcMem = CreateCompatibleDC(hDC);
SelectObject(hdcMem, hBmp2);
BitBlt(hDC, xPos, yPos, 7, 7, hdcMem, 0, 0, SRCCOPY);
}
drawBitmap(hMainWnd, 0, 0);
drawBitmap(hMainWnd, 14, 0);
drawBitmap(hMainWnd, 28, 0);
Но при этом отображается только одно растровое изображение…
MSDN говорит:
SelectObject
Функция выбирает объект в указанном контексте устройства (DC). Новый объект заменяет предыдущий объект того же типа.
Так что, возможно, мой hBmp
потрачен впустую после SelectObject
вызова. Но сначала я скопировал его в hBmp2
, тогда в чем проблема?
Ответ №1:
Вы не удаляете DC памяти, когда закончите с ним. Это означает утечку DC, и растровое изображение все еще выбрано в этом утеченном DC. И согласно SelectObject
документации: «Приложение не может выбрать одно растровое изображение в более чем один DC одновременно».
Итак, второй SelectObject
завершается неудачей, потому что растровое изображение все еще выбрано в первом HDC
.
Уберите за собой, вызвав DeleteDC
в конце drawBitmap
функцию (а также вызовите DeleteObject
hBmp, когда закончите с ней).
Кроме того, HBITMAP hBmp2 = hBmp;
строка ничего не дает. Вы просто присваиваете дескриптор другой переменной. Это все тот же дескриптор для того же растрового изображения.
Комментарии:
1. Спасибо, чувак, это сработало. Я принимаю ваш ответ, по какой-то причине мне нужно подождать всего 5 минут.
2. Кстати, вы могли бы дополнительно оптимизировать этот код, повторно используя сам memory DC вместо просто bitmap (все равно удалите его после того, как закончите с ним, конечно).
3. Все правильно, за исключением, возможно, одной вещи: я не уверен, но я думаю, что когда вы удаляете DC, это также уничтожает выбранное растровое изображение. Так что, если у вас все еще есть дескриптор этого растрового изображения — он недействителен. Более правильным было бы сохранить повторное значение
SelectObject
, а затем, непосредственно перед повторной попыткой вызова DCSelectObject
с этим значением, восстановить исходное растровое изображение в DC (которое представляет собой монохромное растровое изображение 1×1). Это правда?4. В документации DeleteDC ничего не упоминается об удалении выбранных объектов, поэтому я так не думаю.