根据背景色反转文本颜色

9

我有两个ProgressBar控件,如下图所示:

enter image description here

第一个是正确绘制的。正如您所看到的,第二个只有一个0,它应该有两个,但是另一个无法看到,因为ProgressBar的ForeColorTextColor相同。是否可以在下面的ProgressBar绘制为Lime时将文本绘制为黑色,并在背景为黑色时将文本绘制为Lime?


这是哪个进度条?它是内置的还是您正在使用一些自定义或第三方控件? - vendettamit
@vendettamit 抱歉,我忘记说明了,我正在使用 https://www.codeproject.com/tips/645899/csharp-alternative-progressbar - Asad Ali
1
如果文本只有一个部分,除非您使用位图和切换像素,否则不可能。如果您可以将其分成两个部分,您需要决定分割是否需要划分字符。无论如何都不是很容易。但是对于旧的异或绘图模式...我唯一便宜而简单的解决方案是在颜色上做出妥协,不要选择相同的(亮度)作为条形和文本。 - TaW
1
另一个技巧是不仅切换颜色,还要将对齐方式与50%以上或以下的值一起切换。 - TaW
1个回答

17
你可以先绘制背景和文字,然后使用 PatBlt 方法和 PATINVERT 参数来绘制前景石灰色矩形,以将前景绘图与背景绘图结合起来:

enter image description here

enter image description here

using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
public class MyProgressBar : Control
{
    public MyProgressBar() 
    {
        DoubleBuffered = true;
        Minimum = 0; Maximum = 100; Value = 50;
    }
    public int Minimum { get; set; }
    public int Maximum { get; set; }
    public int Value { get; set; }
    protected override void OnPaint(PaintEventArgs e) 
    {
        base.OnPaint(e);
        Draw(e.Graphics);
    }
    private void Draw(Graphics g) 
    {
        var r = this.ClientRectangle;
        using (var b = new SolidBrush(this.BackColor))
            g.FillRectangle(b, r);
        TextRenderer.DrawText(g, this.Value.ToString(), this.Font, r, this.ForeColor);
        var hdc = g.GetHdc();
        var c = this.ForeColor;
        var hbrush = CreateSolidBrush(((c.R | (c.G << 8)) | (c.B << 16)));
        var phbrush = SelectObject(hdc, hbrush);
        PatBlt(hdc, r.Left, r.Y, (Value * r.Width / Maximum), r.Height, PATINVERT);
        SelectObject(hdc, phbrush);
        DeleteObject(hbrush);
        g.ReleaseHdc(hdc);
    }
    public const int PATINVERT = 0x005A0049;
    [DllImport("gdi32.dll")]
    public static extern bool PatBlt(IntPtr hdc, int nXLeft, int nYLeft,
        int nWidth, int nHeight, int dwRop);
    [DllImport("gdi32.dll")]
    public static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);
    [DllImport("gdi32.dll", EntryPoint = "DeleteObject")]
    public static extern bool DeleteObject(IntPtr hObject);
    [DllImport("gdi32.dll")]
    public static extern IntPtr CreateSolidBrush(int crColor);
}

注意:该控件仅用于演示绘制逻辑。对于真实世界的应用程序,您需要在MinimumMaximumValue属性上添加一些验证。


这正是我所需要的!谢谢! - Asad Ali

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接