3

I am trying to create a very simple system tray icon that is nothing but a dynamically colored circle with a white border. To do that, we are using the Webdings font. "n" in Webdings is just a plain circle.

What I'm currently doing is almost there, but on some PC's (yet not all) it ends up having a choppy, ugly black border around it:

enter image description here

Here's what I've got:

protected static Icon GetTrayIconFromCache(Color statusColor)
{
    Bitmap bmp = new Bitmap(16,16);                            
    Graphics circleGraphic = Graphics.FromImage(bmp);
    circleGraphic.DrawString("n", new Font("Webdings", 12F, FontStyle.Regular), Brushes.White, -3f, -2f);
    circleGraphic.DrawString("n", new Font("Webdings", 9F, FontStyle.Regular), new SolidBrush(statusColor), 0f, -1f);
    Icon ico = Icon.FromHandle((bmp).GetHicon());
    return ico;
}

No matter what I try, I can't get rid of those ugly black dots around the outside of the circle. They don't show up for everyone.... some of the developers don't see it and it looks crisp and clean. We've not yet figured out what the commonality is between those PC's where it looks good and where it doesn't.

But... is there a better way to do this?

Equalsk
  • 7,954
  • 2
  • 41
  • 67
Casey Crookston
  • 13,016
  • 24
  • 107
  • 193
  • Why not using two bitmaps instead? – Isma Jan 02 '18 at 12:18
  • Possibly the ones witht the ugly border have a different screen resolution, or they may have deactivated cleartype in their display settings? – LocEngineer Jan 02 '18 at 12:19
  • @Isma, because the color of the inner circle needs to be dynamic. It represents a status color, and in the app, the user can set their status to any color they want. – Casey Crookston Jan 02 '18 at 12:24
  • @LocEngineer, the cleartype may very well be the problem, but we can't force users to set it so that our system try icon looks good. There *must* be a way to generate an icon that looks crisp either way. – Casey Crookston Jan 02 '18 at 12:25
  • Bitmap.GetHIcon() is very troublesome, it only supports generating an icon with a palette containing 16 colors. That never ends well on a bitmap that contains anti-aliased text or line art. Consider [this code](https://stackoverflow.com/a/21389253/17034). You may need to use SystemInformation.IconSize instead of hard-coding 16x16 to avoid resize artifacts that ruin the anti-aliasing effect. – Hans Passant Jan 02 '18 at 12:37

1 Answers1

5

Add a TextRenderingHint of AntiAliasGridFit.

protected static Icon GetTrayIconFromCache(Color statusColor)
{
    Bitmap bmp = new Bitmap(16,16);                            
    Graphics circleGraphic = Graphics.FromImage(bmp);

    circleGraphic.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;

    circleGraphic.DrawString("n", new Font("Webdings", 12F, FontStyle.Regular), Brushes.White, -3f, -2f);
    circleGraphic.DrawString("n", new Font("Webdings", 9F, FontStyle.Regular), new SolidBrush(statusColor), 0f, -1f);
    Icon ico = Icon.FromHandle((bmp).GetHicon());
    return ico;
}
Equalsk
  • 7,954
  • 2
  • 41
  • 67