MonoMac/NSViewを継承したカスタムコントロールを作る

提供: MonoBook
< MonoMac
2015年4月17日 (金) 11:16時点における153.174.184.145 (トーク)による版 (→‎手順)
ナビゲーションに移動 検索に移動

手順

MonoMacXamarin.Macもほぼ同じ手順となっている。 Xamarin.iOSとはちょっと違うので注意。

  • NSViewを継承し、クラスにRegister属性で公開名を付ける。
  • NSCodeを引数とするコンストラクタを作り、 [Export("initWithCoder:")]属性をつける。
    Interface Builderで表示時に呼ばれるコンストラクタ
  • RectangleFを引数とするコンストラクタを作り、[Export("initWithFrame:")]属性をつける。
    実行時(インスタンス生成時)に呼ばれるコンストラクタ

あとは必要に応じてDrawRectメソッドなどをオーバーライドする。

完成したら以下の手順でInterface Builderに貼付ける。

例1:横線を引くだけのカスタムコントロール

    using System;
    using System.Drawing;
    using MonoMac.Foundation;
    using MonoMac.AppKit;
    using MonoMac.CoreGraphics;

    [Register("HorizontalLineView")]
    public class HorizontalLineView : NSView
    {
        /// <summary>
        /// 線の色
        /// </summary>
        /// <value>The default is `NSColor.GrayColor`.</value>
        public NSColor LineColor
        {
            get { return _lineColor; }
            set
            {
                _lineColor = value;
                this.NeedsDisplay = true;
            }
        }

        NSColor _lineColor;

        /// <summary>
        /// 線の太さ
        /// </summary>
        /// <value>The width of the line.</value>
        public float LineWidth
        {
            get { return _lineWidth; }
            set
            {
                _lineWidth = value;
                this.NeedsDisplay = true;
            }
        }

        float _lineWidth;

        /// <summary>
        /// Interface Builderで呼ばれるコンストラクタ。
        /// 直後にAwakeFromNibが呼ばれない。
        /// </summary>
        /// <param name="coder">Coder.</param>
        [Export("initWithCoder:")]
        public HorizontalLineView(NSCoder coder)
            :base(coder)
        {
            Initialize();
        }

        /// <summary>
        /// インスタンス生成時に呼ばれるコンストラクタ。
        /// 直後にAwakeFromNibが呼ばれる。
        /// </summary>
        /// <param name="frameRect">Frame rect.</param>
        [Export("initWithFrame:")]
        public HorizontalLineView(RectangleF frame)
            :base(frame)
        {
            Initialize();
        }
            
        void Initialize()
        {
            // レイヤーを有効にする。
            // これをせずにthis.Layerにアクセスするとクラッシュするよ。
            this.WantsLayer = true;

            // 背景を透明にする
            this.Layer.BackgroundColor = NSColor.Clear.CGColor;
            this.Layer.Opaque = false;

            // 各種プロパティの初期値
            this.LineColor = NSColor.Gray;
            this.LineWidth = 2.0f;
        }

        public override void DrawRect(RectangleF dirtyRect)
        {
            // NSGraphicsContext.CurrentContext.CGContextにアクセスすると落ちる。
            // NSGraphicsContext.CurrentContext.GraphicsPortを使おう。
            var cg = NSGraphicsContext.CurrentContext.GraphicsPort;

            cg.ClipToRect(dirtyRect);
            cg.SetLineWidth(this.LineWidth);

            float y = dirtyRect.Height / 2 - this.LineWidth / 2;

            cg.SetStrokeColor( this.LineColor.CGColor );
            cg.MoveTo(0.0f, y);
            cg.AddLineToPoint(dirtyRect.Width, y);
            cg.StrokePath();
        }
    }

関連項目

参考文献