具有自动滚动重绘功能的面板

Panel with auto scroll redraw

我有以编程方式在其中添加面板的表单;

对于进入我的程序的每个任务,我添加一个标签并 面板的进度条已将 30 像素 Y 添加到先前的 Y 位置。

但是当面板有时想要向下滚动时滚动, 位置成倍增加,而不是在他们的确切位置。

记住,我检查并写入 Y 位置到控制台,看到 Y 位置没问题,但面板显示不正确

我认为问题出在面板绘制方法上, 但不知道如何解决。

问题是任务 26 应该紧接在 25 之后,但位置不正确,尽管我看到控制台的位置是正确的。

添加控件的代码:

 private static void AddTaskControls(int taskId)
        {
            Label lbl = new Label();
            lbl = new Label();
            lbl.Name = "lbl" + taskId.ToString();
            lbl.Text = "Task " + taskId.ToString() + ":";
            lbl.Width = 57;
            lbl.Height = 13;
            lbl.Location = new Point(0, 25 + (taskId) * 30);

            ProgressBar pr = new ProgressBar();
            pr = new ProgressBar();
            pr.Name = "pr" + taskId.ToString();
            pr.Width = 180;
            pr.Height = 23;
            pr.Location = new Point(50, 20 + (taskId) * 30);

            Label lbl2 = new Label();
            lbl2.Name = "lbl" + taskId.ToString() + "List";
            lbl2.Text = "Starting " + taskId.ToString() + "";
            lbl2.Width = 200;
            lbl2.Height = 13;
            lbl2.Location = new Point(230, 25 + (taskId) * 30);
            //Console.WriteLine(lbl2.Location.Y + "taskid:"+taskId);


            if (panel1.InvokeRequired)
            {
                AddTaskControllsCallback t = new AddTaskControllsCallback(AddTaskControls);
                panel1.BeginInvoke(t, new object[] { taskId });
            }
            else
            {
                panel1.Controls.Add(lbl);
                panel1.Controls.Add(pr);
                panel1.Controls.Add(lbl2);               

                pr.BringToFront();                
            }
        }

这与线程无关。添加控件时,当前滚动位置用于重新计算 有效 Location .诡异的?是的..

所以原因可能是您在添加新控件时Panel向下滚动。我看不出它发生在哪里,但这里有一个小测试来证明这个问题:

是不是很眼熟?

我在代码中强制执行滚动,但在您的情况下,原因应该类似,修复也应该如此..

private void button20_Click(object sender, EventArgs e)
{
    // lets add a few buttons..
    for (int i = 0; i < 20; i++)
    {
        Button btn = new Button();
        btn.Top = i * 25;
        btn.Parent = panel2;
    }
    // ..now let's enforce a scoll amount of 111 pixels:
    panel2.AutoScrollPosition =  new Point(panel2.AutoScrollPosition.X, 
                                            -panel2.AutoScrollPosition.Y + 111);

    // ..and add a few more buttons..
    for (int i = 20; i < 40; i++)
    {
        Button btn = new Button();
        btn.Top = i * 25;    // not good enough!
        // btn.Top = i * 25 + panel2.AutoScrollPosition.Y; // this will fix the problem!
        btn.Parent = panel2;
    }
}

因此您的代码需要像这样设置 Locations

lbl.Location = new Point(0, 25 + (taskId) * 30 + panel1.AutoScrollPosition.Y);
..
pr.Location = new Point(50, 20 + (taskId) * 30 + panel1.AutoScrollPosition.Y));
..
lbl2.Location = new Point(230, 25 + (taskId) * 30 + panel1.AutoScrollPosition.Y));

(或者你找出滚动是如何发生的并阻止它。)

我发现在可滚动面板内添加第二个面板、将控件添加到第二个面板并增加第二个面板的大小要容易得多。滚动位置的任何问题都不适用。

因此创建一个表单,添加一个按钮,添加一个面板 panel1AutoScroll = true;,然后在第一个面板(位置 0、0)内添加另一个面板 panel2

private void button1_Click(object sender, EventArgs e)
{
    // lets add a few buttons..
    for (int i = 0; i < 25; i++)
    {
        Button btn = new Button();
        btn.Top = i * 25;
        panel2.Controls.Add(btn); // Add to panel2 instead of panel1
    }

    // Recalculate size of the panel in the scrollable panel
    panel2.Height = panel2.Controls.Cast<Control>().Max(x => x.Top + x.Size.Height);
    panel2.Width = panel2.Controls.Cast<Control>().Max(x => x.Left + x.Size.Width);
}