Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2018.04.22;
Скачать: CL | DM;

Вниз

Метафайлы тормозят при ресайзе   Найти похожие ветки 

 
ProgRAMmer Dimonych ©   (2010-09-30 21:46) [0]

Пишу "графический редактор" с использованием 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 начинает занимать несколько секунд.

Все метафайлы создаются в памяти, без привязки к файлам на диске.

Сталкивался ли кто-нибудь с такой проблемой?


 
Дмитрий Тимохов 2   (2010-10-01 00:02) [1]

пользуюсь метафайлами регулярно.
ты бы код привел, воспроизводивший проблему...


 
ProgRAMmer Dimonych ©   (2010-10-01 01:10) [2]

На сях он, правда :)

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)
{
 int iWidthMM, iHeightMM, iWidthPels, iHeightPels;
 RECT tr;

 if (rect == NULL)
   return CreateEnhMetaFile(pbs->hdcMem,lpFileName,NULL,NULL);

 iWidthMM    = GetDeviceCaps(pbs->hdcMem,HORZSIZE);
 iHeightMM   = GetDeviceCaps(pbs->hdcMem,VERTSIZE);
 iWidthPels  = GetDeviceCaps(pbs->hdcMem,HORZRES);
 iHeightPels = GetDeviceCaps(pbs->hdcMem,VERTRES);

 tr = *rect;
 tr.left   = (tr.left   * iWidthMM  * 100) / iWidthPels;
 tr.top    = (tr.top    * iHeightMM * 100) / iHeightPels;
 tr.right  = (tr.right  * iWidthMM  * 100) / iWidthPels;
 tr.bottom = (tr.bottom * iHeightMM * 100) / iHeightPels;
 return CreateEnhMetaFile(pbs->hdcMem,lpFileName,&tr,NULL);
}


Собственно, это и весь код, который выполняется при ресайзе. Просто ресайзить достаточно, чтобы накапливались тормоза, никаких рисований дополнительно не требуется.


 
han_malign   (2010-10-11 17:24) [3]

уверен что pbs->hbmMemO != NULL?
попробуй DeleteObject(SelectObject(pbs->hdcMem,pbs->hbmMem));


 
ProgRAMmer Dimonych ©   (2010-10-26 21:36) [4]

Выкроил наконец-то время.

pbs->hbmMemO != NULL, гарантированно. Отладчик не врёт, SelectObject() возвращает корректный хэндл, равный сохранённому ранее в pbs->hbmMem. Удаление происходит корректно.

С OllyDbg в зубах выяснил, что утечка происходит при отрисовке PlayEnhMetaFile(), причём, похоже, только тогда, когда отрисовка идёт в DC нового метафайла. При отрисовке в обычный DC утечек, похоже, нет.

Кроме того, сделав EnumEnhMetaFile() и поставив бряк в callback-функции, выяснил, что уже при первой отрисовке помимо мелочей вроде SetBkColor() в DC нового метафайла отрисовывается всякая экзотика вроде TextOut() и RoundRect(), хотя ничего подобного в исходном метафайле не было.

Из упоминаний утечек нарыл только про утечку в Win9x, но конкретно у меня сейчас проблема в WinXP, а по ней замечаний гугл не даёт. :(


 
ProgRAMmer Dimonych ©   (2010-10-28 01:04) [5]

Наткнулся на краткое упоминание про утечку в остальных системах. Но ответа на вопрос, как этого избежать, там, к сожалению, нет. А тормоза и правда ощутимые. :(



Страницы: 1 вся ветка

Текущий архив: 2018.04.22;
Скачать: CL | DM;

Наверх




Память: 0.48 MB
Время: 0.006 c
4-1288182533
Morgan128
2010-10-27 16:28
2018.04.22
Запуск процесса


15-1471959711
Игорь Шевченко
2016-08-23 16:41
2018.04.22
Раздается Delphi 10.1 starter edition


2-1459763922
Dmk
2016-04-04 12:58
2018.04.22
Вращение


15-1470208803
Юрий Зотов
2016-08-03 10:20
2018.04.22
Разновидность шахмат


2-1461311382
istok20
2016-04-22 10:49
2018.04.22
массив из oleacc.IAccessible через TList