2012-04-23 33 views
6

Tôi có một điều khiển tùy chỉnh phóng to trên canvas tài liệu được vẽ tùy chỉnh.Cách sử dụng ScrollableControl với AutoScroll được đặt thành false

Tôi đã thử sử dụng AutoScroll nhưng không mang lại kết quả khả quan. Khi tôi sẽ đặt AutoScrollPosition và AutoScrollMinSize trở lại trở lại (theo thứ tự bất kỳ) nó sẽ buộc một sơn và gây ra jitter mỗi khi thay đổi zoom. Tôi cho rằng điều này là bởi vì nó đã được gọi là Cập nhật và không làm mất hiệu lực khi tôi sửa đổi cả hai thuộc tính.

bây giờ tôi tự thiết lập các thuộc tính HorizontalScroll và VerticalScroll với AutoScroll set false như vậy mỗi lần mức zoom hay thay đổi kích thước của khách hàng:

int canvasWidth = (int)Math.Ceiling(Image.Width * Zoom) + PageMargins.Horizontal; 
int canvasHeight = (int)Math.Ceiling(Image.Height * Zoom) + PageMargins.Vertical; 

HorizontalScroll.Maximum = canvasWidth; 
HorizontalScroll.LargeChange = ClientSize.Width; 

VerticalScroll.Maximum = canvasHeight; 
VerticalScroll.LargeChange = ClientSize.Height; 

if (canvasWidth > ClientSize.Width) 
{ 
    HorizontalScroll.Visible = true; 
} 
else 
{ 
    HorizontalScroll.Visible = false; 
    HorizontalScroll.Value = 0; 
} 

if (canvasHeight > ClientSize.Height) 
{ 
    VerticalScroll.Visible = true; 
} 
else 
{ 
    VerticalScroll.Visible = false; 
    VerticalScroll.Value = 0; 
} 

int focusX = (int)Math.Floor((FocusPoint.X * Zoom) + PageMargins.Left); 
int focusY = (int)Math.Floor((FocusPoint.Y * Zoom) + PageMargins.Top); 

focusX = focusX - ClientSize.Width/2; 
focusY = focusY - ClientSize.Height/2; 

if (focusX < 0) 
    focusX = 0; 
if (focusX > canvasWidth - ClientSize.Width) 
    focusX = canvasWidth - ClientSize.Width; 

if (focusY < 0) 
    focusY = 0; 
if (focusY > canvasHeight - ClientSize.Height) 
    focusY = canvasHeight - ClientSize.Height; 

if (HorizontalScroll.Visible) 
    HorizontalScroll.Value = focusX; 

if (VerticalScroll.Visible) 
    VerticalScroll.Value = focusY; 

Trong trường hợp này, FocusPoint là một Cấu trúc PointF giữ tọa độ trong bitmap mà người dùng đang tập trung vào (ví dụ, khi bánh xe chuột để phóng to chúng đang tập trung vào vị trí chuột hiện tại tại thời điểm đó). Chức năng này hoạt động cho hầu hết các phần.

Điều gì không hoạt động là các thanh cuộn. Nếu người dùng cố gắng cuộn theo cách thủ công bằng cách nhấp vào thanh cuộn, cả hai đều tiếp tục quay lại 0. Tôi không đặt chúng ở bất kỳ nơi nào khác trong mã của tôi. Tôi đã thử viết những điều sau đây trong phương thức OnScroll():

if (se.ScrollOrientation == ScrollOrientation.VerticalScroll) 
{ 
    VerticalScroll.Value = se.NewValue; 
} 
else 
{ 
    HorizontalScroll.Value = se.NewValue; 
} 

Invalidate(); 

Nhưng điều này gây ra một số hành vi rất thất thường bao gồm cả việc trượt và di chuyển ngoài giới hạn.

Tôi phải viết mã cho OnScroll như thế nào? Tôi đã thử base.OnScroll nhưng nó không làm bất cứ điều gì trong khi AutoScroll được đặt thành false.

+0

Tôi nghĩ bạn đã có nó ngay lần đầu tiên. Đặt AutoScrollMinSize trước, sau đó gọi AutoScrollPosition. Sử dụng bảng điều khiển đệm đôi để điều khiển nhấp nháy. – LarsTech

+0

Điều khiển của tôi được đệm đôi. Nó không bao giờ nhấp nháy trừ khi tôi sẽ thay đổi cả AutoScrollMinSize và AutoScrollPosition cùng một lúc. –

Trả lời

3

Tôi đã kết thúc triển khai cuộn tùy chỉnh của riêng mình bằng cách tạo 3 điều khiển con: HScrollBar, VScrollBar và Bảng điều khiển.

Tôi giấu ClientSize và ClientRectangle như vậy:

public new Rectangle ClientRectangle 
{ 
    get 
    { 
     return new Rectangle(new Point(0, 0), ClientSize); 
    } 
} 

public new Size ClientSize 
{ 
    get 
    { 
     return new Size(
      base.ClientSize.Width - VScrollBar.Width, 
      base.ClientSize.Height - HScrollBar.Height 
     ); 
    } 
} 

Cách bố trí được thực hiện trong OnClientSizeChanged:

protected override void OnClientSizeChanged(EventArgs e) 
{ 
    base.OnClientSizeChanged(e); 

    HScrollBar.Location = new Point(0, base.ClientSize.Height - HScrollBar.Height); 
    HScrollBar.Width = base.ClientSize.Width - VScrollBar.Width; 

    VScrollBar.Location = new Point(base.ClientSize.Width - VScrollBar.Width, 0); 
    VScrollBar.Height = base.ClientSize.Height - HScrollBar.Height; 

    cornerPanel.Size = new Size(VScrollBar.Width, HScrollBar.Height); 
    cornerPanel.Location = new Point(base.ClientSize.Width - cornerPanel.Width, base.ClientSize.Height - cornerPanel.Height); 
} 

Mỗi ScrollBar có họ Scroll kiện đăng ký như sau:

private void ScrollBar_Scroll(object sender, ScrollEventArgs e) 
{ 
    OnScroll(e); 
} 

Và cuối cùng chúng tôi có thể cho phép sự kiện mousewheel để di chuyển như sau:

protected override void OnMouseWheel(MouseEventArgs e) 
{ 
    int xOldValue = VScrollBar.Value; 

    if (e.Delta > 0) 
    { 
     VScrollBar.Value = (int)Math.Max(VScrollBar.Value - (VScrollBar.SmallChange * e.Delta), 0); 
     OnScroll(new ScrollEventArgs(ScrollEventType.ThumbPosition, xOldValue, VScrollBar.Value, ScrollOrientation.VerticalScroll)); 
    } 
    else 
    { 
     VScrollBar.Value = (int)Math.Min(VScrollBar.Value - (VScrollBar.SmallChange * e.Delta), VScrollBar.Maximum - (VScrollBar.LargeChange - 1)); 
     OnScroll(new ScrollEventArgs(ScrollEventType.ThumbPosition, xOldValue, VScrollBar.Value, ScrollOrientation.VerticalScroll)); 
    } 
} 

Đối với sơn tùy chỉnh, bạn sẽ sử dụng câu lệnh sau:

e.Graphics.TranslateTransform(-HScrollBar.Value, -VScrollBar.Value); 

này đã làm việc một cách hoàn hảo mà không có sự ổn định hiện nay khi sử dụng AutoScroll.

Các vấn đề liên quan