2

I'm trying to override the OnPaint method of a label in my own custom control with FillPath.

Here is my code for the control:

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);
    }
}

When I run it the text of the label is just the same, it doesn't draw with FillPath.

The reason I'm trying to override the label is I want to use it on Aero glass, which needs FillPath. If I could turn a graphics(the FillPath) in to an object so I can attach events to it, I would like info on that too.

Thanks.

Just tried:

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

Didnt work.

Tanner.R
  • 479
  • 1
  • 6
  • 15
  • Try to use the Graphics object from the PaintEventArgs "e". – Johann Blais Mar 13 '12 at 21:37
  • Put a break point and verify your code is being run. Also try removing the call to base.OnPaint just as a temporary test. – AaronLS Mar 13 '12 at 22:03
  • It hits the break point, but nothing draws. I have removed base.OnPaint it made the label not draw at all. – Tanner.R Mar 13 '12 at 22:22
  • 1
    This just isn't well supported by traditional Winforms text drawing. Best thing to do is pinvoke DrawThemeTextEx() so you can use the DTTSOPTS.iGlowSize to create the milky white background. Aim your browser at google to find the hits on these keywords. – Hans Passant Mar 14 '12 at 00:15

2 Answers2

8

Do not create a new Graphics object, but use e.Graphics provided in the PaintEventArgs argument.

I am not sure what you are trying to achieve with the GraphicsPath. Probably you could just use TextRenderer instead.

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

UPDATE:

I switched a form to Aero Glass and made some tests. Both approaches with TextRenderer and with GraphicsPath work, however the TextRenderer does not perform very well because ClearType produces artifacts on glass.

These API declarations are required

[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();

In the form's constructor I have this code

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);
}

The custom Label must have a black background. Black parts will display as glass. It must have a minimum size of about (125, 70) to fit your text because you start drawing at (55, 55). (Was your label too small?) You have to change the AutoSize to false in order to be able to change the size of the label. Here is the code for the custom label

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);
}

With a few differences, it is the same code as yours. An important difference is that the text color must be different from black; otherwise, it would appear as glass. I just take the font properties of the actual label font. This way you can change its appearance in the properties window.


I found the code for the glass effect in this article of TheCodeKing.

Olivier Jacot-Descombes
  • 104,806
  • 13
  • 138
  • 188
  • I did not test my previous example. My new example is slightly different, tested and does work. It uses the `Font`, `ClientRectangle`, and `ForeColor` of the current label. – Olivier Jacot-Descombes Mar 13 '12 at 22:10
  • That example did work, but not on the Aero Glass. Thats the problem, normal label rendering doesn't work on glass. – Tanner.R Mar 13 '12 at 22:17
  • I see. According to this [SO post](http://stackoverflow.com/questions/2936527/drawing-a-textbox-in-an-extended-glass-frame-w-o-wpf), anything black disappears on glass. Try to use almost black as forecolor `Color.FromArgb(1,0,0)`. – Olivier Jacot-Descombes Mar 13 '12 at 22:38
  • 1
    I made a complete example, because I never used the glass effect before. I did not work, until I realized that the label text was drawn outside of the label! After I had increased its size everything woked perfectly. Please see my update. – Olivier Jacot-Descombes Mar 14 '12 at 14:32
  • Ahh Im retarded, not sure why I was drawing at 55,55. Anyway I can see text now but its not drawing glass, its just a black background. – Tanner.R Mar 14 '12 at 17:31
  • It has to be within one of these extended margins and its background must be a real black (not like the foreground) and of cause it works only if your Windows displays glass! Check "Allow transparency" in `Control Panel\Appearance and Personalization\Personalization\Window Color and Appearance`. – Olivier Jacot-Descombes Mar 14 '12 at 17:40
  • Never mind I set the TransparentKey and all is well. Thanks for the help! – Tanner.R Mar 14 '12 at 17:46
  • Setting the TransparentKey will not create the blurred glass effect. – Olivier Jacot-Descombes Mar 14 '12 at 17:53
0

with a single cs file you can create your own label control

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);
    }
}
}
Jigar Parekh
  • 595
  • 10
  • 23
  • he is going to create custom control.. this is also one easy way to create custom control with over ridden OnPaint methos – Jigar Parekh Aug 04 '13 at 04:46