none
C++Builder5からVC++2005/CLIへの移植で RRS feed

  • 質問

  • 何時もお世話になっております。

    現在、C++Builder5のプログラムをVC++2005/CLIへの移植作業を行っております。

    VC++2005/CLIは、初体験です。

    まず、ブルダーでは以下の事が実現できます。

     

    (Dio.cpp)

    void  Init ( void )

    {

       hWnd =AllocateHWnd(WndProc);
       if(hWnd == NULL) {
          SetErr(ERR_SYSRESOURCE);
          return;
       }

    }

     

    void __fastcall TDioInt::WndProc(TMessage& msg)
    {
     WORD ChNo;

     if(WM_DIOINT_CH0 <= msg.Msg && WM_DIOINT_CH3 >= msg.Msg) {
      ChNo = msg.Msg - WM_DIOINT_CH0;
      if(EventRes[ChNo].FOnIntProc) EventRes[ChNo].FOnIntProc(this, ChNo);
      if(EventRes[ChNo].hEvent) PulseEvent(EventRes[ChNo].hEvent);
     }
     return;
    }


    AllocateHwnd
    AllocateHWnd 関数は,指定されたウィンドウプロシージャを実装するウィンドウを作成します。
    説明

    AllocateHWnd 関数を呼び出すと,ウィンドウコントロールと関連付けられていないウィンドウを作成できます。通常,このメソッドは,メッセージには応答するが,ユーザーインターフェースに表示されない非ビジュアルウィンドウを作成するために使われます。たとえば,TTimer コンポーネントは,このメソッドを使って Windows からのタイマーメッセージに応答するウィンドウを作成します。
    Method パラメータは,生成されたウィンドウがメッセージに応答するために使うウィンドウプロシージャを指定します。
    AllocateHWnd は,新しく作成されたウィンドウのハンドルを返します。

     

    これと同様の事をVC++でも実現可能でしょうか?

    宜しくお願い致します。

     

    2007年11月16日 4:36

回答

すべての返信

  • いわゆる Window を作成する際に,

    ウィンドウプロシージャ と呼ばれる 関数(のエントリポイントを) を登録します。

    その関数は,いわゆるふつうの関数です。

     

    で,一方,クラスのメソッドというのは,

    クラスがインスタンス化されたときのそのインスタンスへの参照を
    いわゆる暗黙の引数である this で受け取ることができます。

     

    で,クラスのインスタンスを受け取れると,

    そのインスタンスに対して,そのメソッド内で,操作ができるわけです。

    ふつうの関数に比べて結構便利なわけです。

    特に,Windowをラップしたようなクラスを作る場合は都合がいいわけです。

     

    だけど,ふつうに Window を作成する場合は,

    ウィンドウプロシージャとして登録できるのは,

    ふつうの関数しか登録できません。

     

    で,いろんな工夫があるわけで,

    Visual C++ が提供している ATL と呼ばれているものにも

    Windowを同じようにラップしたクラスがあるんですが,

    サンク (thunk)と呼ばれるカラクリで解決しています。

    (詳しくは,ATL Internals 2nd Edition に出ています)

     

    で,C++ Builder での Window のラップクラスであると思われる

    VCLでは,その上記の AllocateHWnd() (実際は MakeObjectInstance() ) で,

    継承したクラス内のメソッドを

    ウィンドウプロシージャに登録するカラクリを入れてあるんでしょう。

     

    で,
    .NET の いわゆる WinForm の場合は,

    Form を継承したクラス( Form1 等) の

    WndProcメソッドを単にオーバーライドすればOKです。

     

    追記: ネイティブなら ATL の CWindow を使うのが近い感じでしょう。

    単に同期を取るためだけにウィンドウメッセージを使うなら,

    ふつうの関数を使って,非可視のWindowを作る感じです。

    2007年11月20日 2:21
  • 想像ですが,上記のコードは,

    Windowを持たない VCLコンポーネント内でのコードなんでしょう。

    TForm の派生クラスではないですよね?

    Windowを持たないとメッセージを受け取れないので,

    それで上記のような AllocateHWnd() を入れてあるんだと思います。

     

    で,そういうなんらかのVCLコンポーネント(その派生クラス)を利用している場合は,

    C++ Builder 側の その VCL コンポーネントのところのソースコード

    (C++ でなく Object Pascal で書かれているソースも含めて)を

    ちゃんと理解しないと移植はできないんじゃないかと思います。

     

     

     

     

    2007年11月20日 3:05
  • ご指摘有難う御座います。

    色々と試行錯誤してみます。

    2007年11月30日 3:36