Adsense_top

2009年6月24日水曜日

アフィリエイトをはじめました

アフィリエイトをはじめました。右下にあるバーナーです。
これってどれぐらい儲かるのかな。まだ始めて数日ですが、全く報酬は発生していません。
ページの人気に比例するだろうことは容易に想像がつきますので、マメに記事を書くことが効果的なのかななど考えます。ただ、見てくれている人もいるので、適当なソースコードを載せることも出来ない(と言いつつミスったコード載せて修正をしていますが(^-^;) )し。
Visual Studio 2010が出る頃までに購入(個人の分)の足しになる程度の報酬は稼げないものでしょうか。


2009年6月21日日曜日

DataGridView セルの結合 2-5 コードまとめ

DataGridView セルの結合のここまでのソースコードを一旦まとめました。
問題点が多々あります。問題点を検討して書こうかと思いましたが、コードが長くなりましたので、今日はここまでのコードだけ載せておきます。
public class DgvMergebleTextBoxColumn {
  // 結合行数
  private int mergeRows = 1;
  // コンストラクタ
  public DgvMergebleTextBoxColumn() {
    this.CellTemplate = new DgvMergebleTextBoxCell();
  }
  // 結合行数を設定または取得します。
  public int MergeRows {
    get {
      return
      ((DgvMergebleTextBoxCell)this.CellTemplate).MergeRows;
    }
    set {
      if(this.mergeRows == value)
        return;
      //セルテンプレートの値を変更する
      ((DgvMergebleTextBoxCell)this.CellTemplate).MergeRows
      = value;
      //DataGridViewにすでに追加されているセルの値を変更する
      if(this.DataGridView == null)
        return;
      int rowCount = this.DataGridView.RowCount;
      for(int i = 0; i < rowCount; i++) {
        DataGridViewRow r = this.DataGridView.Rows.SharedRow(i);
        ((DgvMergebleTextBoxCell)r.Cells[this.Index]).MergeRows
        = value;
      }
    }
  }
  // MergeRowsプロパティを追加しているので、
  // Clone()をオーバーライドします。
  public override object Clone() {
    DgvMergebleTextBoxColumn col =
    (DgvMergebleTextBoxColumn)base.Clone();
    col.MergeRows = this.MergeRows;
    return col;
  }
}

public class DgvMergebleTextBoxCell : DataGridViewTextBoxCell {
  // 結合行数
  private int mergeRows = 1;
  public override object Clone() {
    DgvMergebleTextBoxCell cel =
    (DgvMergebleTextBoxCell)base.Clone();
    cel.MergeRows = this.MergeRows;
    return cel;
  }
  ///
  /// DataGridView 内でセルがいくつの行にまたがって表示されるかを
  /// 示す値を取得または設定します。
  ///
  public int MergeRows {
    get { return mergeRows; }
    set { mergeRows = value; }
  }
  // ホストされる編集コントロールの位置とサイズを設定します。
  public override void PositionEditingControl(
  bool setLocation, bool setSize,
  Rectangle cellBounds,
  Rectangle cellClip,
  DataGridViewCellStyle cellStyle,
  bool singleVerticalBorderAdded,
  bool singleHorizontalBorderAdded,
  bool isFirstDisplayedColumn,
  bool isFirstDisplayedRow) {
    // 結合するセルの高さに合わせるために、結合するセルの高さを足す
    Rectangle mergeCellBounds = cellBounds;
    for(int i = 1; i < mergeRows; i++) {
      if(RowIndex + i < this.DataGridView.Rows.Count) {
        mergeCellBounds.Height +=
        DataGridView.Rows.SharedRow(RowIndex + i).Height;
      }
    }
    if(RowIndex % mergeRows == 0) {
      base.PositionEditingControl(setLocation, setSize,
      mergeCellBounds,
      mergeCellBounds, cellStyle,
      singleVerticalBorderAdded,
      singleHorizontalBorderAdded,
      isFirstDisplayedColumn,
      isFirstDisplayedRow);
    } else {
      int row = (RowIndex / mergeRows) * mergeRows;
      for(int k = row; k < RowIndex; k++) {
        mergeCellBounds.Y -=
        DataGridView.Rows.SharedRow(k).Height;
      }
      base.PositionEditingControl(setLocation, setSize,
      mergeCellBounds,
      mergeCellBounds, cellStyle,
      singleVerticalBorderAdded,
      singleHorizontalBorderAdded,
      isFirstDisplayedColumn,
      isFirstDisplayedRow);
    }
  }
  public override void InitializeEditingControl(
  int rowIndex,
  object initialFormattedValue,
  DataGridViewCellStyle dataGridViewCellStyle) {
    base.InitializeEditingControl(rowIndex,
    initialFormattedValue,
    dataGridViewCellStyle);
    DataGridViewTextBoxEditingControl ctl =
    this.DataGridView.EditingControl
    as DataGridViewTextBoxEditingControl;
    // 結合された列の上端の行インデックスを算出しセルを取得
    int row = (rowIndex / mergeRows) * mergeRows;
    DataGridViewCell cell =
    this.DataGridView[ColumnIndex, row];
    // 初期化した編集コントロールに、
    // 結合された列の上端セルの値を代入
    ctl.Text = Convert.ToString(cell.Value);
  }
  protected override object GetValue(int rowIndex) {
    if(rowIndex % mergeRows == 0) {
      // 結合された列の上端行のセルの場合のみ値を返す
      return base.GetValue(rowIndex);
    } else {
      // 結合された列の上端行のセル以外の場合は、null値を返す
      return null;
    }
  }
  protected override bool SetValue(int rowIndex, object value) {
    if(this.DataGridView == null || rowIndex % mergeRows == 0) {
      // DataGridViewにまだ追加されていないセルの場合と
      // 結合された列の上端行セルの場合は通常通り値を設定します。
      return base.SetValue(rowIndex, value);
    } else {
      try {
        // 結合された列の上端行のインデックスを計算
        int topRowIndex = (rowIndex / mergeRows) * mergeRows;
        // DataGridViewにすでに追加されていて、結合された列の
        // 上端行以外のセルの場合、結合された列の上端行のセルに
        // 値を設定します。
        this.DataGridView[this.ColumnIndex,
        TopRowIndex(rowIndex)].Value = value;
        return true;
      } catch(Exception ex) {
        // 何らかのエラーが発生した場合は、falseを返します。
        return false;
      }
    }
  }
  protected override void Paint(Graphics graphics,
  Rectangle clipBounds,
  Rectangle cellBounds,
  int rowIndex,
  DataGridViewElementStates cellState,
  object value, object formattedValue,
  string errorText,
  DataGridViewCellStyle cellStyle,
  DataGridViewAdvancedBorderStyle advancedBorderStyle,
  DataGridViewPaintParts paintParts) {
    Rectangle rect = cellBounds;
    int topRowIndex = TopRowIndex(rowIndex);
    bool isPrint = true;
    object topFormattedValue = null;
    object topValue = null;
    bool cellSelected = false;
    for(int i = 0; i < mergeRows; i++) {
      // 端数行がある場合、マージ行数より少ない行でも表示を
      // 行うために結合行数以下で切り上げる
      if(topRowIndex + i >= this.DataGridView.Rows.Count) {
        break;
      }
      DataGridViewCell cell =
      this.DataGridView[ColumnIndex, topRowIndex + i];
      if(i == 0) {
        // 結合行の最上端セルの値を取得
        topFormattedValue = cell.FormattedValue;
        topValue = cell.Value;
      }
      if(!cell.Equals(this) && !cell.OwningRow.IsNewRow) {
        rect.Height += cell.OwningRow.Height;
      }
      // 描画矩形のY座標を、結合行の最上端セルの座標にあわせる
      if(i < (rowIndex % mergeRows))
        rect.Y -= cell.OwningRow.Height;
      // 結合されたセルのグループ内に選択されたセルがあるか確認
      if((cell.State & DataGridViewElementStates.Selected) != 0)
        cellSelected = true;
    }
    // グループ内に選択されたセルがあった場合は、
    // UIの状態を選択状態にする。
    if(cellSelected)
      cellState |= DataGridViewElementStates.Selected;
    // マージしていることになっている他のセルも
    // 書き直す必要があるためDataGridViewのGraphicsを取得
    Graphics g = this.DataGridView.CreateGraphics();
    // Graphics オブジェクト、描画矩形を設定して描画する。
    base.Paint(g, rect, rect, rowIndex, cellState, topValue,
    topFormattedValue, errorText, cellStyle,
    advancedBorderStyle, paintParts);
  }
  protected override void OnKeyDown(KeyEventArgs e, int rowIndex) {
    // カレントセルにする行Index
    int curIndex = -1;
    // 列ヘッダの場合は、基底クラスに任す
    if(rowIndex >= 0) {
      // ↑キー
      if(e.KeyCode == Keys.Up) {
        if(e.Control) {
          // Ctrlキーが押下されていた場合は
          // 最初の行をカレントセルに設定
          curIndex = 0;
        } else {
          if(TopRowIndex(rowIndex) > 0) {
            // 一つ上の結合セルのグループの上端の行を
            // カレントセルのIndexに設定
            curIndex =
            TopRowIndex(TopRowIndex(rowIndex) - mergeRows);
          } else {
            // 自身が一番上の結合グループのセルの場合は、
            // 自身の結合グループの上端の行(Index=0)を
            // カレントセルのIndexに設定
            curIndex = 0;
          }
        }
        // カレントセルを設定
        this.DataGridView.CurrentCell =
        this.DataGridView[ColumnIndex, curIndex];
        e.SuppressKeyPress = true;
      }
        // ↓キー
      else if(e.KeyCode == Keys.Down) {
        if(e.Control) {
          // Ctrlキーが押下されていた場合は最後の行を
          // カレントセルのIndexに設定
          curIndex =
          TopRowIndex(this.DataGridView.RowCount - 1);
        } else {
          if(TopRowIndex(rowIndex) + mergeRows
          <= this.DataGridView.RowCount) {
            // 自身のセルの属する結合グループより下に、
            // 行が存在する場合、自身のグループの下端の
            // 次の行をカレントセルのIndexに設定
            curIndex =
            TopRowIndex(TopRowIndex(rowIndex) + mergeRows);
          } else {
            // 自身のセルの属する結合グループより下に、
            // 行がない場合は、自身のグループの中の下端の行を
            // カレントセルのIndexに設定。
            // MergeRow分の行がない可能性もあるので、
            // DataGridViewの下端のIndexを設定している。
            curIndex =
            TopRowIndex(this.DataGridView.RowCount - 1);
          }
        }
        // カレントセルを設定
        this.DataGridView.CurrentCell
        = this.DataGridView[ColumnIndex, curIndex];
        e.SuppressKeyPress = true;
      }
    } else {
      // ↑↓キー以外は通常の処理へ
      base.OnKeyDown(e, rowIndex);
    }
  }
  // 現在のセルが所属する結合セルのグループの
  // 上端のセルのインデックスを返します。
  private int TopRowIndex(int rowIndex) {
    return (rowIndex / mergeRows) * mergeRows;
  }
}

次回は、スクロール時の描画の問題点をはじめ多々ある問題点の洗い出しなどをしたいと思っています。

2009年6月16日火曜日

「ジェネリック・クラスってすごい」のソース変でした

昨日のエントリー「ジェネリック・クラスってすごい」に書いたコードがおかしくなっていました。
<>の処理をせずに<PRE>タグで囲んでいたため<>の中身がごっそり抜けていました。
正しくは下記のとおりです。

Dictionary<string, Dictionary<string, string>> dicLanguage =
new Dictionary<string, Dictionary<string, string>>();
Dictionary<string, string> dicJapanese =
new Dictionary<string, string>();
Dictionary<string, string> dicEnglish =
new Dictionary<string, string>();
Dictionary<string, string> dicGerman =
new Dictionary<string, string>();

dicJapanese.Add("朝", "おはよう");
dicJapanese.Add("昼", "こんにちは");
dicJapanese.Add("夜", "こんばんは");
dicEnglish.Add("朝", "Good morning");
dicEnglish.Add("昼", "Hello");
dicEnglish.Add("夜", "Good evening");
dicGerman.Add("朝", "Guter Morgen");
dicGerman.Add("昼", "Guten Tag");
dicGerman.Add("夜", "Guter Abend");
dicLanguage.Add("日本語", dicJapanese);
dicLanguage.Add("英語", dicEnglish);
dicLanguage.Add("ドイツ語", dicGerman);
foreach (string key in dicLanguage.Keys)
{
foreach (string key2 in dicLanguage[key].Keys)
{
Console.WriteLine("{0} : {1} : {2}",
key, key2, dicLanguage[key][key2]);
}
}

失礼いたしました。


2009年6月15日月曜日

ジェネリック・クラスってすごい

当エントリーは、ソースコードのコピーの際、ミスをしているため書かれているソースコードは正しくありません。
正しくは
明日のエントリーに書き直しています。


今日、Dictionary<TKey, TValue> クラス を使っていて、こんなことが出来る事に気がつきました。 Dictionaryの値にDictionaryを入れることが出来てしまうのです。

ソース

Dictionary dicLanguage =
    new Dictionary();
Dictionary dicJapanese = new Dictionary();
Dictionary dicEnglish = new Dictionary();
Dictionary dicGerman = new Dictionary();

dicJapanese.Add("朝", "おはよう");
dicJapanese.Add("昼", "こんにちは");
dicJapanese.Add("夜", "こんばんは");
dicEnglish.Add("朝", "Good morning");
dicEnglish.Add("昼", "Hello");
dicEnglish.Add("夜", "Good evening");
dicGerman.Add("朝", "Guter Morgen");
dicGerman.Add("昼", "Guten Tag");
dicGerman.Add("夜", "Guter Abend");
dicLanguage.Add("日本語", dicJapanese);
dicLanguage.Add("英語", dicEnglish);
dicLanguage.Add("ドイツ語", dicGerman);
foreach (string key in dicLanguage.Keys)
{
foreach (string key2 in dicLanguage[key].Keys)
{
Console.WriteLine("{0} : {1} : {2}",
key, key2, dicLanguage[key][key2]);
}
}

出力結果
日本語 : 朝 : おはよう
日本語 : 昼 : こんにちは
日本語 : 夜 : こんばんは
英語 : 朝 : Good morning
英語 : 昼 : Hello
英語 : 夜 : Good evening
ドイツ語 : 朝 : Guter Morgen
ドイツ語 : 昼 : Guten Tag
ドイツ語 : 夜 : Guter Abend

僕だけが知らなかったのかもしれませんが、ちょっと感激しました。
List<T> クラスでもList<List<string>> みたいなことも出来ました。
何に使えるかは直ぐには思いつきませんが、取りあえず覚えていて損はないかと...。


 


2009年6月14日日曜日

C# DataGridView セルの結合 その5

今回はキーボードでのセル移動の部分を考えました。
protected override void OnKeyDown(KeyEventArgs e, int rowIndex) {
  // カレントセルにする行Index
  int curIndex = -1;
  // 列ヘッダの場合は、基底クラスに任す
  if(rowIndex >= 0) {
    // ↑キー
    if(e.KeyCode == Keys.Up) {
      if(e.Control) {
        // Ctrlキーが押下されていた場合は
        // 最初の行をカレントセルに設定
        curIndex = 0;
      } else {
        if(TopRowIndex(rowIndex) > 0) {
          // 一つ上の結合セルのグループの上端の行を
          // カレントセルのIndexに設定
          curIndex =
          TopRowIndex(TopRowIndex(rowIndex) - mergeRows);
        } else {
          // 自身が一番上の結合グループのセルの場合は、
          // 自身の結合グループの上端の行(Index=0)を
          // カレントセルのIndexに設定
          curIndex = 0;
        }
      }
      // カレントセルを設定
      this.DataGridView.CurrentCell =
      this.DataGridView[ColumnIndex, curIndex];
      e.SuppressKeyPress = true;
    }
      // ↓キー
    else if(e.KeyCode == Keys.Down) {
      if(e.Control) {
        // Ctrlキーが押下されていた場合は最後の行を
        // カレントセルのIndexに設定
        curIndex =
        TopRowIndex(this.DataGridView.RowCount - 1);
      } else {
        if(TopRowIndex(rowIndex) + mergeRows
        <= this.DataGridView.RowCount) {
          // 自身のセルの属する結合グループより下に、
          // 行が存在する場合、自身のグループの下端の
          // 次の行をカレントセルのIndexに設定
          curIndex =
          TopRowIndex(TopRowIndex(rowIndex) + mergeRows);
        } else {
          // 自身のセルの属する結合グループより下に、
          // 行がない場合は、自身のグループの中の下端の行を
          // カレントセルのIndexに設定。
          // MergeRow分の行がない可能性もあるので、
          // DataGridViewの下端のIndexを設定している。
          curIndex =
          TopRowIndex(this.DataGridView.RowCount - 1);
        }
      }
      // カレントセルを設定
      this.DataGridView.CurrentCell
      = this.DataGridView[ColumnIndex, curIndex];
      e.SuppressKeyPress = true;
    }
  } else {
    // ↑↓キー以外は通常の処理へ
    base.OnKeyDown(e, rowIndex);
  }
}

コードをみて、アレッ?て感じた方が多いのではないでしょうか。Shiftキーを処理していません。
MultiSelectを無視しちゃっています。
ここで、中途半端に処理しちゃうととんでもない方向に向いて行ってしまいそうなので、敢えて無視しました。取りあえず、限定した使用方法では使えるかなぁって感じにだけ収めました。
次回にでも、ここまでを纏めて、問題点などを改めて考えてみたいと思っています。

2009年6月8日月曜日

C# DataGridView セルの結合 その4、コード変更

その4」の描画部分のコードに問題がありました。
結合セル内で、キーボードで「UP」キーを押下すると、結合セルからフォーカスが抜けていない時でも、表示が選択状態でなくなってしまいます。
上記操作をした場合新しい選択セルの描画->元のセルの描画の順にイベントが起こるためこのような感じになります。
結合セルのうグループ内で選択されたセルがある場合、選択状態(規定では青色)描画するようにしました。
protected override void Paint(Graphics graphics,
  Rectangle clipBounds,
  Rectangle cellBounds,
  int rowIndex,
  DataGridViewElementStates cellState,
  object value, object formattedValue,
  string errorText,
  DataGridViewCellStyle cellStyle,
  DataGridViewAdvancedBorderStyle advancedBorderStyle,
  DataGridViewPaintParts paintParts) {
  Rectangle rect = cellBounds;
  int topRowIndex = TopRowIndex(rowIndex);
  bool isPrint = true;
  object topFormattedValue = null;
  object topValue = null;
  bool cellSelected = false;  // <---- ★追加
  for(int i = 0; i < mergeRows; i++) {
    // 端数行がある場合、マージ行数より少ない行でも表示を
    // 行うために結合行数以下で切り上げる
    if(topRowIndex + i >= this.DataGridView.Rows.Count) {
      break;
    }
    DataGridViewCell cell =
    this.DataGridView[ColumnIndex, topRowIndex + i];
    if(i == 0) {
      // 結合行の最上端セルの値を取得
      topFormattedValue = cell.FormattedValue;
      topValue = cell.Value;
    }
    if(!cell.Equals(this) && !cell.OwningRow.IsNewRow) {
      rect.Height += cell.OwningRow.Height;
    }
    // 描画矩形のY座標を、結合行の最上端セルの座標にあわせる
    if(i < (rowIndex % mergeRows))
      rect.Y -= cell.OwningRow.Height;
    // ★以下2行追加
    // 結合されたセルのグループ内に選択されたセルがあるか確認
    if((cell.State & DataGridViewElementStates.Selected) != 0)
      cellSelected = true;
  }
  // ★以下2行追加
  // グループ内に選択されたセルがあった場合は、
  // UIの状態を選択状態にする。
  if(cellSelected)
    cellState |= DataGridViewElementStates.Selected;

  // マージしていることになっている他のセルも
  // 書き直す必要があるためDataGridViewのGraphicsを取得
  Graphics g = this.DataGridView.CreateGraphics();
  // Graphics オブジェクト、描画矩形を設定して描画する。
  base.Paint(g, rect, rect, rowIndex, cellState, topValue,
  topFormattedValue, errorText, cellStyle,
  advancedBorderStyle, paintParts);
}

次は、キーボード操作でのセル移動を考えるつもりです。その過程で、上記描画部のコードを更に変更する可能性もありますが、とりあえずここまでのコードで、辻褄が合うようにしました。

2009年6月5日金曜日

C# DataGridView セルの結合 その4

前回の続きです。「ここ」に「C# DataGridView セルの結合 その3」で書き忘れていたコードがありましたので追加しています。
今回は、描画の部分を考えました。」
「DgvMergebleTextBoxCell」クラスでPaintメソッドをオーバーライドしています。
結合されたどのセルを選択されても、結合セルのグループの上端セルの値を取ってきて表示するようにしています。
protected override void Paint(Graphics graphics,
  Rectangle clipBounds,
  Rectangle cellBounds,
  int rowIndex,
  DataGridViewElementStates cellState,
  object value, object formattedValue,
  string errorText,
  DataGridViewCellStyle cellStyle,
  DataGridViewAdvancedBorderStyle advancedBorderStyle,
  DataGridViewPaintParts paintParts) {

  Rectangle rect = cellBounds;
  int topRowIndex = TopRowIndex(rowIndex);
  bool isPrint = true;
  object topFormattedValue = null;
  object topValue = null;
  for(int i = 0; i < mergeRows; i++) {
    // 端数行がある場合、マージ行数より少ない行でも表示を
    // 行うために結合行数以下で切り上げる
    if(topRowIndex + i >= this.DataGridView.Rows.Count) {
      break;
    }
    DataGridViewCell cell =
    this.DataGridView[ColumnIndex, topRowIndex + i];
    if(i == 0) {
      // 結合行の最上端セルの値を取得
      topFormattedValue = cell.FormattedValue;
      topValue = cell.Value;
    }
    if(!cell.Equals(this) && !cell.OwningRow.IsNewRow) {
      rect.Height += cell.OwningRow.Height;
    }
    // 描画矩形のY座標を、結合行の最上端セルの座標にあわせる
    if(i < (rowIndex % mergeRows))
      rect.Y -= cell.OwningRow.Height;
  }
  // マージしていることになっている他のセルも
  // 書き直す必要があるためDataGridViewのGraphicsを取得
  Graphics g = this.DataGridView.CreateGraphics();
  // Graphics オブジェクト、描画矩形を設定して描画する。
  base.Paint(g, rect, rect, rowIndex, cellState, topValue,
  topFormattedValue, errorText, cellStyle,
  advancedBorderStyle, paintParts);
}

こんな感じになります。





それっぽくなりましたが、幾つか問題があります。実際に動かしてテストしてみれば、すぐに見つけることが出来ます。徐々に修正していきたいと思います。
ここまでは、大雑把感じで書けてきましたが、ここから結構細かいところに気をつけていかなければならないような気がします。とりあえず行ける所まで行きたいと思います。

2009年6月4日木曜日

C# DataGridView セルの結合 その3の追加

05/30のエントリー「DataGridView セルの結合 その3」見ていたら、ソースに書き忘れを見つけました。
SetValueをオーバーライドしているところで、「TopRowIndex」メソッドが使われていますが、これは別途定義したものです。
結合したセルの上端のインデックスを計算しているメソッドです。以下のコードです。
// 現在のセルが所属する結合セルのグループの
// 上端のセルのインデックスを返します。
private int TopRowIndex(int rowIndex) {
  return (rowIndex / mergeRows) * mergeRows;
}