Изменение рендеринга ListView при рендеринге в CDDS_POSTPAINT

Итак, я потратил кучу времени, пытаясь отрендерить какой-нибудь текст. Мне, наконец, удалось кое-что получить, создав подкласс ListView и добавив переопределение WndProc следующим образом:

защищенное переопределение void WndProc (ссылка m) {base.WndProc (ref m);

            //NM_CUSTOMDRAW =-12
            switch( m.Msg )
            {
                case 0x004e://WM_NOTIFY:
                case 0x204e://WM_REFLECT_NOTIFY
                    {
                        NMHDR nmhdr     = (NMHDR)System.Runtime.InteropServices.Marshal.PtrToStructure( m.LParam, typeof( NMHDR ) );
                        if ( nmhdr.code == -12 )   //NM_CUSTOMDRAW
                        {
                            NMLVCUSTOMDRAW nmlvcd     = (NMLVCUSTOMDRAW)System.Runtime.InteropServices.Marshal.PtrToStructure( m.LParam, typeof( NMLVCUSTOMDRAW ) );
                            System.Diagnostics.Trace.WriteLine( nmlvcd.nmcd.dwDrawStage.ToString() );
                            if      ( nmlvcd.nmcd.dwDrawStage == 1 ) //CDDS_PREPAINT
                            {
                                int result  = (int)m.Result;
                                result      |= 0x10;//CDRF_NOTIFYPOSTPAINT;
                                m.Result    = (IntPtr)result;
                            }
                            else if ( nmlvcd.nmcd.dwDrawStage == 2 ) //CDDS_POSTPAINT
                            {
                                Graphics g  = Graphics.FromHdc( nmlvcd.nmcd.hdc );
                                if ( DrawFloatingItem != null )
                                { 
                                    PaintEventArgs pe   = new PaintEventArgs( g, nmlvcd.nmcd.rc );
                                    DrawFloatingItem( this, pe );
                                }
                            } 
                            else if ( nmlvcd.nmcd.dwDrawStage == 65537 )    //CDDS_ITEMPREPAINT 
                            {
                                int result  = (int)m.Result;
                                result      |= 0x10;//CDRF_NOTIFYPOSTPAINT;
                                m.Result    = (IntPtr)result;
                            }
                            else if ( nmlvcd.nmcd.dwDrawStage == 65538 )    //CDDS_ITEMPOSTPAINT 
                            {

                            }

                        }
                    }
                    break;
            }
        }

Благодаря этому мне удалось выполнить рендеринг в виде списка. Однако в тот момент, когда я выполняю рендеринг (из события DrawFloatingItem), все элементы сдвигаются вверх на высоту заголовка (т.е. первый элемент визуализируется под заголовком столбца).

Это список перед:

введите описание изображения здесь

И это список после:

введите описание изображения здесь

Кто-нибудь знает, что я здесь делаю не так? Если я закомментирую свои команды рисования (внутри функции «DrawFloatingItem»), то все будет работать, как ожидалось. Однако в тот момент, когда я рисую, рендеринг идет не так, как указано выше.

Любая помощь будет принята с благодарностью!


person Goz    schedule 19.12.2017    source источник
comment
Если вы не знаете, вы часто можете достичь того же результата, не погружаясь напрямую в базовый API: msdn.microsoft.com/en-us/library/   -  person Alex K.    schedule 19.12.2017
comment
@AlexK: OwnerDraw не позволяет обрабатывать PostPaint. И да ... Я уже установил OwnerDraw в значение true ... потому что, если бы я этого не сделал, NM_CUSTOMDRAW вообще не вызывался бы.   -  person Goz    schedule 19.12.2017


Ответы (1)


Как правило, я всегда понимаю это вскоре после публикации вопроса. Моя ошибка заключалась в том, что я не избавлялся от созданного мной объекта Graphics до вызова события DrawFloatingItem.

Изменение на следующее устранило проблему:

 using( Graphics g  = Graphics.FromHdc( nmlvcd.nmcd.hdc ) )
 { 
     if ( DrawFloatingItem != null )
     { 
         PaintEventArgs pe   = new PaintEventArgs( g, nmlvcd.nmcd.rc );
         DrawFloatingItem( this, pe );
     }
 }
person Goz    schedule 19.12.2017