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#はどのように実装しているのでしょうか?