Tôi có một điều khiển tùy chỉnh bao gồm hình chữ nhật tròn được làm đầy với văn bản. (Điều khiển thực tế phức tạp hơn nhưng đoạn code được hiển thị ở đây có các triệu chứng sames). Tôi đã gắn các instance của control vào một Panel, và biến Panel đó thành con của một Panel khác với AutoScroll = true. Tôi nghĩ rằng đó là đủ cho hành vi di chuyển chính xác, nhưng nếu bạn di chuyển như vậy mà phía bên trái của điều khiển của tôi nên đi ra khỏi phía bên trái của bảng điều khiển nó dính và điều khiển co lại. Cùng với việc cuộn như vậy, điều khiển sẽ bị tắt ở trên cùng. (Phía dưới và bên phải dường như không phải là một vấn đề.) Đây là mã mẫu (yêu cầu tham chiếu đến System.Windows.Forms và System.Drawing.) Tôi đang sử dụng Visual Studio 2010 với .NET 4 client trên Windows.Cho phép điều khiển tùy chỉnh để di chuyển chính xác ra khỏi chế độ xem
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace CustomControlScrollTest
{
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
// Form with a Dock = Fill panel with autoscroll turned on, and a nested panel
// with few custom roundRectControls.
public class Form1 : Form
{
Panel autoScrollPanel;
Panel rectPanel;
public Form1()
{
Size = new Size(300, 200);
autoScrollPanel = new Panel();
autoScrollPanel.Dock = DockStyle.Fill;
autoScrollPanel.AutoScroll = true;
autoScrollPanel.AutoScrollMinSize = new Size(600, 450);
autoScrollPanel.Resize += autoScrollPanel_Resize;
autoScrollPanel.Scroll += autoScrollPanel_Scroll;
Controls.Add(autoScrollPanel);
rectPanel = new Panel();
rectPanel.Size = autoScrollPanel.AutoScrollMinSize;
rectPanel.Controls.AddRange(new RoundRectControl[] {
new RoundRectControl(),
new RoundRectControl(),
new RoundRectControl(),
new RoundRectControl(),
new RoundRectControl()
});
foreach (Control c in rectPanel.Controls)
{
c.Click += c_Click;
}
autoScrollPanel.Controls.Add(rectPanel);
placeBoxes();
}
// we want to be able to recalculate the boxes position at any time
// in the real program this occurs due to model changes
void c_Click(object sender, EventArgs e)
{
placeBoxes();
}
void autoScrollPanel_Scroll(object sender, ScrollEventArgs e)
{
Refresh();
}
void autoScrollPanel_Resize(object sender, EventArgs e)
{
Refresh();
}
private void placeBoxes()
{
for (int i = 0; i < rectPanel.Controls.Count; ++i)
{
int j = i + 1;
var node = rectPanel.Controls[i] as RoundRectControl;
if (node != null)
{
node.Title = "Hello (" + j + ")";
node.Location = new Point(i * 100, j * 75);
node.Visible = true;
}
}
}
}
// A rounded rectangle filled blue with a black border and white text
// the size is determined by the text
public class RoundRectControl : Control
{
public RoundRectControl()
{
var f = SystemFonts.MessageBoxFont;
titleFont = new Font(f.Name, f.SizeInPoints + 2, FontStyle.Bold, GraphicsUnit.Point);
ResizeRedraw = true;
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
var g = e.Graphics;
var left = e.ClipRectangle.X;
var right = left + titleWidth + 2 * radius;
var top = e.ClipRectangle.Y;
var bottom = top + nodeHeight + 2 * radius;
var r2 = 2 * radius;
using (var path = new GraphicsPath())
{
path.AddArc(left, bottom - r2, r2, r2, 90, 90);
path.AddArc(left, top, r2, r2, 180, 90);
path.AddArc(right - r2, top, r2, r2, 270, 90);
path.AddArc(right - r2, bottom - r2, r2, r2, 0, 90);
path.CloseFigure();
g.FillPath(titleBrush, path);
g.DrawPath(borderPen, path);
}
g.DrawString(title, titleFont, titleTextBrush, left + radius, top + radius);
}
private string title;
public string Title
{
get { return title; }
set
{
title = value;
Size = getSize();
Invalidate();
}
}
private Brush titleBrush = Brushes.Blue;
private Brush titleTextBrush = Brushes.White;
private Pen borderPen = Pens.Black;
private Size getSize()
{
var g = CreateGraphics();
var titleSize = g.MeasureString(title, titleFont);
titleWidth = (int)titleSize.Width;
nodeHeight = (int)titleSize.Height;
return new Size(titleWidth + 2 * radius + 1, nodeHeight + 2 * radius + 1);
}
public override Size GetPreferredSize(Size proposedSize)
{
return getSize();
}
private int titleWidth;
private int nodeHeight;
private Font titleFont;
private int radius = 5;
}
}
Trong trường hợp bất kỳ ai thắc mắc, không có lớp thiết kế, tôi muốn làm ví dụ hoàn toàn khép kín. (Thông báo không có lớp nào là một phần.) –