Полный customdraw

Тема в разделе "WASM.WIN32", создана пользователем cresta, 11 сен 2007.

  1. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Как рисовать итемы и субитемы листвью вручную? Т.е. сделать полный CUSTOM DRAW?
    Рисование на уровне возврата из callback цвета фона и шрифта не устраивает.
    Нужно перерисовывать полностью, чтобы выделение (selected item) не распространялось на нулевой субитем. И чтобы можно было произвольно выбрать цвет выделения.
    Я в этих возвращаемых из callback значениях запутался полностью :dntknw:

    Може есть пример какой?

    [​IMG]
     
  2. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    В RSDN не смотрел? Там есть 90% ответов на подобные вопросы.
    Выделение, как и заливку фона, желательно рисовать один раз при отрисовке первого подэлемента, рамку его получать через GetItemRect(LVIR_SELECTBOUNDS).

    Пример с MFC:
    Код (Text):
    1. afx_msg void CColoredCtrl::OnNMCustomdraw(NMHDR* pNMHDR, LRESULT* pResult)
    2. {
    3.     LPNMLVCUSTOMDRAW nmcd = reinterpret_cast<LPNMLVCUSTOMDRAW>(pNMHDR);
    4.     *pResult = CDRF_DODEFAULT; // по умолчанию на любом этапе рисует система
    5.  
    6.     const unsigned int CDDS_SUBITEMPREPAINT = CDDS_ITEM|CDDS_SUBITEM|CDDS_PREPAINT;
    7.  
    8.     if(nmcd->nmcd.dwDrawStage == CDDS_PREPAINT)
    9.         // говорим, что будем рисовать элементы
    10.         *pResult = CDRF_NOTIFYITEMDRAW;
    11.     else if(nmcd->nmcd.dwDrawStage == CDDS_ITEMPREPAINT){
    12.         // почему-то по-умолчанию прямоугольник элемента пуст, заполняем его
    13.         GetItemRect(nmcd->nmcd.dwItemSpec, &nmcd->nmcd.rc, LVIR_BOUNDS);
    14.         // говорим, что будем рисовать подэлементы тоже
    15.         *pResult |= CDRF_NOTIFYSUBITEMDRAW;
    16.     }else if(nmcd->nmcd.dwDrawStage == CDDS_SUBITEMPREPAINT){
    17.         int nitem = nmcd->nmcd.dwItemSpec;
    18.         ColoredItem* item = reinterpret_cast<ColoredItem*>(nmcd->nmcd.lItemlParam); // свои данные
    19.         CRect rc = nmcd->nmcd.rc;
    20.  
    21.         // получаем состояние подэлемента
    22.         LVITEM lvi = {LVIF_STATE};
    23.         lvi.iItem = nitem;
    24.         lvi.iSubItem = nmcd->iSubItem;
    25.         lvi.stateMask = LVIS_SELECTED|LVIS_FOCUSED;
    26.         GetItem(&lvi);
    27.  
    28.         // здесь идёт отрисовка в nmcd->nmcd.hdc.
    29.         // Но заливать фон нужно только, когда идёт отрисовка 1го подэлемента (nmcd->iSubItem == 0)
    30.  
    31.         *pResult = CDRF_SKIPDEFAULT; // говорим, что сделали всё сами
    32.     }
    33. }
     
  3. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    IceStudent

    Спасибо, с этим разобрался.
    Вот ещё одна проблема: как можно определить при перерисовке итема по pNmhdr->code == NM_CUSTOMDRAW какие итемы и с каким state будут отрисовываться следующими?
    Это нужно чтобы организовать раздельные select'ы: один selected итем среди root'ов, и один среди child'ов.
    Пока что я отслеживаю LVN_ITEMCHANGING и по этому сообщению запоминаю в глобальных нужную информацию(какой итем активируется и какой деактивируется), но почему-то иногда не снимается выделение старого итема, возможно это связано с опозданием LVN_ITEMCHANGING. И поэтому приходится ещё делать InvalidateRect листа по LVN_ITEMCHANGED, чтобы закрепить изменения. А это приводит к небольшим мерцаниям листа.
    Уже весь msdn вспахал - ничего не вижу...
     
  4. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    Ну, можно просто взять состояние следующего элемента.

    Я делал примерно так же для упрощения (две переменные, под фокус и выделение) и ускорения работы (не надо опрашивать все элементы, чтобы определить, кто сейчас в фокусе).

    Не снимается системой? Если ты хранишь состояние отдельно (или хотя бы часть его, относящуюся к выделению), то имеет смысл при отрисовке элемента сбрасывать у всех выделение и выставлять его только у нужных. Но как делать правильно — я не в курсе; вообще, с этим custom draw больше проблем, чем пользы и зачастую приходится выходить из тупика написанием собственного контрола :)
     
  5. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Да, я тоже пришел к выводу, что надо писать свой контрол, чтобы всё было красиво :)
    Может взять treewiev и скрестить его с listview...
    Такие treelistview существуют, но я видел только для .net.
     
  6. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    codeproject смотрел?
     
  7. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    смотрел. Поиск по сайту выдал только для vb.net/c#.
    На programmersheaven нашел один без ремарок vb.net/c#, закачал а при установке инсталлятор потребовал framework :dntknw: