中の技術日誌ブログ

C#とC++/CLIと
VBと.NETとWindowsで戯れる
 

目次

Blog 利用状況

ニュース

自己紹介

東京でソフトウェアエンジニアをやっています。
お仕事大募集中です。
記事執筆や、講師依頼とかでも何でもどうぞ(*^_^*)
似顔絵 MSMVPロゴ
MSMVP Visual C# Since 2004/04-2013/03

記事カテゴリ

書庫

日記カテゴリ

00-整理

01-MSMVP

Wankuma.WindowsForms.DataGridImageColumn Version2

その他の.Netライブラリ一覧へ戻る

http://blogs.users.gr.jp/naka/category/167.aspx

利用規約

http://blogs.users.gr.jp/naka/articles/2300.aspx

目的

DataGridで画像のカラムを表示したい。
スタートはそこからでした。

ただし大きい画像を表示させると重い、さらに毎回読んでいるととてもじゃないけど実用に耐えないということで、キャッシング機構をhidoriさんに提案していただいてそいつを組み込んであります。(DataGridImageColumn)

それだけでもそこそこの速度は出たのですが、大きい画像をつっこむとやっぱり遅いので、サムネイルを保持するようにしてあります。(DataGridThumbnailImageColumn)

本体

using System;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using hidori.Collections.Simple;
namespace Wankuma.WindowsForms
{
 /// 
 /// DataGridImageColumnはDataGridでImageをバインドするためのカラムスタイルです。
 /// データセットなどにはファイル名を指定してください。
 /// ファイル名がフルパスの場合にはそのまま。
 /// ファイル名だけが格納されている場合にはBaseDirectoryを設定することによってパス合成を行います。
 /// それ以上に複雑なパス決定ルーチンを組みたい場合にはこのクラスを継承し、GetFileNameをoverrideしてください。
 /// 
 public class DataGridImageColumn : DataGridColumnStyle
 {
  private string _BaseDirectory;
  private DisposableCacheBase _Cache;
  private Brush _BackColorBrush;

  /// 
  /// 画像ファイルの基準ディレクトリを示します。
  /// 
  public string BaseDirectory
  {
   set
   {
    this._BaseDirectory = value;
   }
  }
  /// 
  /// コンストラクタ
  /// 
  public DataGridImageColumn()
  {
   this._Cache = new DisposableCacheBase(50, true);
  }

  /// 
  /// デストラクタ 保険でDisposeを実行します。
  /// 
  ~DataGridImageColumn()
  {
   this.Dispose();
  }
 
  /// 
  /// 編集動作は対応しない。
  /// 
  /// 
  /// 
  /// 
  /// 
  /// 
  /// 
  protected override void Edit(CurrencyManager source, int rowNum, System.Drawing.Rectangle bounds, bool readOnly, string instantText, bool cellIsVisible)
  {
  }
  /// 
  /// 編集動作は対応しない。
  /// 
  /// 
  protected override void Abort(int rowNum)
  {
  }
  /// 
  /// 編集動作は対応しない。
  /// 
  /// 
  /// 
  /// 
  protected override bool Commit(CurrencyManager dataSource, int rowNum)
  {
   return true;
  }
  /// 
  /// 行の最小の高さを取得します。
  /// 
  /// 行の最小の高さ。
  protected override int GetMinimumHeight()
  {
   return 10;
  }
  /// 
  /// 列のサイズを自動的に変更するために使用する高さを取得します。
  /// 
  /// Graphics オブジェクト
  /// 画面の高さおよび幅を確認するオブジェクトの値。
  /// セルの自動的なサイズ変更に使用する高さ
  protected override int GetPreferredHeight(System.Drawing.Graphics g, object value)
  {
   return 100;
  }
  /// 
  /// 指定した値の幅および高さを取得します。この幅と高さは、ユーザーが DataGridColumnStyle を使用して DataGridTableStyle に移動するときに使用されます。
  /// 
  /// Graphics オブジェクト
  /// 画面の高さおよび幅を確認するオブジェクトの値。
  /// セルの大きさを格納する Size
  protected override System.Drawing.Size GetPreferredSize(System.Drawing.Graphics g, object value)
  {
   return new System.Drawing.Size(100, 100);
  }
  /// 
  /// 派生クラスでオーバーライドされると、指定した Graphics 、 Rectangle 、 CurrencyManager 、行番号、および配置を使用して DataGridColumnStyle を描画します
  /// 
  /// 描画が実行される Graphics オブジェクト
  /// 描画範囲の外接する Rectangle
  /// 列が属する System.Windows.Forms.DataGrid コントロールの CurrencyManager
  /// 参照先の、基になるデータにある行の番号
  /// 列の内容を右側に配置するかどうかを示す値。内容を右側に配置する必要がある場合は true 。それ以外の場合は false 
  protected override void Paint(System.Drawing.Graphics g, System.Drawing.Rectangle bounds, CurrencyManager source, int rowNum, bool alignToRight)
  {
   this.Paint(g, bounds, source, rowNum);
   
  }


  /// 
  /// 指定した Graphics 、 Rectangle 、 CurrencyManager 、および行番号を使用して DataGridColumnStyle を描画します
  /// 
  /// 描画が実行される Graphics オブジェクト
  /// 描画範囲の外接する Rectangle
  /// 列が属する System.Windows.Forms.DataGrid コントロールの CurrencyManager
  /// 参照先の、基になるデータにある行の番号
  protected override void Paint(System.Drawing.Graphics g, System.Drawing.Rectangle bounds, CurrencyManager source, int rowNum)
  {
   if ( this._BackColorBrush == null )
   {
    //ブラシを作っておく
    this._BackColorBrush = new SolidBrush(this.DataGridTableStyle.BackColor);
   }
   
   //背景をまず初期化する
   g.FillRectangle(this._BackColorBrush, bounds);
   string TargetFileName = this.GetFileName(source, rowNum);
   if ( TargetFileName == null )
   {
    return;
   }

   Image img = null;
   //キャッシュにあるか問い合わせる
   if ( this._Cache.Contains(TargetFileName) == true )
   {
    //ある場合
    img = (Image)this._Cache[TargetFileName];
   }
   else
   {
    img = this.GetImage(TargetFileName);
    this._Cache[TargetFileName] = img;
   }
   if ( img != null )
   {
    //縮尺を設定する
    float WidthPer = (float)bounds.Width / (float)img.Width;
    float HeightPer = (float)bounds.Height / (float)img.Height;
    float Percent = WidthPer > HeightPer ? HeightPer : WidthPer;
    //実際に描画する
    g.DrawImage( img, bounds.X, bounds.Y, img.Width * Percent, img.Height * Percent );
   }   
  }

  /// 
  /// このオブジェクトの破棄ロジックを提供します。
  /// 
  /// 
  protected override void Dispose(bool disposing)
  {
   //ブラシの開放
   if ( this._BackColorBrush != null )
   {
    this._BackColorBrush.Dispose();
   }
   //キャッシュの開放
   if ( this._Cache != null )
   {
    ((IDisposable)this._Cache).Dispose();
   }
   //ベースの開放
   base.Dispose (disposing);
  }
  /// 
  /// バインドされているデータを取得してファイル名を返してください。
  /// nullを返すことによって画像を表示しません。
  /// 
  /// 列が属する System.Windows.Forms.DataGrid コントロールの CurrencyManager
  /// 参照先の、基になるデータにある行の番号
  /// 表示するべきファイル名, nullであれば表示しない
  protected virtual string GetFileName( CurrencyManager source, int rowNum)
  {
   //ファイル名を取得する
   string FileName = GetColumnValueAtRow(source, rowNum).ToString();
   if ( FileName == null || FileName == "" )
   {
    return null;
   }
   else
   {
    if ( this._BaseDirectory == null )
    {
     return FileName;
    }
    else
    {
     return Path.Combine(this._BaseDirectory, FileName);
    }
   }
  } 
  /// 
  /// 示すファイル名でイメージを取得します。
  /// 
  /// 取得すべきファイル名
  /// 取得したイメージ
  protected virtual Image GetImage( string TargetFileName )
  {
   Image img;
   try
   {
    img = Wankuma.Drawing.Image.FromFile(TargetFileName);
   }
   catch( Exception )
   {
    //読み込みを行ったがエラーが発生した場合にはバッテン画像を作成する。
    img = new Bitmap(100, 100);
    using ( Graphics grph = Graphics.FromImage(img) )
    using ( Pen RedPen = new Pen(Color.Red, 3 ) )
    {
     grph.DrawLine(RedPen, new Point(20, 20), new Point( 80, 80 ) );
     grph.DrawLine(RedPen, new Point(20, 80), new Point( 80, 20 ) );
    }
   }
   return img;
  } 

 }
 /// 
 /// DataGridThumbnailImageColumnはDataGridでImageをバインドするためのカラムスタイルです。
 /// データセットなどにはファイル名を指定してください。
 /// ファイル名がフルパスの場合にはそのまま。
 /// ファイル名だけが格納されている場合にはBaseDirectoryを設定することによってパス合成を行います。
 /// それ以上に複雑なパス決定ルーチンを組みたい場合にはこのクラスを継承し、GetFileNameをoverrideしてください。
 /// 
 /// なにがDataGridImageColumnと違うかというと
 /// 
 public class DataGridThumbnailImageColumn : DataGridImageColumn
 {
  private int _ThumbnailImageWidth = 100;
  /// 
  /// サムネイル表示する画像の横幅を設定します。
  /// 大きくするとパフォーマンスによろしくありません。
  /// 
  public int ThumbnailImageWidth
  {
   set
   {
    if ( value > 0 )
    {
     this._ThumbnailImageWidth = value;
    }
    else
    {
     throw new ArgumentOutOfRangeException("ThumbnailImageWidth", value, "1以上の値を設定してください。");
    }
   }
  }
  /// 
  /// 示すファイル名でサムネイルイメージを取得します。
  /// 
  /// 取得すべきファイル名
  /// 取得したイメージ
  protected override Image GetImage(string TargetFileName)
  {
   Image img;
   try
   {
    img = Wankuma.Drawing.Image.FromFileThumbnailWidth(TargetFileName, this._ThumbnailImageWidth);
   }
   catch( Exception )
   {
    //読み込みを行ったがエラーが発生した場合にはバッテン画像を作成する。
    img = new Bitmap(100, 100);
    using ( Graphics grph = Graphics.FromImage(img) )
    using ( Pen RedPen = new Pen(Color.Red, 3 ) )
    {
     grph.DrawLine(RedPen, new Point(20, 20), new Point( 80, 80 ) );
     grph.DrawLine(RedPen, new Point(20, 80), new Point( 80, 20 ) );
    }
   }
   return img;
  }
 }
}

必要ライブラリ

ひどりさんのCacheBase0.2b5以上必須です。
動作保証は0.2b5のみになります。
http://blogs.users.gr.jp/hidori/articles/CacheBase.aspx

投稿日時 : 2004年4月30日 0:04

コメントを追加

No comments posted yet.
タイトル
名前
URL
コメント