Конференция "WinAPI" » Метафайлы тормозят при ресайзе
 
  • ProgRAMmer Dimonych © (30.09.10 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 (01.10.10 00:02) [1]
    пользуюсь метафайлами регулярно.
    ты бы код привел, воспроизводивший проблему...
  • ProgRAMmer Dimonych © (01.10.10 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 (11.10.10 17:24) [3]
    уверен что pbs->hbmMemO != NULL?
    попробуй DeleteObject(SelectObject(pbs->hdcMem,pbs->hbmMem));
  • ProgRAMmer Dimonych © (26.10.10 21:36) [4]
    Выкроил наконец-то время.

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

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

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

    Из упоминаний утечек нарыл только про утечку в Win9x, но конкретно у меня сейчас проблема в WinXP, а по ней замечаний гугл не даёт. :(
  • ProgRAMmer Dimonych © (28.10.10 01:04) [5]
    Наткнулся на краткое упоминание про утечку в остальных системах. Но ответа на вопрос, как этого избежать, там, к сожалению, нет. А тормоза и правда ощутимые. :(
 
Конференция "WinAPI" » Метафайлы тормозят при ресайзе
Есть новые Нет новых   [134431   +11][b:0][p:0.001]