Writing text to the system tray instead of an icon

2020-06-01 04:57发布

I am trying to display 2-3 updatable characters in the system tray rather than display an .ico file - similar to what CoreTemp does when they display the temperature in the system try:

enter image description here

I am using a NotifyIcon in my WinForms application along with the following code:

Font fontToUse = new Font("Microsoft Sans Serif", 8, FontStyle.Regular, GraphicsUnit.Pixel);
Brush brushToUse = new SolidBrush(Color.White);
Bitmap bitmapText = new Bitmap(16, 16);
Graphics g = Drawing.Graphics.FromImage(bitmapText);

IntPtr hIcon;
public void CreateTextIcon(string str)
{
    g.Clear(Color.Transparent);
    g.DrawString(str, fontToUse, brushToUse, -2, 5);
    hIcon = (bitmapText.GetHicon);
    NotifyIcon1.Icon = Drawing.Icon.FromHandle(hIcon);
    DestroyIcon(hIcon.ToInt32);
}

Sadly this produces a poor result nothing like what CoreTemp gets:

enter image description here

You'd think the solution would be to increase the font size, but anything over size 8 doesn't fit inside the image. Increasing the bitmap from 16x16 to 32x32 does nothing either - it gets resized down.

Then there's the problem of me wanting to display "8.55" instead of just "55" - there's enough space around the icon but it appears unusable.

enter image description here

Is there a better way to do this? Why can windows do the following but I cannot?

enter image description here

Update:

Thanks for @NineBerry for a good solution. To add, I find Tahoma to be the best font to use.

1条回答
来,给爷笑一个
2楼-- · 2020-06-01 05:50

This gives me a quite good looking display of a two digit string:

enter image description here

private void button1_Click(object sender, EventArgs e)
{
    CreateTextIcon("89");
}

public void CreateTextIcon(string str)
{
    Font fontToUse = new Font("Microsoft Sans Serif", 16, FontStyle.Regular, GraphicsUnit.Pixel);
    Brush brushToUse = new SolidBrush(Color.White);
    Bitmap bitmapText = new Bitmap(16, 16);
    Graphics g = System.Drawing.Graphics.FromImage(bitmapText);

    IntPtr hIcon;

    g.Clear(Color.Transparent);
    g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit;
    g.DrawString(str, fontToUse, brushToUse, -4, -2);
    hIcon = (bitmapText.GetHicon());
    notifyIcon1.Icon = System.Drawing.Icon.FromHandle(hIcon);
    //DestroyIcon(hIcon.ToInt32);
}

What I changed:

  1. Use a larger font size, but move the x and y offset further to the left and top (-4, -2).

  2. Set TextRenderingHint on the Graphics object to disable anti-aliasing.

It seems impossible to draw more than 2 digits or characters. The icons have a square format. Any text longer than two characters would mean reducing the height of the text a lot.

The sample where you select the keyboard layout (ENG) is actually not a notification icon in the tray area but its very own shell toolbar.


The best I could achieve to display 8.55:

enter image description here

private void button1_Click(object sender, EventArgs e)
{
    CreateTextIcon("8'55");
}

public void CreateTextIcon(string str)
{
    Font fontToUse = new Font("Trebuchet MS", 10, FontStyle.Regular, GraphicsUnit.Pixel);
    Brush brushToUse = new SolidBrush(Color.White);
    Bitmap bitmapText = new Bitmap(16, 16);
    Graphics g = System.Drawing.Graphics.FromImage(bitmapText);

    IntPtr hIcon;

    g.Clear(Color.Transparent);
    g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit;
    g.DrawString(str, fontToUse, brushToUse, -2, 0);
    hIcon = (bitmapText.GetHicon());
    notifyIcon1.Icon = System.Drawing.Icon.FromHandle(hIcon);
    //DestroyIcon(hIcon.ToInt32);
}

with the following changes:

  1. Use Trebuchet MS which is a very narrow font.
  2. Use the single quote instead of the dot because it has less space at the sides.
  3. Use font size 10 and adapt the offsets adequately.
查看更多
登录 后发表回答