最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c# - Drawing image to datagridview doesn't show up until cells repaint - Stack Overflow

programmeradmin1浏览0评论

I'm building a "sequencer style" application. In part of it, I want to draw the waveform of an audio sample onto a row. However, the image doesn't fully appear until the cells it crosses are updated, either by selecting them, scrolling offscreen, or resizing. See gif below for examples:

I do the image draw in RowPrePaint

private void trackEditor_RowPrePaint(object sender, DataGridViewRowPrePaintEventArgs e)
{
    //I only prepaint PLAY SAMPLE rows, as they're the only ones that display waveforms
    if (SequencerObjects[e.RowIndex].category == "PLAY SAMPLE") {
        //PLAY SAMPLE cells get locked out of CellPainting(), so I paint them here first
        //BEFORE drawing the waveform, otherwise the waveform gets covered
        RowPrePainting = true;
        e.PaintCells(e.RowBounds, DataGridViewPaintParts.All);
        RowPrePainting = false;

        //this check is done here instead of with the first if statement, so that the row cells are still painted even if the row has no values set.
        if (!SequencerObjects[e.RowIndex].data_points.Any(x => x.value != null))
            return;
        //values used later in drawing the bitmap
        int offsetportion = (trackEditor.Columns[3].Width - trackEditor.FirstDisplayedScrollingColumnHiddenWidth) + trackEditor.RowHeadersWidth + (trackEditor.Columns[0].Width * 3);
        int columnindex = trackEditor.FirstDisplayedScrollingColumnIndex - FrozenColumnOffset + 1;
        Sequencer_Object seqref = SequencerObjects[e.RowIndex];
        SampleData samp = TCLE.ProjectSamples.FirstOrDefault(x => x.obj_name == seqref.obj_name);
        //if samp is null, it won't have an audio file we can process into a wave
        if (samp == null) {
            return;
        }
        if (seqref.WaveBitmap == null) {
            ///Bunch of code here for math and creating the bitmap itself
            ///
        }
        //once the bitmap is created, now we can draw it
        foreach (SeqDataPoint sdp in seqref.data_points.Where(x => x.value != null)) {
            //if image location start would be offscreen, don't bother drawing it
            if (sdp.beat > columnindex + trackEditor.DisplayedColumnCount(true) && sdp.beat + samp.beats < columnindex)
                continue;
            //math to offset drawing the wave horizontally based on where the active beats are
            e.Graphics.DrawImage(seqref.WaveBitmap, ((sdp.beat - columnindex) * cellwidth) + offsetportion, e.RowBounds.Top + 2);
        }
    }
}

As I understand it, painting is triggered in this order: RowPrePaint -> CellPainting -> RowPostPaint.

The image is drawn in RowPrePaint. I have to draw it here since it spans multiple cells. I tried to draw it in CellPainting at first but the graphics object available there is for 1 cellbounds only. I exclude all the cells for that row in CellPainting. If those cells would be drawn again, they paint over the waveform image. If I draw the waveform in RowPostPaint, then it paints over everything else (header, frozen columns, etc).

So part of my dilemma is that the waveform needs to be bottom-most (so it's drawn behind the header and frozen columns), yet still span across and on top of multiple cells.

The Question Is How can I trigger a repaint of the row's cells so that the waveform shows up, as it does when the cells are resized or selected?

If I programmatically resize the cells, that will re-fire the painting methods in a loop constantly. Same with select/deselect.

发布评论

评论列表(0)

  1. 暂无评论