根据 BackColor 反转文本颜色

Posted

技术标签:

【中文标题】根据 BackColor 反转文本颜色【英文标题】:Invert Text Color depending on BackColor 【发布时间】:2017-04-18 15:02:38 【问题描述】:

我有一个ProgressBar 控件,如下两个:

第一个画得很好。如您所见,第二个只有一个0,它应该有两个但另一个看不到,因为ProgressBar的ForeColorTextColor相同。当下面的ProgressBar 用 Lime 绘制时,有没有办法可以将文本绘制为黑色,而当背景为黑色时,我可以用 Lime 绘制文本?

【问题讨论】:

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

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

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 属性上添加一些验证。

【讨论】:

这正是我所需要的!谢谢!

以上是关于根据 BackColor 反转文本颜色的主要内容,如果未能解决你的问题,请参考以下文章

设置只读文本框默认Backcolor

如何获取 datagridview 单元格的 Style.BackColor

根据背景颜色反转 CSS 字体颜色

如何将控件的 BackColor(或其他属性)绑定到存储在 DataSource 中的字符串值?

如何使用 PyUNO 和 OpenOffice 设置文本背景颜色

C#文本框边框颜色如何改变