Fl_Gl_Windowでのキーボード・マウス入力†Fl_Gl_Windowの派生クラスによるOpenGL描画にキーボード・マウスイベントを処理する関数を追加する. クラスの宣言†rxFlGLWindowクラスを以下のように変更する. class rxFlGLWindow : public Fl_Gl_Window { // 描画フラグ enum DrawObject { RX_IDD_VERTEX = 0, //!< 頂点描画 RX_IDD_EDGE, //!< エッジ描画 RX_IDD_FACE, //!< 面描画 }; int m_iDraw; //!< 描画フラグ rxTrackball m_tbView; //!< トラックボール public: //! コンストラクタ rxFlGLWindow(int x_, int y_, int w_, int h_, const char* l) : Fl_Gl_Window(x_, y_, w_, h_, l) { m_iDraw = RX_IDD_FACE; resizable(this); // ウィンドウリサイズを可能に end(); } //! デストラクタ virtual ~rxFlGLWindow() { } public: void InitGL(void); void Resize(int w, int h); void Display(void); void Mouse(int button, int state, int x, int y); void Motion(int x, int y); void PassiveMotion(int x, int y); void Keyboard(int key, int x, int y); private: void draw(void) void resize(int x_, int y_, int w_, int h_); int handle(int ev); }; キーボード・マウスなどによるイベントを受け取るために,handle関数をオーバーライドしている. そして,GLUTからの移植性を考えて,Mouse,Motion,PassiveMotion,Keyboard関数を追加している. また,マウスにドラッグによる視点の変更を行うためのトラックボールクラス, rxTrackball m_tbView; キーボードによる描画の変更のためのフラグ enum DrawObject { RX_IDD_VERTEX = 0, //!< 頂点描画 RX_IDD_EDGE, //!< エッジ描画 RX_IDD_FACE, //!< 面描画 }; int m_iDraw; //!< 描画フラグ をメンバ変数として追加した. イベントハンドラ†handle関数では様々なFLTKイベントが発生したときに呼ばれる. イベントの種類は引数evで受け取ることができる. 各イベントの詳細は次節以降参照. OpenGLのためのイベントハンドラの例を以下に示す. //! イベントハンドラ int rxFlGLWindow::handle(int ev) { switch(ev){ case FL_PUSH: // マウスボタンダウン Mouse(Fl::event_button(), 1, Fl::event_x(), Fl::event_y()); break; case FL_RELEASE: // マウスボタンアップ Mouse(Fl::event_button(), 0, Fl::event_x(), Fl::event_y()); break; case FL_DRAG: // マウスドラッグ Motion(Fl::event_x(), Fl::event_y()); break; case FL_MOVE: // マウス移動 PassiveMotion(Fl::event_x(), Fl::event_y()); break; case FL_KEYDOWN: // キーダウン(FL_KEYBOARDでもOK) Keyboard(Fl::event_key(), Fl::event_x(), Fl::event_y()); break; case FL_KEYUP: // キーアップ case FL_SHORTCUT: // グローバルショートカット break; case FL_FOCUS: // ウィンドウフォーカス case FL_UNFOCUS: break; default: return Fl_Window::handle(ev); } return 1; } FLTKは直近のイベントに関する情報を変数に記憶しておく.これらの変数の値を参照するのが, Fl::event_x(), Fl::event_y(), Fl::event_button()や Fl::event_key()などである. これらFl::event_*()関数を使って,様々な値を実際に処理を行う関数に渡している. 各イベントの詳細は以下参照. マウスイベント†
rxFlGLWindowクラスにおいて,これらのイベントを処理する関数の例を以下に示す. //! マウスイベント処理関数 void Mouse(int button, int state, int x, int y) { make_current(); int keymod = (Fl::event_state(FL_SHIFT) ? 2 : (Fl::event_state(FL_CTRL) ? 3 : 1)); if(button == FL_LEFT_MOUSE){ if(state){ m_tbView.Start(x, y, keymod); } else{ m_tbView.Stop(x, y); } } else if(button == FL_MIDDLE_MOUSE){ } else if(button == FL_RIGHT_MOUSE){ } redraw(); } //! モーションイベント処理関数(マウスボタンを押したままドラッグ) void Motion(int x, int y) { make_current(); m_tbView.Motion(x, y); redraw(); } //! モーションイベント処理関数(マウスボタンを押さない移動) void PassiveMotion(int x, int y) { } マウスボタンの状態はFL_*_MOUSEという名前で定義されている. m_tbView.Start()はトラックボールでの回転・平行移動・ズームをスタートする. 第三引数の値が1で回転,2で平行移動(視線に垂直な方向に平行移動),3でズーム(視線方向に平行移動)である. ドラッグ中に呼ばれるMotion関数内で,m_tbView.Motion()により視点回転・移動処理を行い, マウスボタンが放されたら m_tbView.Stop()で処理を終了している. キーボードイベント†
rxFlGLWindowクラスにおいて,これらのイベントを処理する関数の例を以下に示す. //! キーボードイベント処理関数 void Keyboard(int key, int x, int y) { cout << "Keyboard" << endl; make_current(); switch(key){ case FL_Left: m_iDraw = (m_iDraw == RX_IDD_VERTEX ? RX_IDD_FACE : m_iDraw-1); break; case FL_Right: m_iDraw = (m_iDraw == RX_IDD_FACE ? RX_IDD_VERTEX : m_iDraw+1); break; case 'v': m_iDraw = RX_IDD_VERTEX; break; case 'e': m_iDraw = RX_IDD_EDGE; break; case 'f': m_iDraw = RX_IDD_FACE; break; } redraw(); } Keyboard関数では頂点,エッジ,面描画を切り替える. 矢印左右でこれらの描画を順次切り替え, キー"V","E","F"で直接それぞれの描画を設定する. ウィンドウフォーカスイベント†
ウィジットイベント†
クリップボードイベント†
D&Dイベント†FLTKはファイルやテキストのD&Dに対応している. テキストはUFT8エンコードで送られ,ファイルはフルパスのリストとして送られる. これらは上記FL_PASTEイベント後, Fl::event_text()(文字列 - char*),Fl::event_length()(文字列の長さ) を参照することでその情報が得られる.
ソースコード†上記例のソースコードは以下(Viual Studio 2010用プロジェクトファイル含む). 実行結果は以下. |