最終更新日 2024-09-25

グリッドビューに顔画像を入れる。

~上級編~

ここは、前節「メモリエディタを作る」の続きとなります。

さて、前節では、.NET FrameWorkのデータグリッドビューコンポーネントを利用して、メモリエディタを作成しました。
ここでは、その続きとして、「データグリッドビューの中に、武将の顔グラを表示する」というのを行います。

8色の顔グラを表示する、というのも無理ではありませんが、ソース長くなっていくので、
ここでは、「フルカラーの顔グラフィックが、kao_24bitフォルダに存在する」というこを前提に組んでみましょう

DataGridViewImageColumnの利用

前節のMemoryEditorFormの中身の変更となります。

まずはメモリビューワーを実現してみましょう。

前節では、全て「DataGridViewTextBoxColumn」型を扱ってきました。
今節では、これに加えて「DataGridViewImageColumn」という画像が扱える「縦列」を扱って、顔グラフィックを取り扱います。

又、画像を縮小する際に、よく利用されるやり方も盛り込まれています。

using namespace System;
using namespace System::Windows::Forms;
using namespace System::Drawing;



ref class MemoryEditorForm : public Form {

private:
  DataGridView^ dgv;  // データグリッドビュー型。 エクセルのように格子状のデータを表示できるため、非常によく利用される。

public:
  MemoryEditorForm() {

    this->Text = "MemoryEditor";

    // データグリッド全体のインスタンス
    dgv = gcnew DataGridView();

    dgv->Height = 800;
    dgv->Width = 1000;
    dgv->RowTemplate->Height = 30; // 各々のセルの高さを30とする。
    dgv->AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode::AllCells; // 各カラムの横幅はコンテンツに応じて自動調整


    // .NETのString^型を要素とする、.NETの配列array^型。
    cli::array<String^>^ colTitle = {"indexID", "顔", "姓名", "政治", "戦闘", "智謀"};

    // -------------- ここからデータグリッドの「縦列に相当するカラムブジェクト」と、「各カラムのタイトル」の文字列をセッティングする。
    // 「index:0 顔グラ:1 姓名:2 政治:3 戦闘:4 智謀:5」 という順番となる。

    for (int i=0; i < colTitle->Length; i++) {
      if ( colTitle[i] != "顔" ) {
        // テキスト型の縦列のオブジェクトを作り
        DataGridViewTextBoxColumn^ dgvtbc = gcnew DataGridViewTextBoxColumn();
        // タイトル文字列を設定
        dgvtbc->HeaderText = colTitle[i];
        // グリッドビューに縦列として追加。
        dgv->Columns->Add(dgvtbc);
      } else {
        // イメージ型の縦列のオブジェクトを作り
        DataGridViewImageColumn^ dgvic = gcnew DataGridViewImageColumn();
        // タイトル文字列を設定
        dgvic->HeaderText = colTitle[i];
        // グリッドビューに縦列として追加。
        dgv->Columns->Add(dgvic);
      }
    }

    // 各カラムに天翔記のデータ(532人の武将の、姓名、政才、戦才、智才)を足してゆく
    DgvDataImport();

    // データグリッドのセルを編集した時のイベントハンドラを登録する。
    dgv->CellValueChanged += gcnew DataGridViewCellEventHandler(this, &MemoryEditorForm::dgv_CellValueChanged);

    // データグリッドビューをフォームに乗っける
    this->Controls->Add(dgv);
  }

private:
  // 武将番号【配列用】を引数として、顔番号を求め、フルカラーの顔画像があれば、
  // それを24*30ピクセルのジメージオブジェクトにして返す。
  Bitmap^ GetFaceBitmap(int iBushouID) {
    // 武将の顔番号を求める
    int iFaceID = p武将戸籍情報[iBushouID].顔番号;
    // 顔番号→4桁のファイル名に
    String^ strFaceFileName = String::Format("kao_24bit\\{0:0000}.bmp", iFaceID+1);

    Bitmap^ bm = gcnew Bitmap(24, 30);
    if (System::IO::File::Exists( strFaceFileName )) {
      // bm の中を描画用意。
      Graphics^ g = Graphics::FromImage(bm);

      // バイキュービックモードとする。(PhotoShopのリサイズモードとかと似た概念)
      g->InterpolationMode = System::Drawing::Drawing2D::InterpolationMode::HighQualityBicubic;
      g->DrawImage(gcnew Bitmap(strFaceFileName), 0, 0, bm->Width, bm->Height); // 内部描画
    }

    return bm;
  }

  void DgvDataImport() {

    // 横列単位で足してゆく、index:0, 姓:1, 名:2, 政治:3 戦闘:4 智謀:5 の順番通り
    for ( int i=0; i<最大数::武将情報::配列数; i++) {

      dgv->Rows->Add(
        i,
        GetFaceBitmap(i),
        gcnew String(Get_名字(i).c_str())+gcnew String(Get_名前(i).c_str()),
        p武将情報[i].最大政才,
        p武将情報[i].最大戦才,
        p武将情報[i].最大智才
        );
    }
  }

  void dgv_CellValueChanged(Object^ sender, DataGridViewCellEventArgs^ e)	{
    // イベントが発生したオブジェクト(=sender) はデータグリッド型なので、データグリッド型として受け取って…
    DataGridView^ grid = (DataGridView^)sender;

    // 一番左のIndexIDに入っている値が、武将番号【配列用】である。
    int iBushouID = Convert::ToInt32(grid[0, e->RowIndex]->Value->ToString()); // indexIDが一番左だからcolumnは0

    // 発生したイベントの列が3番目なら
    if (e->ColumnIndex == 3) {
      // 該当のグリッドの値をbyte型(256までの型)にして、p武将情報に代入する。
      p武将情報[iBushouID].最大政才 = Convert::ToByte(grid[e->ColumnIndex, e->RowIndex]->Value->ToString());
    }
    // 発生したイベントの列が4番目なら
    if (e->ColumnIndex == 4) {
      // 該当のグリッドの値をbyte型(256までの型)にして、p武将情報に代入する。
      p武将情報[iBushouID].最大戦才 = Convert::ToByte(grid[e->ColumnIndex, e->RowIndex]->Value->ToString());
    }
    // 発生したイベントの列が5番目なら
    if (e->ColumnIndex == 5) {
      // 該当のグリッドの値をbyte型(256までの型)にして、p武将情報に代入する。
      p武将情報[iBushouID].最大智才 = Convert::ToByte(grid[e->ColumnIndex, e->RowIndex]->Value->ToString());
    }
    デバッグ出力 << "budhou:" << iBushouID << "row:" << e->RowIndex << "column:" << e->ColumnIndex << endl;

  }
};