2009-10-04 13 views
5

सोच रहा था कि ProgressBar बनाने के लिए यह बहुत आसान होना चाहिए जिसने स्वयं कुछ टेक्स्ट खींचा है। हालांकि, मैं काफी यकीन है कि यहाँ क्या हो रहा है नहीं कर रहा हूँ ...सी #: प्रोग्रेसबार पर ऑनपेंट ओवरराइडिंग काम नहीं कर रहा है?

मैं निम्नलिखित दो ओवरराइड कहा:

protected override void OnPaintBackground(PaintEventArgs pevent) 
    { 
     base.OnPaintBackground(pevent); 
     var flags = TextFormatFlags.VerticalCenter | TextFormatFlags.HorizontalCenter | TextFormatFlags.SingleLine | TextFormatFlags.WordEllipsis; 
     TextRenderer.DrawText(pevent.Graphics, "Hello", Font, Bounds, Color.Black, flags); 
    } 

    protected override void OnPaint(PaintEventArgs e) 
    { 
     base.OnPaint(e); 
     var flags = TextFormatFlags.VerticalCenter | TextFormatFlags.HorizontalCenter | TextFormatFlags.SingleLine | TextFormatFlags.WordEllipsis; 
     TextRenderer.DrawText(e.Graphics, "Hello", Font, Bounds, Color.Black, flags); 
    } 

हालांकि, मैं कोई पाठ मिलता है, और तरीकों भी कहा जा प्रतीत नहीं होता है । यहाँ क्या हो रहा है?


अद्यतन: दो जवाब के लिए धन्यवाद अब तक, मैं यह मिल गया है वास्तव में का उपयोग करके OnPaint कॉल करने के लिए, और मैं इसे बजाय new Rectangle(0, 0, Width, Height) में भेज कर सही जगह में पाठ आकर्षित करने के लिए मिल गया है Bounds का।

मुझे अब टेक्स्ट मिल गया है, लेकिन ProgressBar चला गया है ... और बिंदु ProgressBar के शीर्ष पर टेक्स्ट होना था। कोई विचार है कि मैं इसे कैसे हल कर सकता हूं?

उत्तर

1

आपकी समस्या यह है कि आप अपने Rectangle पैरामीटर के रूप में Bounds में गुजर रहे हैं। बाउंड्स में आपके नियंत्रण की ऊंचाई और चौड़ाई होती है, जो आप चाहते हैं, लेकिन इसमें आपके नियंत्रण के शीर्ष और बाएं गुण भी शामिल हैं, जो मूल रूप से संबंधित हैं, इसलिए आपका "हैलो" नियंत्रण पर ऑफ़सेट हो रहा है नियंत्रण अपने मूल रूप से ऑफसेट है।

Boundsnew Rectangle(0, 0, this.Width, this.Height) के साथ बदलें और आपको अपना "हैलो" देखना चाहिए।

+0

ओह। अच्छी पकड़। – Svish

1

ऐसा लगता है कि यदि आप 'SetStyle (ControlStyles.UserPaint, true)' कहते हैं, तो प्रोग्रेसबार के लिए लागू मानक ऑनपेंट विधि को लागू नहीं किया जा सकता है (बेस.ऑनपेंट (ई) का उपयोग करके बिल्कुल काम नहीं करता है)। अजीब चीज यह है कि यदि आप वास्तव में उपयोगकर्ता नियंत्रण बनाते हैं, और प्रगति पट्टी पर कुछ पाठ खींचने का प्रयास करते हैं ... यह भी काम नहीं कर रहा है ... बेशक आप इसके ऊपर एक लेबल डाल सकते हैं। .. लेकिन मुझे लगता है कि यह वास्तव में वह नहीं है जिसे आप प्राप्त करना चाहते थे।

ठीक है, ऐसा लगता है कि मैंने इस समस्या को हल करने में कामयाब रहा है। हालांकि यह थोड़ा जटिल है। सबसे पहले आपको पारदर्शी लेबल नियंत्रण बनाना होगा। नीचे दिए गए कोड:

public class TransparentLabel : System.Windows.Forms.Label 
{ 
    public TransparentLabel() 
    { 
     this.SetStyle(ControlStyles.Opaque, true); 
     this.SetStyle(ControlStyles.OptimizedDoubleBuffer, false); 
    } 

    protected override CreateParams CreateParams 
    { 
     get 
     { 
      CreateParams cp = base.CreateParams; 
      cp.ExStyle |= 0x20; 
      return cp; 
     } 
    } 
} 

दूसरी बात यह (डॉक = भरण) पर UserControl एक ProgressBar बनाने के लिए, जगह है - इस पर नियंत्रण है कि हम मानक ProgressBar के बजाय का उपयोग करेगा हो जाएगा। कोड:

public partial class UserControl2 : UserControl 
{ 
    public UserControl2() 
    { 
     InitializeComponent(); 
    } 

    protected override void OnPaint(PaintEventArgs e) 
    { 
     this.progressBar1.SendToBack(); 
     this.transparentLabel1.BringToFront(); 
     this.transparentLabel1.Text = this.progressBar1.Value.ToString(); 
     this.transparentLabel1.Invalidate(); 
    } 

    public int Value 
    { 
     get { return this.progressBar1.Value; } 
     set 
     { 
      this.progressBar1.Value = value; 
     } 
    } 
} 

ProgressBar साथ अजीब बात यह है कि यह overdraws 'नियंत्रण है कि यह पर रखा जा रहा है, तो यह वापस करने के लिए, और सामने के लिए लेबल नियंत्रण लाने के प्रगति बार भेजने के लिए जरूरत है। मुझे इस समय और अधिक सुरुचिपूर्ण समाधान नहीं मिला है। यह काम करता है, लेबल प्रगति पट्टी पर प्रदर्शित किया जा रहा है, लेबल नियंत्रण की पृष्ठभूमि पारदर्शी है, इसलिए मुझे लगता है कि ऐसा लगता है कि आप इसे देखना चाहते थे :)

यदि आप चाहें तो मैं अपना नमूना कोड साझा कर सकता हूं ..

ओह, बीटीडब्ल्यू। प्रोग्रेसबार नियंत्रण का यह अजीब व्यवहार मैंने उल्लेख किया है, इसके लिए जिम्मेदार है कि प्रोग्रेसबार से प्राप्त नियंत्रण पर कुछ भी आकर्षित करने के लिए ग्राफिक्स ऑब्जेक्ट का उपयोग करना संभव नहीं है। टेक्स्ट (या जो भी आप ग्राफिक्स ऑब्जेक्ट का उपयोग करते हैं) वास्तव में खींचा जा रहा है लेकिन ... प्रोग्रेसबार नियंत्रण के पीछे (यदि आप नज़दीकी नजर रखते हैं, तो आप इस उपयोगकर्ता को खींचना चीजें झटकेदार देख सकते हैं जब प्रोग्रेसबार का मूल्य बदलता है और इसे करने की आवश्यकता होती है खुद को पुनर्जीवित करें)।

+0

ठीक है, यह वही है जो मैं प्राप्त करना चाहता हूं। समस्या यह है कि जब मैं इसके ऊपर एक लेबल डालता हूं, तो प्रगति पट्टी छिपी हुई है। मैंने एक पारदर्शी लेबल बनाने की कोशिश की, लेकिन यह काम नहीं किया, क्योंकि प्रोग्रेसबार बदलने के बाद यह गायब हो गया। – Svish

+0

यदि आप UserControl बनाते हैं, तो पहले प्रोग्रेसबार (और शायद 'SendItBack') डालने का प्रयास करें, फिर प्रोग्रेसबार पर लेबल नियंत्रण रखें। कार्य करना चाहिए। समस्या यह है कि, लेबल की पृष्ठभूमि को पारदर्शी बनाने के लिए कैसे - मैं इस समय इसके लिए समाधान पर काम कर रहा हूं ... – MaciekTalaska

+0

एचएम, अब यह दिलचस्प है ... इसे बाद में आजमाने की ज़रूरत होगी :) – Svish

4

मुझे इसे स्वयं करने की ज़रूरत है और मैंने सोचा कि मैं अपने समाधान का सरलीकृत उदाहरण पोस्ट करूंगा क्योंकि मुझे कोई उदाहरण नहीं मिला।

class MyProgressBar : ProgressBar 
{ 
    public MyProgressBar() 
    { 
     this.SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true); 
    } 

    protected override void OnPaint(PaintEventArgs e) 
    { 
     Rectangle rect = this.ClientRectangle; 
     Graphics g = e.Graphics; 

     ProgressBarRenderer.DrawHorizontalBar(g, rect); 
     rect.Inflate(-3, -3); 
     if (this.Value > 0) 
     { 
      Rectangle clip = new Rectangle(rect.X, rect.Y, (int)Math.Round(((float)this.Value/this.Maximum) * rect.Width), rect.Height); 
      ProgressBarRenderer.DrawHorizontalChunks(g, clip); 
     } 

     // assumes this.Maximum == 100 
     string text = this.Value.ToString() + '%'; 

     using (Font f = new Font(FontFamily.GenericMonospace, 10)) 
     { 
      SizeF strLen = g.MeasureString(text, f); 
      Point location = new Point((int)((rect.Width/2) - (strLen.Width/2)), (int)((rect.Height/2) - (strLen.Height/2))); 
      g.DrawString(text, f, Brushes.Black, location); 
     } 
    } 
} 
+0

और didn ' मेरे समाधान आपके लिए काम नहीं करते? मैंने दो अलग-अलग मशीनों पर परीक्षण किया है और यह उन सभी पर ठीक काम करना प्रतीत होता है। – MaciekTalaska

+0

मैंने इसे आजमाया नहीं है, मैंने कोड को मैन्युअल रूप से एक प्रगति पट्टी खींचने के लिए इस्तेमाल किया था और फिर पाठ बिट जोड़ा। –

+0

यह मैंने देखा है सबसे अच्छा समाधान है। –

11

आप WndProc ओवरराइड और WmPaint संदेश पकड़ सकते थे: यह वास्तव में बहुत सरल है, तो आप ProgressBarRenderer वर्ग का उपयोग करें।

नीचे दिया गया उदाहरण इसके केंद्र में प्रगति पट्टी की टेक्स्ट प्रॉपर्टी को चित्रित करता है।

public class StatusProgressBar : ProgressBar 
{ 
    const int WmPaint = 15; 

    protected override void WndProc(ref Message m) 
    { 
     base.WndProc(ref m); 

     switch (m.Msg) 
     { 
      case WmPaint: 
       using (var graphics = Graphics.FromHwnd(Handle)) 
       { 
        var textSize = graphics.MeasureString(Text, Font); 

        using(var textBrush = new SolidBrush(ForeColor)) 
         graphics.DrawString(Text, Font, textBrush, (Width/2) - (textSize.Width/2), (Height/2) - (textSize.Height/2)); 
       } 
       break; 
     } 
    } 
} 
+0

यह सुनिश्चित करने के लिए सबसे अच्छा समाधान है – Kosmos

0

अन्य लोगों के सुझावों के साथ यहां एक और समाधान है। मैंने इस काम को करने के लिए प्रोग्रेसबार नियंत्रण को उपclassed। मैं इसके लिए विभिन्न स्थानों से मिश्रित और मिलान कोड। पेंट इवेंट क्लीनर हो सकता है, लेकिन यह आपके लिए है;)

public class LabeledProgressBar: ProgressBar 
    { 
     private string labelText; 

     public string LabelText 
     { 
     get { return labelText; } 
     set { labelText = value; } 
     } 

     public LabeledProgressBar() : base() 
     { 
     this.SetStyle(ControlStyles.UserPaint, true); 
     this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); 

     this.Paint += OnLabelPaint; 
     } 

     public void OnLabelPaint(object sender, PaintEventArgs e) 
     { 
     using(Graphics gr = this.CreateGraphics()) 
     { 
     string str = LabelText + string.Format(": {0}%", this.Value); 
     LinearGradientBrush brBG = new LinearGradientBrush(e.ClipRectangle, 
      Color.GreenYellow, Color.Green, LinearGradientMode.Horizontal); 
     e.Graphics.FillRectangle(brBG, e.ClipRectangle.X, e.ClipRectangle.Y, 
      e.ClipRectangle.Width * this.Value/this.Maximum, e.ClipRectangle.Height); 
     e.Graphics.DrawString(str, SystemFonts.DefaultFont,Brushes.Black, 
      new PointF(this.Width/2 - (gr.MeasureString(str, SystemFonts.DefaultFont).Width/2.0F), 
      this.Height/2 - (gr.MeasureString(str, SystemFonts.DefaultFont).Height/2.0F))); 
     } 
     } 
    } 
संबंधित मुद्दे