NotifyIcon to use from IronPython

IronPython スクリプトを快適に使いたい。
version 2.6 から Python モジュールも同梱になり更に便利になった。
そして .NET Framework のパワーがほぼ全てスクリプトのみで記述できる。
別途 SDK のインストールは不要、exe へのコンパイルも不要、言うことなし。

しかし欠点がある、初期化、つまり初回起動が遅すぎることである。
ならばタスクトレイに常駐させてしまえ!

MSDN: ContextMenu クラス (System.Windows.Forms)
MSDN: NotifyIcon クラス (System.Windows.Forms)
チュートリアル : Windows フォームの動的なコンテキスト メニューの作成

システムトレイ(タスクトレイ)にアイコンを表示するには? ? @IT
起動時にタスクトレイのアイコンのみを表示するには? ? @IT

なんかを参考に作ってみた、WindowsForm に頼るしか方法が無いみたい。
これじゃ当分 Microsoft はこの名前空間を外すことはできないな。

self.menu.MenuItems.Add("Exit", EventHandler(self.on_exit))

とする必要は無いみたい、PyGtk と同様に簡単に書けるのが IronPython の魅力。

しかし WindowsForm の Application クラスはインスタンスを作成しなくてもいいんだね。
WPF ばかりやっていたからチト調子が狂う。

ということでやってみた例。

notify_icon.pyw

# -*- coding: UTF-8 -*-

import clr

clr.AddReferenceByPartialName("System.Windows.Forms")
clr.AddReferenceByPartialName("System.Drawing")

from System import *
from System.IO import *
from System.Windows import *
from System.Windows.Forms import *
from System.Drawing import *

class NfIcon():
    """
        Task Tray Icon
    """
    def __init__(self):
        """
            Initialization
        """
        self.path = Path.GetDirectoryName(__file__)
        # create menu
        self.menu = ContextMenu()
        self.menu.MenuItems.Add("NotePad", self.on_notepad)
        self.menu.MenuItems.Add("Clipboard", self.on_clipboard)
        self.menu.MenuItems.Add("External file Execute", self.on_extern)
        self.menu.MenuItems.Add("-")
        self.menu.MenuItems.Add("Exit", self.on_exit)
        # create tray icon
        # Not inherit. this class is Sealed
        self.icon = NotifyIcon()
        self.icon.ContextMenu = self.menu
        self.icon.Icon = Icon(self.path + "\\icon.ico")
        self.icon.Text = "Description Text"
        self.icon.Visible = True

    def on_notepad(self, sender, e):
        """
            case Lancher
        """
        try:
            import os
            os.system("notepad.exe")
        except Exception, e:
            MessageBox.Show(e.Message)

    def on_clipboard(self, sender, e):
        """
            case Clipboard and Beep
        """
        try:
            Clipboard.SetText("Clipboard Text")
            Media.SystemSounds.Beep.Play()
        except Exception, e:
            MessageBox.Show(e.Message)

    def on_extern(self, sender, e):
        """
            case External file Execute
        """
        try:
            import extern
        except Exception, e:
            MessageBox.Show(e.Message)

    def on_exit(self, sender, e):
        """
            bye
        """
        self.icon.Visible = False
        Application.Exit()

if __name__ == "__main__":
    # Not Application.Run(NfIcon())
    NfIcon()
    Application.Run()

extern.py

# -*- coding: UTF-8 -*-

import clr

clr.AddReferenceByPartialName("System.Windows.Forms")

from System.Windows.Forms import *

MessageBox.Show("this File is extern.py")

ヘタクソな icon を同梱して zip にまとめたのも置いておくね。

notify_icon.zip

で、ipyw(64).exe にて notify_icon.pyw を起動させると常駐する。
アイコンを右クリックするとメニューが出るので選択すればよい。

常駐しているので初期化が必要なくなり高速にスクリプトを実行できる。
スタートアップに登録すれば簡単に使えるね、関連付けしない人は bat を作ればいい。

後は動的なスクリプト読み込みができるようにすれば理想的。
とはいえコレなら追記するのも簡単なのでそんな仕組みは不要かなとも思う。

ということで久々に書いた具体的アプリケーションコードにて本年を終わります。