-
Пишу "графический редактор" с использованием HENHMETAFILE'ов. Для рисования создаю отдельный класс окна. Всё рисование производится одновременно в memory bitmap (hDC+hBitmap) и метафайл (hMFDC). Битмап используется для быстрой отрисовки окна, метафайл - для хранения собственно действий, приводящих к получению изображения.
Добавляю обработку WM_SIZE, выполняю следующие действия:
1. Пересоздаю битмап в памяти (разумеется, с отсоединением и последующим присоединением к hDC). 2. hMF:=CloseEnhMetaFile(hMFDC) 3. hMFDC:=CreateEnhMetaFile(...) 4. PlayEnhMetaFile() в hDC и hMFDC. 5. DeleteEnhMetaFile(hMF) 6. Перерисовка окна.
При многократных ресайзах наблюдаю постепенное замедление процесса: после 2-3 десятков ресайзов (независимо от того, увеличение или уменьшение) обработка WM_SIZE начинает занимать несколько секунд.
Все метафайлы создаются в памяти, без привязки к файлам на диске.
Сталкивался ли кто-нибудь с такой проблемой?
-
пользуюсь метафайлами регулярно. ты бы код привел, воспроизводивший проблему...
-
На сях он, правда :) SelectObject(pbs->hdcMem,pbs->hbmMemO);
DeleteObject(pbs->hbmMem);
hdc = GetDC(hWnd);
pbs->hbmMem = CreateCompatibleBitmap(hdc,wr.right,wr.bottom);
SelectObject(pbs->hdcMem,pbs->hbmMem);
ReleaseDC(hWnd,hdc);
FillRect(pbs->hdcMem,&wr,pbs->hbrBack);
hMF = CloseEnhMetaFile(pbs->hMFDC);
pbs->hMFDC = PaintBox_CreateMetaFile(pbs,NULL,&wr);
PlayEnhMetaFile(pbs->hMFDC,hMF,&wr);
PlayEnhMetaFile(pbs->hdcMem,hMF,&wr);
DeleteEnhMetaFile(hMF);
InvalidateRect(hWnd,NULL,FALSE);
UpdateWindow(hWnd); pbs - это указатель на структуру с хэндлами, коорднатами и прочей внутриклассовой ересью. pbs->hbmMemO - то, что вернула SelectObject() при привязке битмапа к DC wr - структура RECT, результат выполнения GetClientRect() pbs->hMFDC - DC, полученный при вызове CreateEnhMetaFile() HDC PaintBox_CreateMetaFile(PPaintBoxStruct pbs, TCHAR lpFileName[], const LPRECT rect)
Собственно, это и весь код, который выполняется при ресайзе. Просто ресайзить достаточно, чтобы накапливались тормоза, никаких рисований дополнительно не требуется.
-
уверен что pbs->hbmMemO != NULL? попробуй DeleteObject(SelectObject(pbs->hdcMem,pbs->hbmMem));
-
Выкроил наконец-то время.
pbs->hbmMemO != NULL, гарантированно. Отладчик не врёт, SelectObject() возвращает корректный хэндл, равный сохранённому ранее в pbs->hbmMem. Удаление происходит корректно.
С OllyDbg в зубах выяснил, что утечка происходит при отрисовке PlayEnhMetaFile(), причём, похоже, только тогда, когда отрисовка идёт в DC нового метафайла. При отрисовке в обычный DC утечек, похоже, нет.
Кроме того, сделав EnumEnhMetaFile() и поставив бряк в callback-функции, выяснил, что уже при первой отрисовке помимо мелочей вроде SetBkColor() в DC нового метафайла отрисовывается всякая экзотика вроде TextOut() и RoundRect(), хотя ничего подобного в исходном метафайле не было.
Из упоминаний утечек нарыл только про утечку в Win9x, но конкретно у меня сейчас проблема в WinXP, а по ней замечаний гугл не даёт. :(
-
Наткнулся на краткое упоминание про утечку в остальных системах. Но ответа на вопрос, как этого избежать, там, к сожалению, нет. А тормоза и правда ощутимые. :(
|