C#:在ProgressBar上覆盖OnPaint不起作用?

Svi*_*ish 6 c# controls overriding onpaint winforms

我认为应该很容易创建一个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);
    }
Run Code Online (Sandbox Code Playgroud)

但是,我没有文本,甚至似乎都没有调用这些方法.这里发生了什么?


更新:由于到目前为止的两个答案,我已经得到它实际调用OnPaint使用SetStyle(ControlStyles.UserPaint, true),我已经得到它通过发送new Rectangle(0, 0, Width, Height)而不是在正确的地方绘制文本Bounds.

我现在确实得到了文字,但是ProgressBar它已经消失了...而且重点是将文本置于文本之上ProgressBar.知道如何解决这个问题吗?

Chr*_*man 12

您可以覆盖WndProc并捕获WmPaint消息.

下面的示例在其中心绘制进度条的Text属性.

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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Ed *_* S. 6

我需要自己做这件事,我想我会发布一个简化的解决方案示例,因为我找不到任何例子.如果您使用ProgressBarRenderer类,实际上非常简单:

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 ); 
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Mus*_*sis 2

Bounds您的问题是您作为 Rectangle 参数传入。Bounds 包含控件的高度和宽度,这是您想要的,但它还包含控件相对于父窗体的 Top 和 Left 属性,因此您的“Hello”在控件上偏移了多少控件在其父窗体上偏移。

替换Boundsnew Rectangle(0, 0, this.Width, this.Height),您应该会看到“Hello”。