« C4D C.O.F.F.E.E.メニュープラグインにダイアログを…01 | トップページ | C4D ユーザスクリプトでモードレスダイアログを考えてみる… »

C4D C.O.F.F.E.E.メニュープラグインにダイアログを…02

「ユーザスクリプトでダイアログを学習」に付き合ってくれた人は、多分メニュープラグインでのモーダルダイアログの基本は問題ないと思います。

では、今回は、C4Dのレイアウトにも組み込め、ダイアログを開いていてもC4Dの作業を続けられるノンモーダル(モードレス)ダイアログを試してみよう。

さて、モードレスダイアログは…?

モードレスダイアログもモーダルダイアログも使っているウィジェット等が共通なので、全くの別物というわけではないのですね。

では、モードレスダイアログの使い方は…
C4Dが起動している間、ダイアログの割り当てを確保する必要があるそうだ。
要するにC4Dが起動中、保持されるグローバル変数にダイアログを割り当てる。
これは、ユーザスクリプトでは不可能な事ですね。

モードレスという事なので、[OK/キャンセル]ボタンは用済みになりますね。
と言うか…使った場合は、ボタンを押すと閉じてしまうのだ…
その代わりに、標準のウィジェットのボタンを使ってのダイアログの数値を適用する事でしょう。
ダイアログを閉じたときに実行されるメンバ関数AskClose()もあまり重要ではなくなります。
その代わりにCommand()メンバ関数が重要になります。
メニューから呼ばれたときに実行されるMenuPlugin::Execute()も単純にダイアログを開くだけの処理になるでしょう。

さて、モードレスダイアログをメニュープラグインに組み込む具体的な方法を…
モーダルダイアログ使うときは、GeModalDialogクラスのサブクラスを使いました。
モードレスダイアログは、GeDialogクラスのサブクラスを使います。

GeBaseDialog
└ GeUserDialog
  └ GeDialog  モードレスダイアログを使う時
    └ GeModalDialog  モーダルダイアログを使う時

  • C4Dに組み込む時に、グローバル変数にGeDialogクラスのサブクラスを割り当てます。
  • メニュープラグインは通常通りRegister()でC4DへMenuPluginクラスのサブクラスを登録します。

  • モードレスダイアログ本体のGeDialogクラスのサブクラスのコンストラクタからsuper()を使ってプラグインIDを渡します。

  • C4Dユーザがメニューからプラグインを呼んだとき、ダイアログのOpen()メンバ関数でダイアログを開きます。

  • 保存されたレイアウトにプラグインのダイアログが組み込まれているとC4D自体がプラグインダイアログを開く為にメニュープラグインのメンバ関数RestoreLayout()が呼ばれます。
    組み込み自体はダイアログのメンバ関数RestoreLayout()です。(まぎわらしい…)

では、実際にモードレスダイアログを組み込んだメニュープラグインを組んでみよう。
ただし最小限です。
今までのコードを流用してもいいのですが、最初から…

まずは、基本的な所から…

/*
モードレスダイアログのテスト
2009.8.11
*/



//グローバル変数============================================



//ダイアログ===============================================



//メニュープラグイン=========================================



//メイン==================================================
main()
{

}

あまりにも…
基本を通り過ぎて骨…骨すらも無い…

では、モードレスダイアログの為のグローバル変数の宣言。
プラグインIDもグローバル変数にします。

/*
モードレスダイアログのテスト
2009.8.11
*/



//グローバル変数============================================
var dlg;
var pluginID = 1000001;

では、ダイアログです。
GeDialogクラスのサブクラスを使います。
コンストラクタのsuper()でプラグインIDを渡します。

Dialog_10

//ダイアログ===============================================
class test_dialog:GeDialog
{
  public:
    test_dialog();
    CreateLayout();
    Command(id , msg);
}

test_dialog::test_dialog()
{
  super(pluginID);//スーパークラスのコンストラクタにプラグインIDを渡す
}

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

  AddGroupBeginV(10000 , BFH_SCALEFIT , 2 , "group-1" , 0);
    AddStaticText(10001 , BFH_CENTER , 0 , 0 , "項目" , 0);
    AddEditNumber(10002 , BFH_SCALEFIT , 0 , 0);
  AddGroupEnd();

  AddGroupBeginH(20000 , BFH_SCALEFIT , 1 , "group-2" , 0);
    AddButton(20001 , BFH_SCALEFIT , 0 , 0 , "適用");
   
  AddGroupEnd();
}

test_dialog::Command(id , msg)
{
  println("Command()内   ID : " , id);
}

メニュープラグイン本体です。
メニュープラグインのExecute()メンバ関数でのダイアログを開く為のOpen()メンバ関数は、GeModalDialogクラスのものではなく、GeBaseDialogクラスのものです。
引数が3個あり、後の2個は、GeModalDialogクラスのOpen()同様座標です。
最初の1つは、モードレスか否かです。TRUEを指定したのでモードレスです。
モーダルダイアログを使うとき、GeModalDialogのサブクラスを使いましたが、GeDialogクラスのサブクラスでも可能と言うことです。
そのときは、「OK/キャンセル」ボタンの処理等を自分で全て処理しなければいけなくなります。
もしかして、OK/キャンセルボタンを押すとAskClose()が2回呼ばれるのは、この事に関係が…?

メニュープラグインのRestoreLayout()は、保存されたレイアウトを呼んだときにプラグインダイアログが含まれたときに呼ばれます。
それ以外は、断定はできませんが必要ないようです。詳しく確認はしていません。

さて、メニュープラグインのRestoreLayout()には引数secretがありますが…
SDKには、詳しい説明が見当たりません。
secret… 秘密…なのか?
データ型はvoid…C.O.F.F.E.E.使いには馴染みではないですが…型無し…
さらにダイアログ関連のクラスにもRestoreLayout()メンバ関数の説明が無い…
メニュープラグインのRestoreLayout()に渡される物は何なのか?
ダイアログのRestoreLayout()に渡すものは何なのか?
秘密らしい…
だからと言って、クラスの定義等からこの引数を削除すると、C4Dの読み込み時にはエラーを起こさないが、このプラグインのダイアログを含んだレイアウトを読み込むとエラーが出ます。

要するに、「気にしないで、例に従って組んでくれたまえ」という事らしい…

//メニュープラグイン=========================================
class test_plug:MenuPlugin
{
  public:
    test_plug();
    GetID();
    GetName();
    GetHelp();
    Execute(doc);
    RestoreLayout(secret);
}

test_plug::test_plug()
{
  super();
}

test_plug::GetID()
{
  return pluginID;
}

test_plug::GetName()
{
  return "test plug";
}

test_plug::GetHelp()
{
  return "テストです。";
}

test_plug::Execute(doc)
{
  dlg->Open(TRUE , -1 , -1);
}

test_plug::RestoreLayout(secret)
{
  dlg->RestoreLayout(secret);
}

C4D起動時のプラグイン組み込みの為のメイン関数
グローバル変数dlgにモードレスダイアログとして組み込むtest_dialogクラスを割り当てます。
メニュープラグインとしてtest_plugクラスをC4Dへ登録します。

//メイン==================================================
main()
{
  dlg = new(test_dialog);
  Register(test_plug);
}

これで、このプラグインのダイアログは、モードレスでレイアウトにも組み込む事ができます。

Dialog_11

確認してください。
ダイアログをレイアウトに組み込んで、ウィンドウ/レイアウト/レイアウトを別名で保存...を実行し、左上のアイコンから保存したレイアウトを呼び出してください。
ダイアログが組み込まれていれば成功です。

Dialog_12

さて、ダイアログを開いたり、レイアウトに組み込んだりする前に、変数に割り当てられているか確認してください。
割り当てられていなければ、再度割り当ててください。

if(!dlg)dlg = new(test_dialog);

上のプラグインには、確認の部分が抜けています。

それでは、全体をまとめます。

/*
モードレスダイアログのテスト
2009.8.11
*/



//グローバル変数============================================
var dlg;
var pluginID = 1000001;


//ダイアログ===============================================
class test_dialog:GeDialog
{
  public:
    test_dialog();
    CreateLayout();
    Command(id , msg);
}

test_dialog::test_dialog()
{
  super(pluginID);//親コンストラクタにプラグインIDを渡す
}

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

  AddGroupBeginV(10000 , BFH_SCALEFIT , 2 , "group-1" , 0);
    AddStaticText(10001 , BFH_CENTER , 0 , 0 , "項目" , 0);
    AddEditNumber(10002 , BFH_SCALEFIT , 0 , 0);
  AddGroupEnd();

  AddGroupBeginH(20000 , BFH_SCALEFIT , 1 , "group-2" , 0);
    AddButton(20001 , BFH_SCALEFIT , 0 , 0 , "適用");
   
  AddGroupEnd();
}

test_dialog::Command(id , msg)
{
  println("Command()内   ID : " , id);
}


//メニュープラグイン=========================================
class test_plug:MenuPlugin
{
  public:
    test_plug();
    GetID();
    GetName();
    GetHelp();
    Execute(doc);
    RestoreLayout(secret);
}

test_plug::test_plug()
{
  super();
}

test_plug::GetID()
{
  return pluginID;
}

test_plug::GetName()
{
  return "test plug";
}

test_plug::GetHelp()
{
  return "テストです。";
}

test_plug::Execute(doc)
{
  if(!dlg)dlg = new(test_dialog);
  dlg->Open(TRUE , -1 , -1);
}

test_plug::RestoreLayout(secret)
{
  if(!dlg)dlg = new(test_dialog);
  dlg->RestoreLayout(secret);
}


//メイン==================================================
main()
{
  dlg = new(test_dialog);
  Register(test_plug);
}

もちろん、これはモードレスダイアログのテストなので、実際何かするプラグインではありません。

さてこれで、ユーザスクリプトでも基本的なダイアログが、使えるような知識を取得したし…
メニュープラグインでも、基本的なダイアログを…モーダルでもモードレスでも使える知識を得たし…

|

« C4D C.O.F.F.E.E.メニュープラグインにダイアログを…01 | トップページ | C4D ユーザスクリプトでモードレスダイアログを考えてみる… »