« C4D ユーザスクリプトでモーダルダイアログの学習-03 | トップページ | 最近、「C4D 水 表現」で検索してこのブログへ… »

C4D ユーザスクリプトでモーダルダイアログの学習-04

ユーザスクリプトでのダイアログの学習をしていますが…
なんとなく、組み立て方、構造が分かってきたような気がします。
その気になる事が大切で…

今回は、ダイアログで何かをした時に呼ばれる、Command()を学習します。

では、今回のベースになるスクリプトです。

/*
GeDialogクラスのCommand()の学習
2009.8.3
*/



//test_dialogクラス =======================================
class test_dialog:GeModalDialog
{
  public:
    var ch1 , ch2;//チェックボックス用
    var tx1 , tx2;//エディットテキスト用
    var bt1 , bt2;//ボタン用

    test_dialog();
    CreateLayout();
    Init();
    AskClose();
}

test_dialog::test_dialog()
{
  super();

  ch1 = ch2 = TRUE;
  tx1 = "C4D";
  tx2 = "Cinema 4D";
  bt1 = bt2 = FALSE;
}

test_dialog::CreateLayout()
{
  SetTitle("test");

  AddGroupBeginV(10000 , BFH_SCALEFIT , 1 , "group" , 0);
    AddGroupBorder(BORDER_GROUP_IN);

    AddGroupBeginV(11000 , BFH_SCALEFIT , 2 , "group-1" , 0);
      AddGroupBorder(BORDER_GROUP_IN);

      AddCheckbox(100 , BFH_CENTER , 0 , 0 , "");
      AddEditText(101 , BFH_SCALEFIT , 0 , 0);
    AddGroupEnd();

    AddGroupBeginV(12000 , BFH_SCALEFIT , 2 , "group-1" , 0);
      AddGroupBorder(BORDER_GROUP_IN);

      AddCheckbox(200 , BFH_CENTER , 0 , 0 , "");
      AddEditText(201 , BFH_SCALEFIT , 0 , 0);
    AddGroupEnd();

    AddGroupBeginV(13000 , BFH_SCALEFIT , 2 , "group-1" , 0);
      AddGroupBorder(BORDER_GROUP_IN);

      AddButton(300 , BFH_SCALEFIT , 0 , 0 , "ボタンA");
      AddButton(301 , BFH_SCALEFIT , 0 , 0 , "ボタンB");
    AddGroupEnd();

  AddGroupEnd();

  AddDlgGroup(DR_DLGGROUP_OK | DR_DLGGROUP_CANCEL);
}

test_dialog::Init()
{
  SetCheckbox(100 , ch1);
  SetCheckbox(200 , ch2);
  SetString(101 , tx1);
  SetString(201 , tx2);
}

test_dialog::AskClose()
{
  println("ダイアログは閉じました。");
}



//main ===================================================
main(doc , op)
{
  var dlg = new(test_dialog);

  dlg->Open(-1 , -1);
  if(!dlg->GetResult())return;

  println("ok");
}

今回はダイアログから数値を取得しないので、AskClose()は必要なかったのですが、ダイアログが閉じられると呼ばれる事を確認するだけ。println()を実行させます。

このスクリプトを実行すると、こんなダイアログが表示されます。

Dialog_45

ここまで、ダイアログの学習を読まれた方は、このスクリプトのコメントは必要ないですね。

では、先に進めましょう。

ダイアログのウィジェットの操作をしたら呼ばれるメンバ関数を追加しオーバーライドします。
test_dialogクラスの定義部にCommand()を追加します。
引数は([int]id , [BaseContainer]msg)です。

//test_dialogクラス =======================================
class test_dialog:GeModalDialog
{
  public:
    var ch1 , ch2;//チェックボックス用
    var tx1 , tx2;//エディットテキスト用
    var bt1 , bt2;//ボタン用

    test_dialog();
    CreateLayout();
    Init();
    AskClose();
    Command(id , msg);
}

メンバ関数の定義をします。

test_dialog::Command(id , msg)
{
  println("ダイアログ上でユーザが何かしました。");
}

実行して開かれたダイアログのウィジェットをクリップすると、コンソールに表示されます。

OKボタンを押すと、Command()も呼ばれ、AskClose()は2度呼ばれるようですね。

ダイアログ上でユーザが何かしました。
ダイアログ上でユーザが何かしました。
ダイアログは閉じました。
ok

エディットテキストはテキストの内容を変更しないとCommand()は呼ばれないようです。
残りは、クリックしただけでCommand()は呼ばれました。

キャンセルボタンは、Command()とAskClose()が1回づつ呼ばれています。

ダイアログ上でユーザが何かしました。
ダイアログは閉じました。

もう、多分Command()の引数を見て気づかれていると思いますが、クリックされたウィジェットのIDが引数で渡されます。

Command()の定義を少し変えます。

test_dialog::Command(id , msg)
{
  println("ダイアログ上でユーザが " , id , " に何かしました。");
}

これで実行すると、クリックされたウィジェットのIDがコンソールに表示されます。

ダイアログのレイアウトで指定したIDが表示されたIDと同じか確認してください。

OKボタンのIDは…1
キャンセルボタンのIDは…2

そう言えば…
ダイアログの学習の最初に、エディットナンバーのウィジェットに数値を入力し、OKボタンを押したにもかかわらず、キャンセル扱いになる不具合は…
キャンセルボタンのIDとエディットナンバーのIDが衝突していたからですね…

引数のmsgは、メッセージなのですが不明です。
チェックボックス、エディットテキスト、OK、キャンセル、に関しては、msgに該当するものがありません。
モーダルダイアログだからだろうか?

では、Command()はこれで終わりかと言うとまだです。

では、チェックボックスのOn/Offで隣のエディットテキストの有効/無効を操作してみよう。
ウィジェットの有効/無効の操作はEnable(id , bool)を使います。
チェックボックスの値を取得し、その値をEnable()に渡します。

test_dialog::Command(id , msg)
{
  println("ダイアログ上でユーザが " , id , " に何かしました。");

  Enable(101 , GetCheckbox(100));
  Enable(201 , GetCheckbox(200));

  //AskClose()で最後に読み取るので、ここで変数を変更する必要は無いかも
  ch1 = GetCheckbox(100);
  ch2 = GetCheckbox(200);
}

チェックボックスID:100は、エディットテキストID:101
チェックボックスID:200は、エディットテキストID:201
に、対応しています。
実行して確認してください。
チェックボックスのOn/Offで隣のエディットテキストの有効/無効が切り替わります。

Dialog_46

このままでは、他のウィジェットが押されても実行されてしますので、switch()を使いますか…

test_dialog::Command(id , msg)
{
  println("ダイアログ上でユーザが " , id , " に何かしました。");

  switch(id)
  {
    case 100://チェックボックス
      Enable(101 , GetCheckbox(100));
      break;

    case 200://チェックボックス
      Enable(201 , GetCheckbox(200));
      break;

    case 300://ボタン

    case 301://ボタン

  }
}

では、ボタンAをクリックしたら2つのテキストを入れ替えてみましょう。
まずは、入れ替えようの変数を用意して、片方を保持し、もう片方の値を代入します。
保持した値をもう片方に代入します。

test_dialog::Command(id , msg)
{
  println("ダイアログ上でユーザが " , id , " に何かしました。");

  var swap;

  switch(id)
  {
    case 100://チェックボックス
      Enable(101 , GetCheckbox(100));
      break;

    case 200://チェックボックス
      Enable(201 , GetCheckbox(200));
      break;

    case 300://ボタン
      swap = GetString(101);
      SetString(101 , GetString(201));
      SetString(201 , swap);
      break;

    case 301://ボタン

  }
}

Dialog_47

文字列を操作できるので、1文字づつの操作も可能でしょう。
ボタンを沢山配置してソフトキーボードの様な物も作れるでしょう。

では、ボタンBをクリックしたら、別のダイアログを開いてみよう。
ダイアログから、ダイアログを開くよりタブを使った方が良いような…

ま、テストなので…

test_dialog::Command(id , msg)
{
  println("ダイアログ上でユーザが " , id , " に何かしました。");

  var swap;
  var newdlg = new(test_dialog);

  switch(id)
  {
    case 100://チェックボックス
      Enable(101 , GetCheckbox(100));
      break;

    case 200://チェックボックス
      Enable(201 , GetCheckbox(200));
      break;

    case 300://ボタン
      swap = GetString(101);
      SetString(101 , GetString(201));
      SetString(201 , swap);
      break;

    case 301://ボタン
      newdlg->Open(-1 , -1);
  }
}

新たにダイアログクラスを定義しても良かったのですが…
面倒だったので、同じクラスのダイアログを使いました。

ボタンBを押すと、同じレイアウトの新しいダイアログが開きます。
勿論モーダルなので、一番最後のダイアログのみのコントロールです。

Dialog_48

これで、ダイアログから新たなダイアログを開ける事が確認できました。

今回は…
Command()でダイアログが開いている時の作業ができ、
その中でもウィジェットからの値を読み取ったり適用したりできる事が分かりました。
あと、新しいダイアログを開ける事も…

|

« C4D ユーザスクリプトでモーダルダイアログの学習-03 | トップページ | 最近、「C4D 水 表現」で検索してこのブログへ… »