MonoMacおよびXamarin.MacでAppKitのNSApplicationのサブクラスを利用したい場面もあることだろう。多くの場合はNSApplicationDelegateで事足りるだろうが、稀にすべてのイベントをトラップしたい場面などではNSApplicationのサブクラスを作る必要がある。
目次
実装1
NSApplicationのサブクラスを作る
Register属性で指定した名前は後ほどInfo.plistで利用される。凄く重要。クラス名と同じにしておくと紛らわしくないと思われる。
NSApplicationがデフォルトコンストラクタを持たない関係でサブクラスにもコンストラクタがないとコンパイルが通らないが、デバッガで追ってみた限りでは呼ばれている気配はない。そのためAwakeFromNibメソッドをオーバーライドして初期化している。これでいいのかは知らん。
using System;
using Foundation;
using AppKit;
[Register("App")]
public class App : NSApplication
{
public App(IntPtr handle) : base(handle) {}
public App(NSCoder coder) : base(coder) {}
/// <summary>
/// 初期化はAwakeFromNibのタイミングでいいのか?
/// 調査中
/// </summary>
public override void AwakeFromNib()
{
base.AwakeFromNib();
this.Delegate = new AppDelegate();
}
/// <summary>
/// こいつをオーバーライドすればほぼ全てのイベントが取れる
/// </summary>
/// <param name="theEvent">The event.</param>
public override void SendEvent(NSEvent theEvent)
{
base.SendEvent(theEvent);
}
}
Info.plistに「Principal class」を設定する
Info.plistを開き、Xamarin Studio下部の「ソース」タブを選択する。Info.plistがない場合はファイルを追加する(新規追加ダイアログでは「Application Manifest」という名称になっているはず)。
プロパティの一覧が列挙されるので、プロパティ「Principal class」に「String」型で前述のRegister属性で付けた名前を入力する(この例であれば「App」)。プロパティ「Principal class」がない場合はリスト下部の「Add new entry」を選べば新しい行が追加される。
エントリポイントを書き換える
Xamarin Studioで「空のプロジェクト」を作ると初期値でこんな感じになっている。
static class MainClass
{
static void Main(string[] args)
{
NSApplication.Init();
var application = NSApplication.SharedApplication;
application.Delegate = new AppDelegate();
application.Run();
}
}
これを以下のように書き換える。なお「空のプロジェクト」ではなく「Cocoa」を選ぶと最初からこうなっている。
using System;
using AppKit;
static class MainClass
{
static void Main(string[] args)
{
NSApplication.Init();
NSApplication.Main(args);
}
}