-1

基本上,我创建了面板类的扩展,它在自身上添加了多个位图,以创建多个五线谱。我尝试在面板上添加一个垂直滚动条,但没有奏效。我的 Paint 过程与此类似

private void StavePanel_Paint(object sender, PaintEventArgs e)
{
    for(int i = 0; i < linenumber; i++)
    {
        Bitmap bmp = new Bitmap(Width, 200);
        //edit bmp to resemble stave
        e.Graphics.DrawImage(bmp,new Point(0,200*i);
    }
}
4

4 回答 4

1

只需设置 AutoScrollMinSize 属性:

panel1.AutoScrollMinSize = new Size(0, 1000);

在绘制事件期间,您需要使用 TranslateTransform 方法转换绘图的位置。此外,您需要在绘制位图后处理它们:

e.Graphics.TranslateTransform(panel1.AutoScrollPosition.X, panel1.AutoScrollPosition.Y);

using (Bitmap bmp = new Bitmap(Width, 200)) {
  //edit bmp to resemble stave
  e.Graphics.DrawImage(bmp,new Point(0,200*i);
}

或提前创建和存储它们,以避免在绘制事件期间产生该成本。

于 2015-10-06T19:10:37.430 回答
0

如果您想继续使用调用 GDI 代码的现有模式来绘制控件,则应添加滚动条控件并将事件处理程序添加到其更改事件。.Invalidate除了在面板上调用之外,更改处理程序不需要做任何事情。.Invalidate 是向控件发出的信号,表明它“脏”并且需要重绘。您将需要修改您的绘画代码以在滚动条值的相反方向上偏移绘图。

因此,如果您的滚动条位于 50 位置,则应在 Y - 50 处绘制所有内容。

如果您使用纯 GDI 绘图代码,则根本不需要弄乱 AutoScroll 属性。仅当您的面板托管的实际控件大于面板时才使用此选项。

于 2015-10-06T19:04:18.840 回答
0

正如其他人提到的,您需要设置AutoScroll为true。但是之后,任何时候添加或删除位图(或者在开始时,如果它们是固定的),您需要AutoScrollMinSize使用公式设置高度bitmapCount * bitmapHeight。同样在您的油漆处理程序中,您需要考虑该AutoScrollPosition.Y属性。

下面是这个概念的一个小例子:

using System;
using System.Drawing;
using System.Windows.Forms;

namespace Tests
{
    static class Program
    {
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            var form = new Form();
            var panel = new Panel { Dock = DockStyle.Fill, Parent = form };
            // Setting the AutoScrollMinSize
            int bitmapCount = 10;
            int bitmapHeight = 200;
            panel.AutoScrollMinSize = new Size(0, bitmapCount * bitmapHeight);
            panel.Paint += (sender, e) =>
            {
                // Considering the AutoScrollPosition.Y
                int offsetY = panel.AutoScrollPosition.Y;
                var state = offsetY != 0 ? e.Graphics.Save() : null;
                if (offsetY != 0) e.Graphics.TranslateTransform(0, offsetY);
                var rect = new Rectangle(0, 0, panel.ClientSize.Width, bitmapHeight);
                var sf = new StringFormat(StringFormat.GenericTypographic) { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center };
                for (int i = 0; i < bitmapCount; i++)
                {
                    // Your bitmap drawing goes here
                    e.Graphics.FillRectangle(Brushes.Yellow, rect);
                    e.Graphics.DrawRectangle(Pens.Red, rect);
                    e.Graphics.DrawString("Bitmap #" + (i + 1), panel.Font, Brushes.Blue, rect, sf);
                    rect.Y += bitmapHeight;
                }
                if (state != null) e.Graphics.Restore(state);
            };
            Application.Run(form);
        }
    }
}

编辑:正如LarsTech在评论中正确提到的那样,在这种情况下,您实际上并不需要设置AutoScroll属性。所有其他保持不变。

于 2015-10-06T19:38:42.800 回答
0

AutoScroll属性设置为 true。

您也可以考虑替代方案:

  • FlowLayoutPanel并动态添加图片框而不是绘画。
  • TableLayoutPanel并动态添加图片框而不是绘画。
  • 扩展ListBox并将DrawMode属性设置为OwnerDrawFixedorOwnerDrawVariable然后覆盖方法OnPaintand OnMeasureItem(仅适用于OwnerDrawVariable)。
于 2015-10-06T18:51:06.330 回答