【问题标题】:Override Label OnPaint?覆盖标签 OnPaint?
【发布时间】:2013-07-07 12:45:13
【问题描述】:

我正在尝试使用 FillPath 在我自己的自定义控件中覆盖标签的 OnPaint 方法。

这是我的控件代码:

public partial class GlassLabel : Label
{
    public GlassLabel()
    {
        InitializeComponent();
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        Graphics g = this.CreateGraphics();
        GraphicsPath path = new GraphicsPath();
        SolidBrush br = new SolidBrush(Color.Black);
        path.AddString("LLOOOOLL", new FontFamily("Microsoft Sans Serif"), (int)FontStyle.Regular, 12, new Point(55, 55), StringFormat.GenericDefault);
        g.SmoothingMode = SmoothingMode.HighQuality;
        g.FillPath(br, path);
    }
}

当我运行它时,标签的文本是一样的,它不使用 FillPath 绘制。

我试图覆盖标签的原因是我想在需要 FillPath 的 Aero 玻璃上使用它。如果我可以将图形(FillPath)转换为一个对象,以便我可以将事件附加到它,我也想知道这方面的信息。

谢谢。

刚试过:

e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
        e.Graphics.FillPath(br, path);

没用。

【问题讨论】:

  • 尝试使用 PaintEventArgs "e" 中的 Graphics 对象。
  • 放置一个断点并验证您的代码是否正在运行。还可以尝试删除对 base.OnPaint 的调用,作为临时测试。
  • 它达到了断点,但什么也没有。我已经删除了 base.OnPaint 它使标签根本不绘制。
  • 传统的 Winforms 文本绘图不能很好地支持这一点。最好的办法是 pinvoke DrawThemeTextEx() 这样您就可以使用 DTTSOPTS.iGlowSize 创建乳白色背景。将浏览器对准 google 以查找这些关键字的匹配结果。

标签: c# custom-controls label system.drawing


【解决方案1】:

不要创建新的 Graphics 对象,而是使用 PaintEventArgs 参数中提供的 e.Graphics

我不确定你想用GraphicsPath 实现什么。也许你可以改用TextRenderer

protected override void OnPaint(PaintEventArgs e)
{
    TextRenderer.DrawText(e.Graphics, "LLOOOOLL", Font, ClientRectangle, ForeColor, 
        TextFormatFlags.Left | TextFormatFlags.VerticalCenter); 
}

更新:

我将表格切换到 Aero Glass 并进行了一些测试。使用TextRendererGraphicsPath 的两种方法都可以工作,但是TextRenderer 的性能不是很好,因为ClearType 会在玻璃上产生伪影。

这些 API 声明是必需的

[StructLayout(LayoutKind.Sequential)]
public struct MARGINS
{
    public int Left;
    public int Right;
    public int Top;
    public int Bottom;
}

[DllImport("dwmapi.dll", PreserveSig = false)]
public static extern void DwmExtendFrameIntoClientArea (IntPtr hwnd, 
                                                        ref MARGINS margins);

[DllImport("dwmapi.dll", PreserveSig = false)]
public static extern bool DwmIsCompositionEnabled();

在表单的构造函数中我有这段代码

InitializeComponent();

if (DwmIsCompositionEnabled()) {
    // Stretch the margins into the form for the glass effect.
    MARGINS margins = new MARGINS();
    margins.Top = 300;
    DwmExtendFrameIntoClientArea(this.Handle, ref margins);
}

自定义Label 必须有黑色背景。黑色部分将显示为玻璃。它必须具有大约 (125, 70) 的最小尺寸才能适合您的文本,因为您从 (55, 55) 开始绘图。 (您的标签是否太小?)您必须将AutoSize 更改为false 才能更改标签的大小。这是自定义标签的代码

protected override void OnPaint(PaintEventArgs e)
{
    GraphicsPath path = new GraphicsPath();
    SolidBrush br = new SolidBrush(Color.FromArgb(1, 0, 0));
    path.AddString("LLOOOOLL", Font.FontFamily, (int)Font.Style, Font.SizeInPoints, 
                   new Point(55, 55), StringFormat.GenericDefault);
    e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
    e.Graphics.FillPath(br, path);
}

除了一些不同之处,它与您的代码相同。一个重要的区别是文本颜色必须不同于黑色;否则,它会显示为玻璃。我只取实际标签字体的字体属性。这样您就可以在属性窗口中更改其外观。


我在this article of TheCodeKing找到了玻璃效果的代码。

【讨论】:

  • 我没有测试我之前的例子。我的新示例略有不同,经过测试并且确实有效。它使用当前标签的FontClientRectangleForeColor
  • 该示例确实有效,但不适用于 Aero Glass。这就是问题所在,正常的标签渲染在玻璃上不起作用。
  • 我明白了。根据这个SO post,任何黑色的东西都会在玻璃上消失。尝试使用几乎黑色作为前景色Color.FromArgb(1,0,0)
  • 我做了一个完整的例子,因为我之前没用过玻璃效果。我没有工作,直到我意识到标签文本是在标签之外绘制的!在我增加了它的大小之后,一切都完美地醒来了。请查看我的更新。
  • 啊,我智障,不知道为什么我在 55,55 时画。无论如何,我现在可以看到文字,但不是绘图玻璃,它只是黑色背景。
【解决方案2】:

使用单个 cs 文件,您可以创建自己的标签控件

using System;
using System.Windows.Forms;

namespace GujControls
{
public partial class LABEL_BIRTHDATE : Label
{
    public LABEL_BIRTHDATE()
    {
        this.SuspendLayout();
        this.Font = GujWords.gujfont;
        this.Size = new System.Drawing.Size(70, 23);
        this.ResumeLayout();            
    }

    private System.ComponentModel.IContainer components = null;

    protected override void Dispose(bool disposing)
    {
        if (disposing && (components != null))
        {
            components.Dispose();
        }
        base.Dispose(disposing);
    }
    protected override void OnPaint(PaintEventArgs e)
    {
        TextRenderer.DrawText(e.Graphics, "NAME", Font,    ClientRectangle, ForeColor, TextFormatFlags.Left | TextFormatFlags.VerticalCenter);
    }
}
}

【讨论】:

  • 他将创建自定义控件.. 这也是使用过度使用的 OnPaint 方法创建自定义控件的一种简单方法
猜你喜欢
  • 2010-10-18
  • 2014-09-20
  • 1970-01-01
  • 2015-01-29
  • 2013-11-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-03
相关资源
最近更新 更多