GraphicsPath の代わりをPolygonでやってみたけど、思った以上に綺麗にならなかったのでやっぱ辞めた(´・ω・`)

今週も引き続いてCompact Framework周りの整理中でした。
今週の対応はUI周りということで、今まで作ってきたコントロール類の整理と標準化。


まあ、実用的に使うのはカスタムボタンとカスタムラベルだけだろうけど(´д`;)
カスタムボタンについては、今までの要件の最小公倍数を取ってこんなバカな設計にしていたりしてヽ(゚∀゚)ノ

まあ、カラーボタンとイメージボタンにはわけても良かったんですが(・ω・)


その他のものとしては、SIPコントロールも使うかな(・∀・)?
一応デザイナ対応で、ボタンの背景にはイメージも使えたりするので、ちょっとしたカスタム入力画面を作る用途にはこれで十分かと。


後は、タスクマネージャみたいなのとか、シンプルなゲージなんかは、デバッグ画面とかでしか使わないですが(´ω`)
CpuUsage、DriveInfo、MemoryManager、PowerManager、NetworkInfomationみたいなクラスも作ってあるので、それらと組み合わせればお手軽なシステムモニタが即完成なカンジ。
っというか、定期的な状態の取得と通知、通知を受けてのビヘイビア(PictureBox.Imageを変えるだとか、Control.Textを更新するだとか)みたいな機構も作ってあるので、ヘッダ領域にバッテリ残量や無線LAN状態を表示するみたいな処理は1行で書けるようにしてあるだわさ(・∀・)


ちなみに、UI画面左下の領域はなにをやっているかわかりにくいけど、カスタムボーダーを描画する仕掛け。
元ネタはMSDNにあったものだけど、ソースはこんなカンジ。

    public abstract class BorderEffect
    {
        private Control target;

        public Control Target
        {
            get { return this.target; }
        }

        protected BorderEffect()
        {
        }

        protected BorderEffect(Control target)
        {
            Attach( target );
        }

        public void Attach(Control target)
        {
            this.target = target;
            if( target.Parent != null )
            {
                target.Parent.Paint += ParentPaint;
            }
        }

        private void ParentPaint(object sender, PaintEventArgs e)
        {
            OnParentPaint( sender, e );
        }

        protected abstract void OnParentPaint(object sender, PaintEventArgs e);
    }
    public class ShadowEffect : BorderEffect
    {
        private int borderWidth = 1;
        private Color borderColor = Color.Gray;

        public int BorderWidth
        {
            get { return this.borderWidth; }
            set
            {
                this.borderWidth = value;
                Invalidate();
            }
        }

        public Color BorderColor
        {
            get { return this.borderColor; }
            set
            {
                this.borderColor = value;
                Invalidate();
            }
        }

        public ShadowEffect()
        {
        }

        public ShadowEffect(Control target) : base( target )
        {
        }

        private void Invalidate()
        {
            if( Target.Parent == null )
            {
                return;
            }

            Rectangle rect = new Rectangle( Target.Left, Target.Top, Target.Width + this.borderWidth, Target.Height + this.borderWidth );

            Target.Parent.Invalidate( rect );
        }

        protected override void OnParentPaint(object sender, PaintEventArgs e)
        {
            Rectangle rect = new Rectangle( Target.Left, Target.Top, Target.Width + this.borderWidth, Target.Height + this.borderWidth );

            if( e.ClipRectangle.IntersectsWith( rect ) )
            {
                using( Brush brush = new SolidBrush( this.borderColor ) )
                {
                    e.Graphics.FillRectangle( brush, Target.Left + this.borderWidth, Target.Top + this.borderWidth, Target.Width, Target.Height );
                }
            }
        }
    }
    public class Border3DEffect : BorderEffect
    {
        private int borderWidth = 1;
        private bool bump = true;

        public int BorderWidth
        {
            get { return this.borderWidth; }
            set
            {
                if( ( value != 1 ) && ( value != 2 ) )
                {
                    throw new ArgumentException( "value" );
                }
                this.borderWidth = value;
                Invalidate();
            }
        }

        public bool Bump
        {
            get { return this.bump; }
            set
            {
                this.bump = value;
                Invalidate();
            }
        }

        public Border3DEffect()
        {
        }

        public Border3DEffect(Control target) : base( target )
        {
        }

        private void Invalidate()
        {
            if( Target.Parent == null )
            {
                return;
            }

            Rectangle rect = new Rectangle( Target.Left - this.borderWidth, Target.Top - this.borderWidth, Target.Width + this.borderWidth * 2, Target.Height + this.borderWidth * 2 );

            Target.Parent.Invalidate( rect );
        }

        protected override void OnParentPaint(object sender, PaintEventArgs e)
        {
            if( this.bump == true )
            {
                if( this.borderWidth == 1 )
                {
                    e.Graphics.Draw3DRect( Target.Left - 1, Target.Top - 1, Target.Width + 2, Target.Height + 2, SystemColors.ControlLight, SystemColors.ControlDark );
                }
                else if( this.borderWidth == 2 )
                {
                    e.Graphics.Draw3DRect( Target.Left - 1, Target.Top - 1, Target.Width + 2, Target.Height + 2, SystemColors.Control, Color.Black );
                    e.Graphics.Draw3DRect( Target.Left - 2, Target.Top - 2, Target.Width + 4, Target.Height + 4, SystemColors.ControlLight, SystemColors.ControlDarkDark );
                }
            }
            else
            {
                if( this.borderWidth == 1 )
                {
                    e.Graphics.Draw3DRect( Target.Left - 1, Target.Top - 1, Target.Width + 2, Target.Height + 2, SystemColors.ControlDark, SystemColors.ControlLight );
                }
                else if( this.borderWidth == 2 )
                {
                    e.Graphics.Draw3DRect( Target.Left - 1, Target.Top - 1, Target.Width + 2, Target.Height + 2, Color.Black, SystemColors.Control );
                    e.Graphics.Draw3DRect( Target.Left - 2, Target.Top - 2, Target.Width + 4, Target.Height + 4, SystemColors.ControlDarkDark, SystemColors.ControlLight );
                }
            }
        }
    }
    public static class GraphicsExtension
    {
        public static void Draw3DRect(this Graphics g, int x, int y, int width, int height, Color colorTopLeft, Color colorBottomRight)
        {
            using( Brush brushTopLeft = new SolidBrush( colorTopLeft ) )
            using( Brush brushBottomRight = new SolidBrush( colorBottomRight ) )
            {
                g.FillRectangle( brushTopLeft, x, y, width - 1, 1 );
                g.FillRectangle( brushTopLeft, x, y, 1, height - 1 );
                g.FillRectangle( brushBottomRight, x + width - 1, y, 1, height );
                g.FillRectangle( brushBottomRight, x, y + height - 1, width, 1 );
            }
        }
    }

親のPaintにアタッチして、対象コントロールの周りに影を描画するわけですね(・∀・)
こういうちょっとしたUIの装飾もよくやるのでライブラリ化。


っで、Compact Framework周りの整理で残作業として残っているのは以下の項目。

  • ListView拡張

Message Hookして、色だとか、ヘッダでソートだとかの処理を行うListView拡張の標準化。

  • 固定長ファイル

C++版からの再移植。Byte配列マーシャラができたので、今あるC#版は捨て。
固定長ファイルへのバイナリサーチ、簡易DB化などを行うモノ。

  • 通信ライブラリ

RAS制御、FTP、メール送信、Ping、カスタムプロトコル通信。
いずれもC++版、C#版のソース断片があるものからの再構築。

  • ネットワーク情報強化

iphelpとかDeviceIoControlな世界をもう少し。

  • データアクセス

Executor、MapperのPC版からの移植。

  • UIFramework私家版

UIElementな何か。

  • ビットマップ、リージョン周り

描画が貧弱な分、やはりリージョンに頼らざるを得ないケースも。


っで、日記のタイトルについては前に作った円形ゲージのCE版を作ってみようと思い、ゾーンの描画の所でGraphicsPathの代わりにPloygonを計算して描画してみたんだけど、目盛りの描画と綺麗に重ならないケースがあったりして、ライブラリへの正式採用は辞めたという事でした。
まあ、CEではビットマップの背景を使う方向で(´д`;)