« C4D ワイドレンズやFishEyeのようにレンズディストーション… | トップページ | C4D ダイアログのユーザエリアの定期的な割り込み処理… »

C4D ダイアログのガジェットのひとつ、ユーザエリアのテストをユーザスクリプトで行ってみる。

以前のダイアログの記事で、一度も取り上げていないユーザエリアをテストします。
ダイアログにビットマップを表示したり、線を引いたり…
自分で独自のGUIのパーツを作る為の…
独自のスライダーだったり、独自のボタンだったり…

でも、今回テストするのは初歩的なもので…
独自のガジェット作成するわけではないのだ…

マニュアルには、3Dトラックボールとかオブジェクトマネージャの様に階層リストも作れると書いてある…
大昔C4Dユーザの駆け出しの頃に、これを読んで…
「ユーザエリアは、簡単に3Dトラックボールの機能を持たせられるのか…」
「3Dトラックボールを作るための、特別なものが用意されているんだ…」
なんて思ったんですけどね…

まんまと騙されました…
そう、「全く無理ではなく、頑張ればできますよ。」って言うこと…
「全部一から作るんだけどね…」

多分トラックボールのガジェットを作るとなると…
C4Dでトラックボールをモデリング/レンダリングして…
レンダリング画像をユーザエリアに貼り付けて…
マウスのスクラッチ量を取得して、ダイアログに渡す…
こんな感じだろうか…

Poserの様な3Dトラックボールのインターフェイスが必要だろうか?
C4Dはビュー上でAltキー+マウスドラッグで視野を回転できるし…

まぁ、そんな事はどうでも良いですね…

今回はプラグインではなく、手軽なユーザスクリプトでの作業です。

さて、ユーザエリアは…
GeUserAreaクラスですね。
モーダルダイアログのように、グローバル変数に割り当てとか、気を付けることはあるのだろうか…
その辺は、まぁテストしていくうちにわかるだろう…

まずは、ユーザエリアを配置するダイアログを…
今回のダイアログは、ユーザエリアを配置するだけなので、最小限で…
配置するガジェットは、ユーザエリアとダイアロググループ(OK/キャンセルボタン)のみ…

/*
ダイアログのユーザエリアのテスト
久々のC.O.F.F.E.E.だ…
2009.9.16
*/



//ダイアログ ---------------------------------------------
class testDialog:GeModalDialog
{
  public:
    testDialog();  //コンストラクタ
    CreateLayout();//ダイアログレイアウト
}

//コンストラクタ
testDialog::testDialog()
{
  super();
}

//ダイアログレイアウト
testDialog::CreateLayout()
{
  SetTitle("testDialog");

//  AddUserArea(1000 , 0 , 500 , 400);
  AddDlgGroup(DR_DLGGROUP_OK|DR_DLGGROUP_CANCEL);
 
}



//メイン ------------------------------------------------
main(doc , op)
{
  var dlg = new(testDialog);
  dlg->Open(-1 , -1);
}

まぁ、シンプルで…
実行すると…

Userarea_01

ただ、開くだけですからね。
レイアウトのダイアロググループの上にユーザエリアを配置します。
今はコメント化してありますが…
配置予定のユーザエリアは、サイズ500×400です。

コメントを外してもエラーにはならないようですね。

Userarea_02

って言うか…
500×400のはずだが…なんで縦に長いのかね…
ま、全てを定義していないからだろうけど…

あ、ごめんなさい…C4D R10 Demoだったんで、ここからR11 Demoを使います。
ってアンタ!まだDemoかい!ま、そのうちね…

さて、UserAreaの最低限の定義は…?
とりあえず、ダイアログの前に定義します。

//ユーザエリア -----------------------------------------
class testUserArea:GeUserArea
{
  public:
    testUserArea(id , dlg); //コンストラクタ
    Init();                 //初期化
    GetUserWidth();         //幅
    GetUserHeight();        //高さ
    Draw(x1 , y1 , x2 , y2);//描画
}

//コンストラクタ
testUserArea::testUserArea(id , dlg)
{
  super(id , dlg);
}

//初期化
testUserArea::Init()
{
  println("Init()");
}

//幅
testUserArea::GetUserWidth()
{
  return 500;
}

//高さ
testUserArea::GetUserHeight()
{
  return 400;
}

//描画
testUserArea::Draw(x1 , y1 , x2 , y2)
{
  println("Draw()");
}

多分これで最小限だと思います。
あえてオーバーライドしなくても良いメンバ関数はありますが…

ユーザエリアのコンストラクタには、idとユーザエリアを取り付けるダイアログを渡します。
idは、ダイアログのレイアウト中でガジェットに指定するidです。
コンストラクタに渡して、super()で更にGeUserAreaクラスコンストラクタに渡します。
これだけのようです。
後は、変数を初期化したり…

Init()メンバ関数は、GUIによってユーザエリアを初期化されるときに呼ばれるようです。
変数等の初期化をここでするようですが、必要なければ省略してもよいみたいです。
省略してもエラーにはなりません。

GetUserWidth()は単純に幅をreturnで返せば良いだけ…
マニュアルには詳しく書いていませんが、GUIがレイアウトの調整するときに、呼ばれるのだろう…

GetUserHeight()も多分同じだろうと…

Draw()は、ユーザエリアが再描画されるたびに呼ばれる所で、そのつどユーザエリアをここで更新する。
更新すべき領域、左上(x1 , y1)右下(x2 , y2)の座標が渡される。

この状態で実行してもユーザエリアは、まともに動作しません。

さて、この新たに定義したユーザエリアを動作させるにはどうするのか?

ダイアログ同様、new()を使って変数に割り当てます。
割り当てる場所は、ダイアログのCreateLayout()内で行います。
CreateLayout()内ならどこでも良いと言う訳ではありません。
ガジェットのユーザエリアを組み込んだ後、要するにAddUserArea()の後に変数に割り当てます。
レイアウトにガジェットとしてのユーザエリアが先に組み込まれていなければならないと…

//ダイアログレイアウト
testDialog::CreateLayout()
{
  SetTitle("testDialog");

  AddUserArea(1000 , 0 , 500 , 400);
  u_area = new(testUserArea , 1000 , this);

  AddDlgGroup(DR_DLGGROUP_OK|DR_DLGGROUP_CANCEL);
}

変数u_areaにtestUserAreaを割り当てました。id : 1000…
thisは、初めて説明しますが、クラス内でこのクラスを指定するときに使います。

新たに定義したtestUserAreaを割り当てた変数u_areaは…
ここで宣言するのであればvarを前に付けますが、CreateLayout()から出るとなくなってしまいます。
今回はモーダルダイアログだし、イベント処理もないから大丈夫なのだろうが…
やはり、ダイアログのメンバ変数として宣言したほうが良いでしょう…

class testDialog:GeModalDialog
{
  public:
    var u_area;    //ユーザエリア変数

    testDialog();  //コンストラクタ
    CreateLayout();//ダイアログレイアウト
}

さて、いよいよ実行です…

Userarea_03

スクリプトが実行されても、ユーザエリアのDraw()には描画処理がまだ無い為、更新されません。

一旦ブラウザー(IE)をアクティブにして、C4Dへ戻ってくると…

Userarea_04

IEで表示されていた画像の一部が残ったままです。

では、ユーザエリアのDraw()で更新します。
今回は、黒でユーザエリアを塗りつぶします。

testUserArea::Draw(x1 , y1 , x2 , y2)
{
  println("Draw()");

  DrawSetPen(vector(0.0));
  DrawRectangle(x1 , y1 , x2 , y2);
}

描画色を設定する為に、GeUserAreaクラスのDrawSetPen([vector]color)メンバ関数を使います。
更新すべき領域をDrawRectangle([int]x1 , [int]y1 , [int]x2 , [int]y2)メンバ関数で長方形で塗りつぶします。

Userarea_05

今度は、ユーザエリアが黒く塗りつぶされました。
他のアプリケーションからC4Dへ切り替えても更新されます。

Draw()メンバ関数は、更新が必要な時に呼ばれます。
ダイアログを開いたとき。
ユーザエリアにフォーカスされた時(クリックされアクティブになった時)
他のガジェットをクリックしたとき。
他のアプリケーションからC4Dへ切り替わったとき。

このスクリプトは、ユーザエリアの更新が起こる度にコンソールに"Draw()"と表示されます。
どんな時に表示されるか確認して下さい。

この他に、自分で更新させる事もできます。

では、ユーザエリアに、何か描画してみましょう。
GeUserAreaクラスで用意しているものは…
先ほどの、矩形描画DrawRectangle()
ライン描画DrawLine()
ビットマップ表示DrawBitmap()
テキスト描画DrawText()
等があります。

まずは、ラインから…
ユーザエリアの1つの白い対角線を引いてみます。

testUserArea::Draw(x1 , y1 , x2 , y2)
{
  println("Draw()");

  DrawSetPen(vector(0.0));
  DrawRectangle(x1 , y1 , x2 , y2);
  DrawSetPen(vector(1.0));
  DrawLine(x1 , y1 , x2 , y2);
}

Userarea_06

テキストを表示してみます。

testUserArea::Draw(x1 , y1 , x2 , y2)
{
  println("Draw()");

  DrawSetPen(vector(0.0));
  DrawRectangle(x1 , y1 , x2 , y2);
  DrawSetPen(vector(1.0));
  DrawLine(x1 , y1 , x2 , y2);
  DrawSetTextPen(vector(0.5 , 1.0 , 1.0) , vector(0.3 , 0.3 , 0.5));
  DrawText("test" , 100 , 200);
}

DrawSetTextPen([vector]f_color , [vector]b_color)メンバ関数はテキストのフォアグランドとバックグラウンドのカラーを指定します。
DrawText([string]text , [int]x , [int]y)メンバ関数で、文字列と座標を指定し表示します。

Userarea_07

ところで、フォントのサイズの指定はどうするんだろうか…
見当たらないから保留…

ビットマップは、ビットマップファイルを用意して、Filenameクラスで読み込むのが面倒くさいので…
スクリプト内でビットマップを生成します。
ビットマップを割り当てる変数はグローバルにします。

/*
ダイアログのユーザエリアのテスト
久々のC.O.F.F.E.E.だ…
2009.9.16
*/


var bm;//ビットマップ用


//ユーザエリア -----------------------------------------
class testUserArea:GeUserArea
{
  public:
    testUserArea(id , dlg); //コンストラクタ
    Init();                 //初期化

main()関数内でビットマップを生成します。

main(doc , op)
{
  bm = new(BaseBitmap , 100 , 100);
  bm->SetPen(vector(1.0 , 0.0 , 0.0));
  bm->DrawRect(0 , 0 , 99 , 99);
  bm->SetPen(vector(1.0 , 1.0 , 0.0));
  bm->DrawRect(10 , 10 , 89 , 89);

  var dlg = new(testDialog);
  dlg->Open(-1 , -1);
}

これで、表示するビットマップが完成しました。
サイズは100×100。
周りが赤で中が黄色の正方形。

Userarea_08

これを、ユーザエリアに表示させます。

testUserArea::Draw(x1 , y1 , x2 , y2)
{
  println("Draw()");

  DrawSetPen(vector(0.0));
  DrawRectangle(x1 , y1 , x2 , y2);
  DrawSetPen(vector(1.0));
  DrawLine(x1 , y1 , x2 , y2);
  DrawSetTextPen(vector(0.5 , 1.0 , 1.0) , vector(0.3 , 0.3 , 0.5));
  DrawText("test" , 100 , 200);
  DrawBitmap(bm , 0 , 0 , 99 , 99   , 250 , 250 , 349 , 349 , BMP_NORMAL);
}

DrawBitmap([BaseBitmap]bm ,
                    [int]bmx1 , [int]bmy1 , [int]bmx2 , [int]bmy2 ,
                    [int]arx1 , [int]ary1 , [int]arx2 , [int]ary2 ,
                    [int]mode)メンバ関数は…
表示するビットマップと、ビットマップの表示する切り出す領域の左上と右下の座標…
ビットマップを表示するユーザエリアの領域の左上と右下の座標…
転写モード。

Userarea_09

主な描画は、試しました。

ここでひとつ…
何も指定せずにエリア外の座標を指定して描画すると、はみ出して描画されるらしい。

testUserArea::Draw(x1 , y1 , x2 , y2)
{
  println("Draw()");

  DrawSetPen(vector(0.0));
  DrawRectangle(x1 , y1 , x2 , y2);
  DrawSetPen(vector(1.0));
  DrawLine(x1 , y1 , x2 , y2);
  DrawSetTextPen(vector(0.5 , 1.0 , 1.0) , vector(0.3 , 0.3 , 0.5));
  DrawText("test" , 100 , 200);
  DrawBitmap(bm , 0 , 0 , 99 , 99   , 250 , 250 , 349 , 449 , BMP_NORMAL);
}

Userarea_10

本当に、はみ出した…

これを防止する為のメンバ関数があります。
SetClippingRegion([int]x1 , [int]y1 , [int]x2 , [int]y2);
これを指定してユーザエリアに描画するとクリップされ指定範囲外の描画を阻止できます。
では、Draw()メンバ関数内で描画が始まる前に実行します。

testUserArea::Draw(x1 , y1 , x2 , y2)
{
  println("Draw()");

  SetClippingRegion(0 , 0 , 499 , 399);

  DrawSetPen(vector(0.0));
  DrawRectangle(x1 , y1 , x2 , y2);
  DrawSetPen(vector(1.0));
  DrawLine(x1 , y1 , x2 , y2);
  DrawSetTextPen(vector(0.5 , 1.0 , 1.0) , vector(0.3 , 0.3 , 0.5));
  DrawText("test" , 100 , 200);
  DrawBitmap(bm , 0 , 0 , 99 , 99   , 250 , 250 , 349 , 449 , BMP_NORMAL);
}

Userarea_11

あ、ごめんなさい、ビットマップの色を間違って変更してしまった…
決して、クリッピングしたら色が変わるわけではないので…って、横着しないでキャプチャし直せよ…

クリッピングされ範囲外には描画されません。

このクリッピングを解除するには、
ClearClippingRegion()を使うそうな…

これで最低限、描画に必要なテストは終わったと…

次は、マウスクリックやキーボードからのイベントを受けてみる。
ユーザエリアにフォーカスされている…ユーザエリアがアクティブのとき…
イベントが起こると呼ばれるメンバ関数InputEvent(msg)を使います。

クラスの定義に追加します。

//ユーザエリア -----------------------------------------
class testUserArea:GeUserArea
{
  public:
    testUserArea(id , dlg); //コンストラクタ
    Init();                 //初期化
    GetUserWidth();         //幅
    GetUserHeight();        //高さ
    Draw(x1 , y1 , x2 , y2);//描画
    InputEvent(msg);        //デバイスからの入力
}

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

testUserArea::InputEvent(msg)
{
  println("InputEvent()");
}

これで実行すると、ユーザエリアがアクティブのとき…
マウスクリック、ホイール、キーボード入力すると、コンソールに"InputEvent()"が表示されます。
このままでは、入力が有るか無いかしかわかりません。
何から、どんな入力が有ったかを知る必要が有ります。
入力情報は、InputEvent()に渡されたmsgコンテナからデータを取得します。
コンテナからのデータ取得は、BaseContainerクラスのGetData(id)メンバ関数を使います。

では、入力をコンソールに表示させていきます。
入力機器はマウスかキーボードか?

testUserArea::InputEvent(msg)
{
  println("InputEvent()");

  //入力デバイスの取得
  if(msg->GetData(BFM_INPUT_DEVICE) == BFM_INPUT_MOUSE)println("マウス入力がありました。");
  if(msg->GetData(BFM_INPUT_DEVICE) == BFM_INPUT_KEYBOARD)println("キーボード入力がありました。");
}

これで実行すると、クリックしたりキー入力があれば、マウスなのかキーボードなのかコンソールに表示されます。
今回はif()を使いましたが、switch()でも…

msgコンテナから、入力デバイスを取得する為のIDは…
BFM_INPUT_DEVICE

比較するする定数は…
BFM_INPUT_MOUSE //マウス
BFM_INPUT_KEYBOARD  //キーボード

次に、デバイスのキーコードを取得します。
マウスのボタン、キーボードのキーの生のコード。
キャラクタのアスキーコードではありません。

testUserArea::InputEvent(msg)
{
  println("InputEvent()");

  //入力デバイスの取得
  if(msg->GetData(BFM_INPUT_DEVICE) == BFM_INPUT_MOUSE)println("マウス入力がありました。");
  if(msg->GetData(BFM_INPUT_DEVICE) == BFM_INPUT_KEYBOARD)println("キーボード入力がありました。");

  //キーコードの取得
  switch(msg->GetData(BFM_INPUT_CHANNEL))
  {
    case BFM_INPUT_MOUSELEFT:
      println("マウス左ボタン");
      break;
    case BFM_INPUT_MOUSERIGHT:
      println("マウス右ボタン");
      break;
    case BFM_INPUT_MOUSEMIDDLE:
      println("マウス中ボタン");
      break;
    case BFM_INPUT_MOUSEWHEEL:
      println("マウスホイール");
      break;
    default:
      println("キーコード: " , msg->GetData(BFM_INPUT_CHANNEL));
  }
}

これで実行すると、マウスはボタン名、キーボードはキーコードが表示されます。

マウスのボタンには定数が用意されていますが…
キーボードのキーには用意されていないので、判別するときは、数値で比較します。

msgコンテナからキーコードを取得する為のIDは…
BFM_INPUT_CHANNEL

マウスボタンの比較する定数は…
BFM_INPUT_MOUSELEFT  //左ボタン
BFM_INPUT_MOUSERIGHT  //右ボタン
BFM_INPUT_MOUSEMIDDLE  //中ボタン
BFM_INPUT_MOUSEWHEEL  //ホイール

次はキーボードから入力されたキャラクターの取得。

testUserArea::InputEvent(msg)
{
  println("InputEvent()");

  //入力デバイスの取得
  if(msg->GetData(BFM_INPUT_DEVICE) == BFM_INPUT_MOUSE)println("マウス入力がありました。");
  if(msg->GetData(BFM_INPUT_DEVICE) == BFM_INPUT_KEYBOARD)println("キーボード入力がありました。");

  //キーコードの取得
  switch(msg->GetData(BFM_INPUT_CHANNEL))
  {
    case BFM_INPUT_MOUSELEFT:
      println("マウス左ボタン");
      break;

    case BFM_INPUT_MOUSERIGHT:
      println("マウス右ボタン");
      break;

    case BFM_INPUT_MOUSEMIDDLE:
      println("マウス中ボタン");
      break;

    case BFM_INPUT_MOUSEWHEEL:
      println("マウスホイール");
      break;

    default:
      println("キーコード: " , msg->GetData(BFM_INPUT_CHANNEL));
  }

  //入力文字の取得
  println("入力文字: " , msg->GetData(BFM_INPUT_ASC));
}

キーボードからの入力は文字が取得されますが、マウスボタンの場合はnilになります。

msgコンテナから入力文字の取得の為のIDは…
BFM_INPUT_ASC

続いては、マウスのダブルクリックか否かを取得します。

testUserArea::InputEvent(msg)
{
  println("InputEvent()");

  //入力デバイスの取得
  if(msg->GetData(BFM_INPUT_DEVICE) == BFM_INPUT_MOUSE)println("マウス入力がありました。");
  if(msg->GetData(BFM_INPUT_DEVICE) == BFM_INPUT_KEYBOARD)println("キーボード入力がありました。");

  //キーコードの取得
  switch(msg->GetData(BFM_INPUT_CHANNEL))
  {
    case BFM_INPUT_MOUSELEFT:
      println("マウス左ボタン");
      break;

    case BFM_INPUT_MOUSERIGHT:
      println("マウス右ボタン");
      break;

    case BFM_INPUT_MOUSEMIDDLE:
      println("マウス中ボタン");
      break;

    case BFM_INPUT_MOUSEWHEEL:
      println("マウスホイール");
      break;

    default:
      println("キーコード: " , msg->GetData(BFM_INPUT_CHANNEL));
  }

  //入力文字の取得
  println("入力文字: " , msg->GetData(BFM_INPUT_ASC));

  //ダブルクリックの取得
  if(msg->GetData(BFM_INPUT_DOUBLECLICK))println("ダブルクリック");
}

これで、マウスがダブルクリックされたかどうかが判ります。
この判定は、ダブルクリックの最初のクリックはシングルクリックで…
2回目のクリックがダブルクリックと判定されます。

msgコンテナからのダブルクリックの取得の為のIDは…
BFM_INPUT_DOUBLECLICK

次に、クリックしたときのマウスの座標を取得します。

testUserArea::InputEvent(msg)
{
  println("InputEvent()");

  //入力デバイスの取得
  if(msg->GetData(BFM_INPUT_DEVICE) == BFM_INPUT_MOUSE)println("マウス入力がありました。");
  if(msg->GetData(BFM_INPUT_DEVICE) == BFM_INPUT_KEYBOARD)println("キーボード入力がありました。");

  //キーコードの取得
  switch(msg->GetData(BFM_INPUT_CHANNEL))
  {
    case BFM_INPUT_MOUSELEFT:
      println("マウス左ボタン");
      break;

    case BFM_INPUT_MOUSERIGHT:
      println("マウス右ボタン");
      break;

    case BFM_INPUT_MOUSEMIDDLE:
      println("マウス中ボタン");
      break;

    case BFM_INPUT_MOUSEWHEEL:
      println("マウスホイール");
      break;

    default:
      println("キーコード: " , msg->GetData(BFM_INPUT_CHANNEL));
  }

  //入力文字の取得
  println("入力文字: " , msg->GetData(BFM_INPUT_ASC));

  //ダブルクリックの取得
  if(msg->GetData(BFM_INPUT_DOUBLECLICK))println("ダブルクリック");

  //マウスの座標の取得
  print("X: " , msg->GetData(BFM_INPUT_X) , " => ");
  println("Global2LocalX()=" , Global2LocalX(msg->GetData(BFM_INPUT_X)));
  print("Y: " , msg->GetData(BFM_INPUT_Y) , " => ");
  println("Global2LocalY()=" , Global2LocalY(msg->GetData(BFM_INPUT_Y)));
}

ここで実行すると、2種類の数値が表示されます。
単純に取得したXYと、Global2Localで変換されたXYです。

コンテナmsgから直接取得した座標は、ダイアログの原点からの座標です。

Userarea_12

Global2Localで変換した座標は、ユーザエリアの原点からの座標です。

msgコンテナからのダイアログ座標系でのマウス座標の取得の為のIDは…
BFM_INPUT_X
BFM_INPUT_Y
BFM_INPUT_Z

ダイアログ座標系からユーザエリア座標系への変換の為のメンバ関数…(ただの引き算ですけどね…)
Global2LocalX([int]x)
Global2LocalX([int]y)

msgコンテナからの座標の取得はZもありますが…
ユーザエリアへの変換はZがありません…2Dだから当たり前ではありますが…
でZ値は、何に対応しているの?

最後に、ホイールからの数値の取得。

testUserArea::InputEvent(msg)
{
  println("InputEvent()");

  //入力デバイスの取得
  if(msg->GetData(BFM_INPUT_DEVICE) == BFM_INPUT_MOUSE)println("マウス入力がありました。");
  if(msg->GetData(BFM_INPUT_DEVICE) == BFM_INPUT_KEYBOARD)println("キーボード入力がありました。");

  //キーコードの取得
  switch(msg->GetData(BFM_INPUT_CHANNEL))
  {
    case BFM_INPUT_MOUSELEFT:
      println("マウス左ボタン");
      break;

    case BFM_INPUT_MOUSERIGHT:
      println("マウス右ボタン");
      break;

    case BFM_INPUT_MOUSEMIDDLE:
      println("マウス中ボタン");
      break;

    case BFM_INPUT_MOUSEWHEEL:
      println("マウスホイール");
      break;

    default:
      println("キーコード: " , msg->GetData(BFM_INPUT_CHANNEL));
  }

  //入力文字の取得
  println("入力文字: " , msg->GetData(BFM_INPUT_ASC));

  //ダブルクリックの取得
  if(msg->GetData(BFM_INPUT_DOUBLECLICK))println("ダブルクリック");

  //マウスの座標の取得
  print("X: " , msg->GetData(BFM_INPUT_X) , " => ");
  println("Global2LocalX()=" , Global2LocalX(msg->GetData(BFM_INPUT_X)));
  print("Y: " , msg->GetData(BFM_INPUT_Y) , " => ");
  println("Global2LocalY()=" , Global2LocalY(msg->GetData(BFM_INPUT_Y)));

  //ホイールからの取得
  println("ホイール数値: " , msg->GetData(BFM_INPUT_VALUE));
}

ホイールからの数値の取得は-120か120が通常の値のようです。
速く回すと-240や240、-360や360が取得できます。
キーダウンは1です。
感圧デバイスからも対応しているようですが今回は、確認しません。

msgコンテナからホイールの数値の取得する為のIDは…
BFM_INPUT_VALUE

これで、入力デバイスからの取得は、ほぼ対応できると思います。

まだユーザエリアの基本的なテストは全てではないですが、今回は、ここで終了です。
最後に、全ての一連でコードを…

/*
ダイアログのユーザエリアのテスト
久々のC.O.F.F.E.E.だ…
2009.9.16
*/


var bm;//ビットマップ用

//ユーザエリア -----------------------------------------
class testUserArea:GeUserArea
{
  public:
    testUserArea(id , dlg); //コンストラクタ
    Init();                 //初期化
    GetUserWidth();         //幅
    GetUserHeight();        //高さ
    Draw(x1 , y1 , x2 , y2);//描画
    InputEvent(msg);        //デバイスからの入力
}

//コンストラクタ
testUserArea::testUserArea(id , dlg)
{
  super(id , dlg);
}

//初期化
testUserArea::Init()
{
  println("Init()");
}

//幅
testUserArea::GetUserWidth()
{
  return 500;
}

//高さ
testUserArea::GetUserHeight()
{
  return 400;
}

//描画
testUserArea::Draw(x1 , y1 , x2 , y2)
{
  println("Draw()");

  SetClippingRegion(0 , 0 , 499 , 399);

  DrawSetPen(vector(0.0));
  DrawRectangle(x1 , y1 , x2 , y2);
  DrawSetPen(vector(1.0));
  DrawLine(x1 , y1 , x2 , y2);
  DrawSetTextPen(vector(0.5 , 1.0 , 1.0) , vector(0.3 , 0.3 , 0.5));
  DrawText("test" , 100 , 200);
  DrawBitmap(bm , 0 , 0 , 99 , 99   , 250 , 250 , 349 , 449 , BMP_NORMAL);
}

//デバイスからの入力
testUserArea::InputEvent(msg)
{
  println("InputEvent()");

  //入力デバイスの取得
  if(msg->GetData(BFM_INPUT_DEVICE) == BFM_INPUT_MOUSE)println("マウス入力がありました。");
  if(msg->GetData(BFM_INPUT_DEVICE) == BFM_INPUT_KEYBOARD)println("キーボード入力がありました。");

  //キーコードの取得
  switch(msg->GetData(BFM_INPUT_CHANNEL))
  {
    case BFM_INPUT_MOUSELEFT:
      println("マウス左ボタン");
      break;

    case BFM_INPUT_MOUSERIGHT:
      println("マウス右ボタン");
      break;

    case BFM_INPUT_MOUSEMIDDLE:
      println("マウス中ボタン");
      break;

    case BFM_INPUT_MOUSEWHEEL:
      println("マウスホイール");
      break;

    default:
      println("キーコード: " , msg->GetData(BFM_INPUT_CHANNEL));
  }

  //入力文字の取得
  println("入力文字: " , msg->GetData(BFM_INPUT_ASC));

  //ダブルクリックの取得
  if(msg->GetData(BFM_INPUT_DOUBLECLICK))println("ダブルクリック");

  //マウスの座標の取得
  print("X: " , msg->GetData(BFM_INPUT_X) , " => ");
  println("Global2LocalX()=" , Global2LocalX(msg->GetData(BFM_INPUT_X)));
  print("Y: " , msg->GetData(BFM_INPUT_Y) , " => ");
  println("Global2LocalY()=" , Global2LocalY(msg->GetData(BFM_INPUT_Y)));

  //ホイールからの取得
  println("ホイール数値: " , msg->GetData(BFM_INPUT_VALUE));
}



//ダイアログ ---------------------------------------------
class testDialog:GeModalDialog
{
  public:
    var u_area;    //ユーザエリア変数

    testDialog();  //コンストラクタ
    CreateLayout();//ダイアログレイアウト
}

//コンストラクタ
testDialog::testDialog()
{
  super();
}

//ダイアログレイアウト
testDialog::CreateLayout()
{
  SetTitle("testDialog");

  AddUserArea(1000 , 0 , 500 , 400);
  u_area = new(testUserArea , 1000 , this);

  AddDlgGroup(DR_DLGGROUP_OK|DR_DLGGROUP_CANCEL);
}



//メイン ------------------------------------------------
main(doc , op)
{
  bm = new(BaseBitmap , 100 , 100);
  bm->SetPen(vector(1.0 , 0.0 , 0.0));
  bm->DrawRect(0 , 0 , 99 , 99);
  bm->SetPen(vector(1.0 , 1.0 , 0.0));
  bm->DrawRect(10 , 10 , 89 , 89);

  var dlg = new(testDialog);
  dlg->Open(-1 , -1);
}

|

« C4D ワイドレンズやFishEyeのようにレンズディストーション… | トップページ | C4D ダイアログのユーザエリアの定期的な割り込み処理… »