ウィンドウを継承するには?

解決


ワンモセッ  2007-09-27 18:45:57  No: 66462  IP: 192.*.*.*

他掲示板(2ch)で質問したのですが、かまってもらえなかったのでここへ来て
しまいました。
VC6のSDKでウィンドウを持ったクラスの継承がしたいです。 
Hoge1クラス:メインウィンドウになるクラス 
Hoge2クラス:継承元となるウィンドウを持ったクラス 
Hoge3クラス:Hoge2クラスを継承したクラスでHoge1ウィンドウのボタンを押したときに表示されるウィンドウを持ったクラス 

Hoge2クラスはWinProcをstaticでクラス内に入れています。クラスの登録やウィンドウを生成する関数はprivateとして存在します。 
Hoge3クラスも同じような構成です。 
で、Hoge3クラスで不用なメッセージ処理はHoge2のウィンドウクラスに回してやりたいのですが、 
その方法がいまいちわかりません。手順・・がいまいちです。 
Hoge3クラスの登録をする前に、Hoge2クラスのウィンドウを登録する必要があると思い、 
WNDCLASSEXを使ってウィンドウの登録をする?と思いきや、横取りするHoge2にあるプロシージャとかも指定しないといけないわけですよね? 
でもこの段階だと、Hoge2クラスの存在すら誰も知らないわけで・・・この辺りがよくわかりません。 
ボタンのスーパークラス化と同じようなイメージでいるのですが、ボタンの場合は 
ウィンドウズが予めその存在を認識しているからGetClassInfoExを使って情報を取得する 
ことができますが、自作ウィンドウクラスの場合はそれができなくて・・・

編集 削除
通りすがり  2007-09-27 20:22:48  No: 66463  IP: 192.*.*.*

DefWindowProcではなくてCallWindowProcでもとのウィンドウプロシージャにメッセージを流せばいいのでは?

編集 削除
ワンモセッ  2007-09-27 21:32:00  No: 66464  IP: 192.*.*.*

>>通りすがりさん
class Hoge3 : public Hoge2
とした場合、
Hoge2のプロシージャはDefWindowProcで、Hoge3はCallWindowProcというのはわかります。
だとすると、CallWindowProcの一番目の引数に指定する、メッセージを送り返すWinProcのアドレスはどのように取得するのでしょうか?
GetClassInfoExを使ってHoge2のWinProcを取得しようとしたのですが、
「そんなクラスはねぇー!」と怒られました。
Hoge3クラスは生成して、ウィンドウはありますが、Hoge2は継承されているだけでウィンドウの登録をしていません(怒られた理由なんですが・・)。

編集 削除
wclrp ( 'o')  2007-09-28 00:38:05  No: 66465  IP: 192.*.*.*

>Hoge3クラスで不用なメッセージ処理はHoge2のウィンドウクラスに回してやりたい

これが俺のイメージと違うな。

Hoge2クラスのウィンドウを作成しないのならば
Hoge2クラスのウィンドウクラスはいらない。
Hoge3クラスが欲しいのはウィンドウプロシージャなんだから。

class Hoge2 : public Hoge1
{
  int WinProc(msg,...) { ... }
};

class Hoge3 : public Hoge2
{
  int WinProc(msg,...)
  {
    switch(msg) {
    case WM_〜
      〜
      return 1;
    } 
    return Hoge2::WinProc(msg,...);
  }
};

Hoge2クラスのウィンドウをウィンドウクラス経由で作成したいなら
Hoge2クラスのウィンドウクラスが必要だろうけど
MFCは確かウィンドウプロシージャ1つを使いまわしている。
ウィンドウクラスもC++クラスと対に存在するわけじゃない。

HWNDからCWndインスタンスを探すマップを用いている。
話が長くなるのでここまで。

編集 削除
wclrp ( 'o')  2007-09-28 00:50:19  No: 66466  IP: 192.*.*.*

ウィンドウクラスに登録するのは
Hoge2でもHoge3でもHoge1::DefWinProcとする。

class Hoge1
{
  static ... DefWinProc ...;
  virtual  int WinProc(msg,...) = 0;
};

以下は正しいか知らん。適当に想像して書いてる。

std::map<HWND,Hoge1*> g_WndManager;

Hoge3::CreateWindo(...)
{
  hwnd = ::CreateWindow(...が成功したら
  g_WndManagerにhwnd,thisを追加する。
  厳密にはMFCは違う方法でやっている。
}

Hoge1::DefWinProc(HWND hwnd, wparam, lparam)
{
  g_WndManagerからhwndを探し、Hoge1*を得る。
  return pHoge1->WinProc...
}

ただしこの方法では
WM_CREATEなど::CreateWindowが終わる前に来るメッセージのとき
まだg_WndManagerに登録されていないからpHoge1->WinProcが呼べない。

MFCではフックとか使って何とかやっているらしいが俺はしらん。

編集 削除
wclrp ( 'o')  2007-09-28 00:57:17  No: 66467  IP: 192.*.*.*

質問を見ると
Hoge1はメインウィンドウであって
class Hoge2 : public Hoge1;の関係ではなくまったく別の話なのか。

class Hoge2 : public Hoge1;って書いてしまった。

Hoge1はBaseWindowと読み直してくれ。

説明の補足
staticじゃないとウィンドウプロシージャに出来ないけど
staticだとstaticではないメンバ変数やメンバ関数にアクセスできないから
g_WndManagerやvirtual BaseWindow::WinProcが必要になるんだよ。

編集 削除
ワンモセッ  2007-09-28 01:45:36  No: 66468  IP: 192.*.*.*

>>wclrp ( 'o') さん
いろいろありがとうございます。マップって、わかると便利そうですね・・。既に”staticだとstaticではないメンバ変数やメンバ関数にアクセスできない”これも、どうにかならないのかな?と思っていました。
が、ちょっと話を戻します。
Hoge1は、メインウィンドウなので、既に表示されてるとして
class Hoge1
{
   Hoge3 hoge3;
   hoge3.InitInstance(hInstance); //hoge3ウィンドウ表示
}

//ウィンドウクラス(ボタンが1つ配置されてる)
class Hoge2
{
  int WinProc(msg,...) { ... }
};

//ウィンドウクラス(追加でボタンとテキストボックスを配置する)
class Hoge3 : public Hoge2
{
  int WinProc(msg,...)
  {
    switch(msg) {
    case WM_〜
      〜
      return 1;
    } 
    return CallWinProc(msg,...);
  }
};

要は、Hoge2は変更せずに、追加になった機能をHoge2を継承したHoge3に
実装して、追加機能ぶんのプロシージャはHoge3で処理して、それ以外は
Hoge2にまわしてやって、Hoge2の処理が終わったらDefWinProc・・
みたいなイメージなのですが・・・。
ボタンをスーパークラス化したときのイメージなのですが・・・。

編集 削除
ワンモセッ  2007-09-28 13:36:14  No: 66469  IP: 192.*.*.*

他掲示板(2ch)で解決できました。
ttp://72.14.209.104/search?q=cache:techtips.belution.com/ja/vc/0009/
をベースにウィンドウを作成することにしました。
使い方というか、1つ1つの文章の意味を理解するために以下のサイトを
参考にしました。
ttp://nomina.petit-archives.mydns.jp/tests/old/gecko012/nmnConsoleControl.cpp
ttp://www7a.biglobe.ne.jp/~lshen/EternalWindows/WinBase/Window/Window08.html

編集 削除