Detach
уничтожит предыдущую ручку.
Обратите внимание, что если вы позвоните по телефону Detach
после звонка SetBitmap
, растровое изображение управления изображением будет уничтожено. В результате управление изображением наносится один раз, но он не будет перекрашиваться. Например, управление изображением гаснет, если диалоги изменены.
EDIT
Чтобы разрушить старый битмап, вызовите Detach
с последующим DestroyObject
. Пример
HGDIOBJ hbitmap_detach = m_bitmap.Detach();
if (hbitmap_detach)
DeleteObject(hbitmap_detach);
m_bitmap.Attach(hbitmap);
Если это временная CBitmap
то DeleteObject
не является необходимым, так как DeleteObject
вызывается автоматически, когда CBitmap
выходит из области видимости.
Обратите внимание, что если вы уничтожите растровое изображение после вызова SetBitmap
, растровое изображение управления изображением будет уничтожено. В результате управление изображением наносится один раз, но он не будет перекрашиваться. Например, управление изображением гаснет, если диалоги изменены.
Это та же проблема, если вы объявляете временный CBitmap
на стеке и прикрепляете растровый дескриптор. Этот битмап-дескриптор будет уничтожен, а управление изображением не сможет перекрасить.
Кроме того, Windows XP иногда создает дублирующее растровое изображение, которое также необходимо уничтожить. SetBitmap
возвращает дескриптор предыдущего растрового изображения. В Vista + возвращаемое растровое изображение - это то же самое, что было сохранено в m_bitmap
, мы уже уничтожаем его с помощью Detach
. Но в XP нам нужно уничтожить эту копию, если это другой дескриптор.
void CMyDialog::foo()
{
HBITMAP save = m_bitmap;
HBITMAP hbitmap = (HBITMAP)::LoadImage(0, filename,
IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
if (hbitmap)
{
HGDIOBJ hbitmap_detach = m_bitmap.Detach();
//Edit ****************************************
//Delete old handle, otherwise program crashes after 10,000 calls
if (hbitmap_detach)
DeleteObject(hbitmap_detach);
//*********************************************
m_bitmap.Attach(hbitmap);
HBITMAP oldbmp = m_picControl.SetBitmap(m_bitmap);
//for Windows XP special case where there might be 2 copies:
if (oldbmp && (oldbmp != save))
DeleteObject(oldbmp);
}
}
Кроме того, SetBitmap
принимает HBITMAP
параметр и возвращает HBITMAP
, так что вы можете избежать использования CBitmap
вообще. Следующий пример работает в Vista, +
void foo()
{
HBITMAP temp = (HBITMAP)::LoadImage(0,filename,IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
if (temp)
{
HBITMAP oldbmp = m_picControl.SetBitmap(temp);
if (oldbmp)
DeleteObject(oldbmp);
}
}
Вы, кажется, ничего не делаете с 'buffer'? Также добавьте для вызова ':: GetLastError()' в соответствующих местах и запишите их (или используйте отладчик) –
A [mcve], пожалуйста. Это должно быть полным и ** минимальным **. Ваши вызовы 'CBitmap :: Attach' и' Detach' являются массовыми убийствами, связанными с управлением ресурсами C++, и служат только для того, чтобы сделать ваш код более трудным для чтения. Если вы не знаете, почему это неправильно, вам нужно забрать хорошую книгу по программированию Windows API (Petzold's * «Programming Windows, 5th Edition» *), за которой следует одно для MFC («Прокси» * «Программирование Windows с MFC "*). Рассматривая историю вопроса, вы не добились большого прогресса. – IInspectable
Используйте gdiplus, чтобы облегчить жизнь – seccpur