向下滚动时面板丢失内容

时间:2013-04-24 11:06:41

标签: c# winforms scroll panel paint

我在一个较大的面板内有2个面板。 2个内部面板自动调整大小,外部面板自动滚动,以便我可以将我的2个面板的内容向下滚动。

我使用paint事件在右侧面板上绘制网格线,两者都有标签控件。

一切正常(也调整大小和响应)但是当我向下滚动时会出现奇怪的事情。

所以说当滚动条位于初始状态的顶部时,我会调用您看到的内容。然后当我向下滚动时,看不到这个初始状态,我调整大小/最小化/刷新......我的右手面板(带有网格线和标签)变灰,一切都消失了。

如果我再次向上滚动并触及初始状态的底部,标签和图形都会返回。

我知道这可能很难理解,但如果您认为可能有所帮助,请随时要求澄清任何内容。

The initial state 初始状态

After scrolling down and resizing/minimize - restoring... 向下滚动并调整大小/最小化 - 恢复...

Everything appears again when I reach something which was in the initial state

当我到达处于初始状态的东西时,一切都会再次出现

右侧面板的绘画事件(虽然我怀疑它会有多大用处)

private void panelPlanning_Paint(object sender, PaintEventArgs e)
    {
        for (int i = 0; i <= sub.Days + 1; i++)
        {
            if (toolStripButtonGrid.CheckState == CheckState.Checked)
            {
                if (vertGrid)
                {
                    if (dashedVert)
                    {
                        Pen blackPen = new Pen(Color.FromArgb(50, 0, 0, 0), 1);
                        blackPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;

                        e.Graphics.DrawLine(blackPen, i * labelDaysWidth, 0, i * labelDaysWidth, panelPlanning.Height);
                    }
                    else
                    {
                        Pen blackPen = new Pen(Color.FromArgb(50, 0, 0, 0), 1);
                        e.Graphics.DrawLine(blackPen, i * labelDaysWidth, 0, i * labelDaysWidth, panelPlanning.Height);
                    }
                }
            }
        }

        for (int i = 0; i < userList.Count; i++)
        {
            if (horGrid && toolStripButtonGrid.CheckState == CheckState.Checked)
            {
                if (dashedHor)
                {
                    Pen blackPen = new Pen(Color.FromArgb(50, 0, 0, 0), 1);
                    blackPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;

                    e.Graphics.DrawLine(blackPen, 0, i * userHeight, panelPlanning.Width, i * userHeight);
                }
                else
                {
                    Pen blackPen = new Pen(Color.FromArgb(50, 0, 0, 0), 1);
                    e.Graphics.DrawLine(blackPen, 0, i * userHeight, panelPlanning.Width, i * userHeight);
                }
            }
        }

        for (int i = 0; i <= sub.Days + 1; i++)
        {
            if (dtPickerStart.Value.AddDays(i) == DateTime.Today)
            {
                Pen blackpen = new Pen(Color.Black, 3);
                e.Graphics.DrawLine(blackpen, i * labelDaysWidth + labelDaysWidth / 2, 0, i * labelDaysWidth + labelDaysWidth / 2, panelPlanning.Height);
            }
        }

        if (userList.Count > 0)
        {
            panelPlanning.Height = userList.Count * userHeight;
            panelUsers.Height = userList.Count * userHeight;
        }
        if (nrResources == 0)
        {
            nrResources = 10;
        }
        userHeight = panel1.Height / nrResources;
    }

修改

https://www.dropbox.com/sh/p4k9zilmy5pq6ev/RpBEe05B3j

解决方案的简化版本给出了同样的问题。

编辑2

我已经能够解决大部分问题。下面是我更改的一些代码(要查看我更改的内容,您可以看到上面的Dropbox链接进行比较。

private void this_beginResize(object sender, EventArgs e)
{
    this.ResizeBegin -= new EventHandler(this_beginResize);

    panelPlanning.Paint -= new PaintEventHandler(panelPlanning_Paint);

    this.SuspendLayout();
    SuspendDrawing(panelTimeline);
    SuspendDrawing(panelPipeLine);
    SuspendDrawing(panel1);
}

我曾经删除ResizeEnd事件并稍后再添加它。我把它改成了ResizeBegin,因为这对我来说更有意义。

private void this_SizeChanged(object sender, EventArgs e)
{
    panelTimeline.Controls.Clear();
    sub = dtPickerEnd.Value - dtPickerStart.Value;
    addDayLabels(sub);

    panelUsers.Controls.Clear();
    addUserLabels();

    panelPlanning.Paint += new PaintEventHandler(panelPlanning_Paint);

    ResumeDrawing(panel1);
    ResumeDrawing(panelTimeline);
    ResumeDrawing(panelPipeLine);
    this.ResumeLayout();

    if (userList.Count > 0)
    {
        panelPlanning.Height = userList.Count * userHeight;
        panelUsers.Height = userList.Count * userHeight;
    }
    if (nrResources == 0)
    {
        nrResources = 10;
    }
    userHeight = panel1.Height / nrResources;
    lastPanelHeight = panel1.Height;

    panelPlanning.Controls.Clear();
    addPlanning();

    this.ResizeBegin += new EventHandler(this_beginResize);
}

当调整大小结束时,我习惯使计划面板成为容器面板的高度。这可能是我向下滚动时内容丢失的主要原因。 我用我的paint事件中的代码替换了它来计算高度。我还分配了一个变量lastPanelHeight,它跟踪下面方法的面板高度。 最大化和恢复事件在实际执行之前会在这里调用,因此我需要知道它们必须恢复到什么状态。

protected override void WndProc(ref Message m)
{
    if (m.Msg == 0x0112) // WM_SYSCOMMAND
    {
        // Check your window state here
        if (m.WParam == new IntPtr(0xF030) || m.WParam == new IntPtr(0xF120)) // Maximize event - SC_MAXIMIZE from Winuser.h
        {
            //Same code as the two above combined but with lastPanelHeight as value to do the calculations with
        }
    }
    base.WndProc(ref m);
}

,我仍然遇到问题。当我调整大小并且表单变大或者我从最大化或最小化状态恢复窗口时,滚动条以奇怪的方式运行。 当它一直向下并且形状变大时,它在面板中保持相同的高度,从而向上移动。 在恢复时,滚动条总是一直回到顶部。 任何想法?

1 个答案:

答案 0 :(得分:1)

经过初步改进(请参阅问题编辑2)我专注于滚动条,并在一段时间后让它工作。诀窍是在调整大小之前跟踪滚动条值和面板高度,并在调整大小后使用新高度计算它。滚动位置设置如下,但滚动条仍将显示在另一个位置。这可以通过启用和禁用滚动条来修复。完整的代码(请注意,有一个最大化和恢复的代码)下面。

/// The beginning of a form resize
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void this_beginResize(object sender, EventArgs e)
{
    lastLocation = this.Location;
    this.ResizeBegin -= new EventHandler(this_beginResize);

    panelPlanning.Paint -= new PaintEventHandler(panelPlanning_Paint);
    scrollvalue = panel1.VerticalScroll.Value;
    lastHeight = panel1.Height;

    this.SuspendLayout();
    SuspendDrawing(panelTimeline);
    SuspendDrawing(panelPipeLine);
    SuspendDrawing(panel1);
}

/// <summary>
/// Called when the form is done resizing
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void this_SizeChanged(object sender, EventArgs e)
{
    if (this.Location != lastLocation)
    {
        lastLocation = this.Location;
        return;
    }

    panelTimeline.Controls.Clear();
    sub = dtPickerEnd.Value - dtPickerStart.Value;
    addDayLabels(sub);

    panelUsers.Controls.Clear();
    addUserLabels();

    panelPlanning.Paint += new PaintEventHandler(panelPlanning_Paint);

    ResumeDrawing(panel1);
    ResumeDrawing(panelTimeline);
    ResumeDrawing(panelPipeLine);
    this.ResumeLayout();

    if (userList.Count > 0)
    {
        panelPlanning.Height = userList.Count * userHeight;
        panelUsers.Height = userList.Count * userHeight;
    }
    if (nrResources == 0)
    {
        nrResources = 10;
    }
    userHeight = panel1.Height / nrResources;

    panel1.VerticalScroll.Value = scrollvalue * panel1.Height / lastHeight;
    panel1.VerticalScroll.Enabled = false;

    panelPlanning.Controls.Clear();
    addPlanning();

    this.ResizeBegin += new EventHandler(this_beginResize);

    panel1.VerticalScroll.Enabled = true;
    panel1.VerticalScroll.Value = scrollvalue * panel1.Height / lastHeight;
}

/// <summary>
/// Handles maximize and restore
/// </summary>
/// <param name="m"></param>
protected override void WndProc(ref Message m)
{
    if (m.Msg == 0x0112) // WM_SYSCOMMAND
    {
        // Check your window state here
        if (m.WParam == new IntPtr(0xF030) || m.WParam == new IntPtr(0xF120)) // Maximize event - SC_MAXIMIZE from Winuser.h
        {
            this.ResizeBegin -= new EventHandler(this_beginResize);

            panelPlanning.Paint -= new PaintEventHandler(panelPlanning_Paint);
            scrollvalue = panel1.VerticalScroll.Value;

            if (panel1.Height != 0)
            {
                lastHeight = panel1.Height;
            }

            this.SuspendLayout();
            SuspendDrawing(panelTimeline);
            SuspendDrawing(panelPipeLine);
            SuspendDrawing(panel1);

            panel1.VerticalScroll.Enabled = false;
        }
    }

    base.WndProc(ref m);

    if (m.Msg == 0x0112) // WM_SYSCOMMAND
    {
        // Check your window state here
        if (m.WParam == new IntPtr(0xF030) || m.WParam == new IntPtr(0xF120)) // Maximize event - SC_MAXIMIZE from Winuser.h
        {
            panelTimeline.Controls.Clear();
            sub = dtPickerEnd.Value - dtPickerStart.Value;
            addDayLabels(sub);

            panelUsers.Controls.Clear();
            addUserLabels();

            panelPlanning.Paint += new PaintEventHandler(panelPlanning_Paint);

            ResumeDrawing(panel1);
            ResumeDrawing(panelTimeline);
            ResumeDrawing(panelPipeLine);
            this.ResumeLayout();

            if (userList.Count > 0)
            {
                panelPlanning.Height = userList.Count * userHeight;
                panelUsers.Height = userList.Count * userHeight;
            }
            if (nrResources == 0)
            {
                nrResources = 10;
            }
            userHeight = panel1.Height / nrResources;

            panel1.VerticalScroll.Value = scrollvalue * panel1.Height / lastHeight;
            panel1.VerticalScroll.Enabled = false;

            panelPlanning.Controls.Clear();
            addPlanning();

            this.ResizeBegin += new EventHandler(this_beginResize);

            panel1.VerticalScroll.Enabled = true;
            panel1.VerticalScroll.Value = scrollvalue * panel1.Height / lastHeight;
        }
    }
}