2012-04-23 18 views
6

पर मेरा कस्टम नियंत्रण है जो एक कस्टम खींचे गए दस्तावेज़ कैनवास पर ज़ूम करता है।ऑटोस्क्रॉल सेट के साथ स्क्रॉल करने योग्य कंट्रोल का उपयोग कैसे करें

मैंने ऑटोस्क्रोल का उपयोग करने की कोशिश की लेकिन यह संतोषजनक परिणाम नहीं दे रहा था। जब मैं ऑटोस्क्रॉलपोजिशन और ऑटोस्क्रॉलमिन्स साइज को वापस (किसी भी क्रम में) सेट करता हूं तो यह एक पेंट को मजबूर करेगा और जब भी ज़ूम बदलता है तो जिटर का कारण बनता है। मुझे लगता है कि ऐसा इसलिए था क्योंकि यह दोनों गुणों को संशोधित करते समय अद्यतन को कॉल कर रहा था और अमान्य नहीं था।

मैं अब मैन्युअल रूप से तो हर बार की तरह झूठी को AutoScroll सेट के साथ HorizontalScroll और VerticalScroll गुण स्थापित कर रहा हूँ ज़ूम स्तर या ग्राहक आकार परिवर्तन:

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; 

इस मामले में, FocusPoint एक है प्वाइंटएफ संरचना जो बिटमैप में निर्देशांक रखती है जिसे उपयोगकर्ता केंद्रित करता है (उदाहरण के लिए, जब वे ज़ूम इन करने के लिए माउस व्हील होते हैं तो वे उस समय वर्तमान माउस स्थान पर ध्यान केंद्रित कर रहे हैं)। यह कार्यक्षमता अधिकांश भाग के लिए काम करती है।

स्क्रॉल बार काम नहीं करता है। यदि उपयोगकर्ता स्क्रॉल बार पर क्लिक करके मैन्युअल रूप से स्क्रॉल करने का प्रयास करता है, तो वे दोनों 0 पर लौटते रहते हैं। मैं उन्हें अपने कोड में कहीं और सेट नहीं करता हूं। मैं विधि Onscroll() में निम्नलिखित लेखन की कोशिश की है:

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

Invalidate(); 

लेकिन इस flicking और सीमा से बाहर स्क्रॉल सहित कुछ बहुत ही अनियमित व्यवहार का कारण बनता है।

मुझे ऑनस्क्रॉल के लिए कोड कैसे लिखना है? मैंने आधार की कोशिश की है। ऑनस्क्रॉल लेकिन ऑटोस्क्रॉल को गलत पर सेट करते समय यह कुछ भी नहीं किया।

+0

मुझे लगता है कि आपको पहली बार यह सही था। पहले AutoScrollMinSize सेट करें, फिर AutoScrollPosition पर कॉल करें। झिलमिलाहट को नियंत्रित करने के लिए डबल-बफर किए गए पैनल का उपयोग करें। – LarsTech

+0

मेरा नियंत्रण डबल buffered था। यह कभी भी फ्लिकर नहीं हुआ जब मैं एक ही समय में ऑटोस्क्रॉलमिन और ऑटोस्क्रॉलपोजिशन दोनों को बदल दूंगा। –

उत्तर

3

मैंने 3 बाल नियंत्रण बनाकर अपनी खुद की कस्टम स्क्रॉलिंग को कार्यान्वित किया: एक एचएसक्रॉलबार, एक वीएसक्रॉलबार, और एक पैनल।

मैं ClientSize और ClientRectangle छिपाने तो जैसे:

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 
     ); 
    } 
} 

लेआउट OnClientSizeChanged में किया जाता है:

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

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); 
} 

प्रत्येक स्क्रॉलपट्टी उनके स्क्रॉल घटना के बाद की सदस्यता ली है

और अंत में हम माउसव्हील घटनाओं निम्नलिखित के साथ स्क्रॉल करने के लिए अनुमति दे सकते हैं:

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)); 
    } 
} 

कस्टम चित्रकला के लिए, आप निम्न कथन का प्रयोग करेंगे:

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

यह वर्तमान खामियों जब AutoScroll का उपयोग किए बिना पूरी तरह से काम किया।