cscの作法 その454

# 概要
cscの作法、調べてみた。
フォーム、表示しないでタスクトレイに住み憑く、方法。

# 参考にしたページ

https://qiita.com/kob58im/items/8bca7a87890a66f8a425

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/5a862288-3b4a-1888-3e99-22cf61dcac41.png)

# サンプルコード

```
using System;
using System.ComponentModel;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Drawing.Drawing2D;

public static class Animator {
	public static void Animate(int interval, int frequency, Func<int, int, bool> callback) {
		var timer = new System.Windows.Forms.Timer();
		timer.Interval = interval;
		int frame = 0;
		timer.Tick += (sender, e) => {
			if (callback(frame, frequency) == false || frame >= frequency)
			{
				timer.Stop();
			}
			frame++;
		};
		timer.Start();
	}
	public static void Animate(int duration, Func<int, int, bool> callback) {
		const int interval = 25;
		if (duration < interval)
			duration = interval;
		Animate(25, duration / interval, callback);
	}
}
static class MyIconUtil {
	static class NativeMethods {
		[DllImport("user32.dll", CharSet = CharSet.Auto)]
		public extern static bool DestroyIcon(IntPtr handle);
	}
	public static Icon Create16x16Icon(string[] iconDot) {
		Bitmap bmp = new Bitmap(16, 16);
		using (Graphics g = Graphics.FromImage(bmp))
		{
			g.Clear(Color.White);
		}
		for (int y = 0; y < 16; y++)
		{
			for (int x = 0; x < 16; x++)
			{
				if (iconDot[y][x] == '#')
				{
					bmp.SetPixel(x, y, Color.Black);
				}
			}
		}
		IntPtr Hicon = bmp.GetHicon();
		return Icon.FromHandle(Hicon);
	}
	public static void DestroyIcon(Icon icon) {
		NativeMethods.DestroyIcon(icon.Handle);
	}
}
class TaskTrayTest {
	static string[] iconDot = new string[] {
		"................",
		".###...##...##..",
		"..#...#..#.#..#.",
		"..#...#....#..#.",
		"..#...#....#..#.",
		"..#...#....#..#.",
		"..#...#....#..#.",
		"..#...#....#..#.",
		"..#...#....#..#.",
		"..#...#....#..#.",
		"..#...#....#..#.",
		"..#...#....#..#.",
		"..#...#....#..#.",
		"..#...#..#.#..#.",
		".###...##...##..",
		"................",
	};
	TaskTrayTest() {
		NotifyIcon trayIcon = new NotifyIcon();
		Icon tmpIcon = MyIconUtil.Create16x16Icon(iconDot);
		trayIcon.Icon = tmpIcon;
		trayIcon.Visible = true;
		trayIcon.Text = "常駐テスト";
		var menu = new ContextMenuStrip();
		menu.Items.AddRange(new ToolStripMenuItem[] {
			new ToolStripMenuItem("&Open", null, (s, e) => {
				MyDoSomething();
			}, "Open"),
			new ToolStripMenuItem("E&xit", null, (s, e) => {
				MyExit();
			}, "Exit")
		});
		trayIcon.DoubleClick += (s, e) => {
			MyDoSomething();
		};
		trayIcon.ContextMenuStrip = menu;
	}
	void MyDoSomething() {
		Console.WriteLine("open is called.");
		using (var form = new Form())
		{
			form.FormBorderStyle = FormBorderStyle.None;
			form.StartPosition = FormStartPosition.Manual;
			var graphicsPath = new GraphicsPath();
			graphicsPath.AddString("★", new FontFamily("メイリオ"), 0, 50, new Point(0, 0), StringFormat.GenericDefault);
			form.Region = new Region(graphicsPath);
			form.Left = 100;
			form.Top = 100;
			form.BackColor = Color.White;
			form.Load += (sender, e) => {
				Animator.Animate(800, (frame, frequency) => {
					if (!form.Visible || form.IsDisposed)
						return false;
					form.Left = 100 + 800 * frame / frequency;
					form.Top = 100 + 800 * frame / frequency;
					if (frame == frequency)
						form.Close();
					return true;
				});
			};
			form.ShowDialog();
		}
	}
	void MyExit() {
		var e = new CancelEventArgs();
		Application.Exit(e);
		if (e.Cancel)
		{
			Console.WriteLine("Application.Exit is canceled.");
		}
	}
	[STAThread]
	static void Main(string[] args) {
		new TaskTrayTest();
		Application.Run();
	}
}




```


以上。