VC2008 MFCです。
自作のウィンドウクラスで、ユーザ操作などで内部の状態が変わったことを
独自のメッセージで親に通知する場合、メッセージの送り先は
GetParentとGetOwner、どちらにするのが正しい概念なのですか?
なにも設定しない限りはGetParentもGetOwnerも同じなのは理解していますが、
MFCのソースやネット上のソースなどを見ても、両者が混在しているようなので、
明確な区別の仕方があるのかなと疑問に思っています。
よろしくお願いいたします。
VSのエディションによってはできないかもしれないが・・
GetOwnerに対し、右クリックメニュー>「定義へ移動」
をすると、GetOwnerの内容が見れる
1行しかないので、自分でみたほうが面白いしわかりやすい
Win32SDKにはGetOwner()という関数は存在しません。
本質的には「親ウインドウ」しか無いと言えます。
一般にWS_CHILDスタイルを持つウインドウを作成するとき
CreateWindow()の第8引数hWndParentに指定したものが「親ウインドウ」。
WS_POPUP又は無視定で、hWndParentにデスクトップウインドウ
を指定した場合がWin32SDKでの「オーナーウインドウ」とされています。
ところがMFCではCWnd::m_hWndOwnerメンバが存在しており、
CWnd::SetOwner()で自由に設定できるようになっています。
CWnd::GetOwner()はこれか、又はGetParent()の結果を戻します。
これは、ツールバー等、複数階層の親子関係をバイパスして、
メッセージを送信するための仕組みとして利用されています。
以上を勘案すると
1.GetOwner()を使用する場面とは、
CWnd::SetOwner()で設定した「オーナー」に中間の親子関係を
たどらずにWM_COMMAND(等)の送信先として利用する場合にのみ使用する。
2.上記以外はGetParent()を使用する
のように、自分は考えています。
あぁっまちがったorz。
>WS_POPUP又は無視定で、hWndParentにデスクトップウインドウ
>を指定した場合がWin32SDKでの「オーナーウインドウ」とされています。
を
>WS_POPUP又は無視定で、hWndParentにしていたものが
>Win32SDKでの「オーナーウインドウ」とされています。
に訂正します。
> 独自のメッセージで親に通知する場合、メッセージの送り先は
> GetParentとGetOwner、どちらにするのが正しい概念なのですか?
親というならGetParent()の気がする。
なぜなら、
他の人も書かれているようにGetOwner()はSetOwner()された場合は
どんなウィンドウを返すか分からないから。
いわゆる親に通知したいのなら、GetParent()
いわゆる親以外に通知したいのなら、SetOwner()した上でGetOwner()
じゃないかな?
自信なし。
GetOwnerのヘルプにかいてあります。
ここから
> ウィンドウがオーナーを持っていないときは、既定で返される
> 親ウィンドウ オブジェクトへのポインタを取得します。
> オーナー ウィンドウと所有されているウィンドウ間の関係は
> いくつかの重要な点で親と子の関係とは異なっていることに注意してください。
> たとえば、親を持つウィンドウは、親ウィンドウのクライアント領域内
> に収められます。
> 所有されているウィンドウは、デスクトップの任意の位置に描画できます。
ここまで
ついでながら、ややこしいこと
・オーナーウィンドウ付きのWS_OVERLAPPEDでは、GetParentはゼロを返す。
・コンボボックスのドロップダウンリストはデスクトップの子(WS_CHILD)。
::GetParent
CWnd::GetParent
CWnd::GetOwner
CWnd::GetParentOwner
ほかにも、
AfxGetMainWndや、フレーム・ビューつかってるときのGetParentFrameもありますな
「どれを使うのが正しいの?」という話になる以前に、
「どういうウィンドウの関係になっていて、
どいつを「親」としてどっから呼びたいの?」
ということが必要になってくるかと
みなさんありがとうございます。
こちらの都合で返信が遅れてしまいました。申し訳ありません。
> 「どれを使うのが正しいの?」という話になる以前に、
> 「どういうウィンドウの関係になっていて、
> どいつを「親」としてどっから呼びたいの?」
> ということが必要になってくるかと
作っているのは、ボタンやエディットボックスのような
「任意のウィンドウやダイアログに置いて使う」ものなので、
どれが親になったりどういう関係になったりするのかは
使う側の事情で変わってくるという状態です。
となると、bunさんの言われるように、こういうものは親ではなく
オーナに送っておいたほうがよいのかなと解釈しました。
「クリックされたよ」とか「位置が変わったよ」などのメッセージなので、
常に親に送るべきものというわけではないですよね。
使う側が意図的にSetOwner()したときにも対応できますし、
していない場合には自動で親に送られるようですし。
勘違いしている点がありましたら指摘していただけると嬉しいです。
ありがとうございます。
>「クリックされたよ」とか「位置が変わったよ」などのメッセージなので、
「位置が変わったよ」はオーナーに送ってもオーナーは
どうしようもないと思います(vv;)。
1.ユーザー操作が最終的にコマンド相当処理になる場合は、
オーナー(又は親)に送る。
2.位置が変わったなど、兄弟に影響のある状態変更は
自分を含む兄弟の位置を直接操作できるもの(つまり親)
に送る。
べきではないでしょうか?。そもそもSetOwner()するケースとは、
・君の直接の上司(親)じゃないけど、特命的イベントが発生したら
窓口の重役(オーナー)に直接知らせてくださいね。席替などは
いままで通り上司(親)に処理してもらってね。
みたいな事ではないでしょうか。
> 「位置が変わったよ」はオーナーに送ってもオーナーは
> どうしようもないと思います(vv;)。
すみません、位置というのはウィンドウ自身の座標ではなく、
リストやツリーなどで言う「選択位置」です。
この場合も親ではなくオーナのほうが適してますよね?
亀山さんが作っているのものが
>作っているのは、ボタンやエディットボックスのような
>「任意のウィンドウやダイアログに置いて使う」ものなので、
ということぐらいしかわからないので
詳細によっては変わりますが、
一般的なダイアログコントロールの類として話すならば・・・
>リストやツリーなどで言う「選択位置」です。
>この場合も親ではなくオーナのほうが適してますよね?
これは、否。
VC++のクラスビューペインは、「クラスをシングルクリックで選択」したら、
まず、クラスビューの下に選択したクラスに属する関数・変数名がでるし
プロパティペインは、上部のボタンによって、
「プロパティペインで表示している内容」を変更している
同じ親に属する別の子ウィンドウに変更をかける場合もありうるなら
オーナーに飛ばすより、親でうけるほうが妥当。
いったんオーナー(VC++本体)を通してから、
クラスビューペインに更新命令を出してるのかもしれないが・・・
ryoさん、ご意見ありがとうございます。
> いったんオーナー(VC++本体)を通してから、
> クラスビューペインに更新命令を出してるのかもしれないが・・・
クラスの情報を知っているのはIntelliSenseでしょうし、
IntelliSenseの情報を持っているのはVC++本体ですよね。
また、クラスビューペインのツリーの選択位置によって
プロパティウィンドウペインなどの情報も連動して変わるので、
自分もryoさんの言われているように、「いったんオーナーを通してから…」
のほうが流れ的にはしっくり来るかなと思いますが、
この手のものは様々な手法があって、作るたびに考え直してしまいます。
ありがとうございます。
> 自分もryoさんの言われているように、「いったんオーナーを通してから…」
> のほうが流れ的にはしっくり来るかなと思いますが、
> この手のものは様々な手法があって、作るたびに考え直してしまいます。
case by case ですね。
今回の、
>「いったんオーナーを通してから…」
は、ryoさんの意見を読むと、
一旦元に戻って体制を整える。
(大げさに書いてます。)
だと思います。
親にも戻ってくると思いますが。。。。。
オーナーだとわかっている時を除いて、まず親ウインドウでいいと思います。
自身のウインドウ全体のハンドルとか、デスクトップのウインドウのハンドルを取得
するとか特別の処理以外は親でいいと思います。