delegate5
前回delegate4 - while( c++ );の続き。
以下のようなプログラムでフォームに対してボタンを配置することが出来る様になりました。
class HogeForm : public Form { private: ButtonPtr button1; ButtonPtr button2; public: HogeForm() : Form() , button1( new Button() ) , button2( new Button() ) { InitializeComponent(); } private: void InitializeComponent() { // // button1 // button1->text = "button1"; button1->x = 50; button1->y = 50; button1->w = 100; button1->h = 50; button1->click += xtl::bind ( &HogeForm::Button1_Clicked //メンバ関数 , this //呼び出し元 , xtl::_1, xtl::_2 //プレースホルダ(呼び出し時にイベントの発生源が渡される), プレースホルダ(呼び出し時にイベントが渡される) ); // // button2 // button2->text = "button2"; button2->x = 150; button2->y = 50; button2->w = 100; button2->h = 50; button2->click += xtl::bind ( &HogeForm::Button2_Clicked //メンバ関数 , this //呼び出し元 , xtl::_1, xtl::_2 //プレースホルダ(呼び出し時にイベントの発生源が渡される), プレースホルダ(呼び出し時にイベントが渡される) ); // // HogeForm // this->text = "hoge"; this->x = CW_USEDEFAULT; this->y = CW_USEDEFAULT; this->w = 400; this->h = 300; this->load += xtl::bind ( &HogeForm::WindowLoad //メンバ関数 , this //呼び出し元 , xtl::_1, xtl::_2 //プレースホルダ(呼び出し時にイベントの発生源が渡される), プレースホルダ(呼び出し時にイベントが渡される) ); this->closing += xtl::bind ( &HogeForm::WindowClosing //メンバ関数 , this //呼び出し元 , xtl::_1, xtl::_2 //プレースホルダ(呼び出し時にイベントの発生源が渡される), プレースホルダ(呼び出し時にイベントが渡される) ); this->AddControl( button1 ); this->AddControl( button2 ); } private: //windowが初めて表示される直前に実行される void WindowLoad( Component* /*sender*/, WindowEvent& /*e*/ ) { std::cout << "load" << std::endl; } //windowが閉じられる直前に実行される void WindowClosing( Component* /*sender*/, WindowEvent& /*e*/ ) { //プログラム終了 system.Exit( 0 ); std::cout << "closing" << std::endl; } //ボタン1押下時 void Button1_Clicked( Component* /*sender*/, ActionEvent& /*e*/ ) { std::cout << "button1" << std::endl; } //ボタン2押下時 void Button2_Clicked( Component* /*sender*/, ActionEvent& /*e*/ ) { std::cout << "button2" << std::endl; } }; int main() { system.Run( FormPtr( new HogeForm() ) ); return 0; }
実行結果
正直、見た目がしょぼいですね。。。vistaでこのボタンは無いですよね?
Win32APIを使って、.NET Frameworkのような見た目のアプリケーションは作れないんでしょうか?
とりあえずそれは置いておいて、他のコンポーネントも追加して行きましょう。
次はメニューを作りましょうか。ボタンと同様に扱えますし。
メニュー
VC++付属のspy++を使って、C#のボタンやメニューのメッセージを調べてみました。
が、なぜかフリーズする。。。
Formのメッセージを見ているだけなんですが。
とりあえずわかったこと。
- C#ではWM_COMMANDを使っていない。
Win32APIでは通常、WM_COMMANDメッセージでボタンやメニューアイテムのIDを取得し、対応する処理を行うのですが、上記のサンプルプログラムではIDを使っていません。IDと同時に取得できるボタンのウィンドウハンドルを使ってComponentを検索し、登録されたイベントハンドラを実行しています。
しかし、メニューでは選択されたメニューアイテムのウィンドウハンドルを取得することは出来ず、IDで識別する必要があります。
今回の目的はあくまでも「delegateを使ってメニュー処理を行う」事なので、IDは使いたくないのです。でも、Win32APIではIDで識別するしかない。
さて、どうしましょうか。。。?
C#はどのように実装しているのでしょうか?