LoginSignup
2
2

More than 3 years have passed since last update.

C#(csc.exe) - トレイアイコンをクリックするとToast通知を出すサンプル

Last updated at Posted at 2019-12-05

サンプルアプリの仕様概要

Windows10で動作します。ただしVisual Studio等でWindows SDK入れてないとwindows.winmdファイルがなくてコンパイルできないっぽい

  • アイコンを左クリックで通知が出ます。(連打すると通知が延々と何度も出るので注意)
  • アイコンを右クリック→Exitで終了できます。

image.png

ソースコード

ToastNotificationManager.CreateToastNotifier("Microsoft.Windows.Computer");のところはかなり強引です。1


using System;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;

using Windows.UI.Notifications;

public static class IconUtil
{
    static class NativeMethods
    {
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public extern static bool DestroyIcon(IntPtr handle);
    } 

    static readonly string[] iconDot = new string[]{
        "................",
        ".###.###..##.###",
        "..#..#...#....#.",
        "..#..#...#....#.",
        "..#..#...#....#.",
        "..#..#...#....#.",
        "..#..#...#....#.",
        "..#..###..#...#.",
        "..#..#.....#..#.",
        "..#..#.....#..#.",
        "..#..#.....#..#.",
        "..#..#.....#..#.",
        "..#..#.....#..#.",
        "..#..#.....#..#.",
        "..#..###.##...#.",
        "................",
    };

    public static Icon MakeDefaultIcon()
    {
        using ( Bitmap bmp = new Bitmap(16,16) ) {
            using ( Graphics g = Graphics.FromImage(bmp) ) {
                g.Clear(Color.Blue);
            }
            for(int y=0;y<16;y++){
                for(int x=0;x<16;x++){
                    if (iconDot[y][x]=='#') {
                        bmp.SetPixel(x,y,Color.Yellow);
                    }
                }
            }

            IntPtr Hicon = bmp.GetHicon();
            return Icon.FromHandle(Hicon);
        }
    }

    public static void DestroyIcon(Icon ico)
    {
        NativeMethods.DestroyIcon(ico.Handle);
    }
}

class TaskTrayLauncher
{
    NotifyIcon trayIcon;

    static void ShowSampleToast()
    {
        string xmlStr = File.ReadAllText("sample.xml", Encoding.GetEncoding("Shift_JIS"));
        var content = new Windows.Data.Xml.Dom.XmlDocument();
        content.LoadXml(xmlStr);
        var notifier = ToastNotificationManager.CreateToastNotifier("Microsoft.Windows.Computer");
        notifier.Show(new ToastNotification(content));
    }

    TaskTrayLauncher()
    {
        trayIcon = new NotifyIcon();
        Icon tmpIcon = IconUtil.MakeDefaultIcon();
        trayIcon.Icon = tmpIcon;
        trayIcon.Visible = true;

        trayIcon.Text = "Launcher";
        var menu = new ContextMenuStrip();
        var menuItem = new ToolStripMenuItem();

        menu.Items.AddRange(new ToolStripMenuItem[]{
            new ToolStripMenuItem("E&xit", null, (s,e)=>{Application.Exit();}, "Exit")
        });

        trayIcon.MouseClick += TrayIcon_MouseClick;
        trayIcon.ContextMenuStrip = menu;
    }

    void TrayIcon_MouseClick(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left) {
            ShowSampleToast();
        }
        // 右クリックはcontextmenuを表示させるので、ここでは何もしない
    }

    [STAThread]
    static void Main(string[] args)
    {
        new TaskTrayLauncher();
        Application.Run();
    }
}

toastのxml

同じフォルダにおいてください。
Shift_JIS2で保存してください。

sample.xml

<toast activationType='foreground' launch='args'>
    <visual>
        <binding template='ToastGeneric'>
            <text>test</text>
            <text>testtest</text>
        </binding>
    </visual>
    <audio src='ms-winsoundevent:Notification.SMS' />
</toast>

コンパイルバッチ

使い方:
compile.bat ファイル名.cs

compile.bat

csc /r:C:\Windows\Microsoft.NET\assembly\GAC_MSIL\System.Runtime.WindowsRuntime\v4.0_4.0.0.0__b77a5c561934e089\system.runtime.windowsruntime.dll ^
/r:C:\Windows\Microsoft.NET\assembly\GAC_MSIL\System.Runtime.InteropServices.WindowsRuntime\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Runtime.InteropServices.WindowsRuntime.dll ^
/r:C:\Windows\Microsoft.NET\assembly\GAC_MSIL\System.Runtime\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Runtime.dll ^
"/r:C:\Program Files (x86)\Windows Kits\8.1\References\CommonConfiguration\Neutral\Annotated\Windows.winmd" %*

参考記事(参考サイト)

  1. Win向け通知アプリにトーストを使う - Qiita
  2. Windows 10 でトースト通知を飛ばす - みかづきメモ

ボタンの追加とイベント処理

参考記事2にあるように、xmlを修正すればToast通知上にボタンを追加することは簡単にできるのですが、
参考記事1で言及されている通り、イベントを受け取るのは困難で、特に、
https://docs.microsoft.com/ja-jp/windows/uwp/design/shell/tiles-and-notifications/send-local-toast-desktop#step-4-implement-the-activator
にあるGUIDの登録が必要になるっぽいです。


  1. 詳しくは参考記事1のコードの説明を参照ください。 

  2. UTF-8を使うべきだと思いますが、PC環境の私的な事情でShift_JISにしています・・ 

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2