MFC Visual C++.NET WindowXPで開発しています
CListCtrlから派生したクラスを作っています。
ですが、あるタイミングで親ウインドウに自作メッセージを送りたいんです
親ウインドウで WM_NOTIFY で処理すると思っていますけど、
でもうまくいってないんです。どうすればいいのでしょうか?
よろしくおねがいします
親子関係はともかくとして、派生クラスから別な派生クラスを操作するなら、
http://homepage3.nifty.com/mitui707/VisualC/VCotherclassoperate.html/
というのがありました。
SDIで、ダイアログ→ダイアログとなっていますが、要は派生クラス → 派生クラスです。
はずしていたら、ごめんなさい。
ユーザー定義のメッセージを送る場合は
SendMessageでWM_USER以降のメッセージを
送るのが簡単だし一般的ではないでしょうか。
(ユーザー定義のイベントのようなものを作りたいということなら
スマートではないかもしれませんが)
WM_NOTIFYで送ることもできないわけではないですが
自作コントロールでもないですし勝手に通知コードを
定義しても大丈夫かというとわかりません。
WM_USERに関して補足
送り先がコモンコントロール等の場合には既存のメッセージと被る可能性があるので、WM_APP以降にすべきです。
WM_USER+nを使うのはプライベートなウインドウのみにしておきましょう。
(WM_USER+nなメッセージがいろいろ存在していますので)
MSDNより抜粋
WM_USER through 0x7FFF Integer messages for use by private window classes.
WM_APP through 0xBFFF Messages available for use by applications.
>送り先がコモンコントロール等の場合には既存のメッセージと被る可能性があるので、WM_APP以降にすべきです。
たしかに親ウインドウがコントロールでないということが
この質問からはわかりませんね。。。
同様の理由から「CListCtrlから派生したクラス」というものに再利用性を求めるなら
これらの方法はオススメではありません。
この前は問題をはっきりにしていなくて申し訳ないんですが…
実は…
CEdit コントロールは テキストが変更されたら
EN_CHANGEメッセージが自動的に送られて、
必要によって、親ウインドウにON_EN_CHANGEメッセージを捕まえて
処理することができます.
僕が今作ってるクラスは CListCtrlクラス から 派生して、
あるタイミングでCEditなどのコントロールのように、
親ウインドウにメッセージを送って、
親ウインドウがこのメッセージを捕まえて、
それに応じて処理することができるようにしたいんです。
以下は僕のコ−ドですが
#define UM_MYMSGTOPARENT WM_USER+100
class CMyListCtrl:public CListCtrl
{
//......省略
CWnd* m_Parent; //親ウインドウ
afx_msg void OnOneFunction();
};
void CMyListCtrl::OnOneFunction()
{
//ここのm_Parentウインドウが有効なウインドウです
NMHDR nmhdr;
nmhdr.hwndFrom = this->GetSafeHwnd();
nmhdr.idFrom = this->GetDlgCtrlID();
nmhdr.code = UM_MYMSGTOPARENT ;
m_Parent->SendMessage(WM_NOTIFY,(WPARAM)GetDlgCtrlID(),
(LPARAM)&nmhdr);
}
/////////////////////////////////////
そして親ウインドウで
BOOL CParentWnd::OnNotify(WPARAM wParam,LPARAM lParam,LRESULT* lR)
{
if((UINT)wParam == IDC_MYLISTID)
{
// ここで処理
}
}
ちょっと自分で試したんだが
こうしては大丈夫なのかな?もっといい方法があるのかな?
すみません、
ステートメントひとつ忘れちゃった:
return CDialog::OnNotify(wParam,lParam,lR);
>#define UM_MYMSGTOPARENT WM_USER+100
この定義は通知コードとして安全に使えるものでしょうか?
たしかにWM_NOTIFYを送ることはできるでしょうが
問題はどんな通知コードを送るかですね。
おそらくWM_NOTIFYはサブクラス化されたウインドウから
ユーザー定義の通知コードを増やすことを想定してないので、
WM_APPに相当するような定数は用意されてないのかもしれません。
今回の場合は少なくとも
NM_FIRST〜NM_LAST
LVN_FIRST〜LVN_LAST
は避けなければならない感じでしょうか(?)
>ちょっと自分で試したんだが
>こうしては大丈夫なのかな?もっといい方法があるのかな?
単に親ウインドウ側で処理したいと仮定すると
別のアプローチとしては
JAVAのイベントリスナーのような仕組みを用意するとか、
CMyListCtrlのイベントを仮想関数で定義する
(実装はCParentWndのインナークラスにでもする)
とかの方法があると思います。
えっと、やはりちょっとわからないところがあるんだけど、
どうすれば避けるのか分からないんです:
>NM_FIRST〜NM_LAST
>LVN_FIRST〜LVN_LAST
単にこう定義しては済まないんでしょう:
#define UM_MYMSGTOPARENT WM_APP + 1000
昨日のコード は わけも分からなく 正しく 行けました。
>BOOL CParentWnd::OnNotify(WPARAM wParam,LPARAM lParam,LRESULT* lR)
>{
> if((UINT)wParam == IDC_MYLISTID)
> {
> // ここで処理
// ヘッダーにUM_MYMSGTOPARENTが定義されてます。
// このヘッダーもインクルードされています
if( ((NMHDR*)lParam)->code == UM_MYMSGTOPARENT )
{
AfxMessageBox("メッセージが届いた!");
}
> }
> return CDialog::OnNotify(wParam,lParam,lR);
>}
今日も MSDN を探してみたら、こういう作り方はなさそうだ、
ON_NOTIFY_REFLECT が 独自のメッセージ を 親ウインドウに送信できるそうですが、
試してみたら、失敗しました…. メッセージが届いてなかったそうだ。
//////////////////////////////////////////////////////////////////////
>単に親ウインドウ側で処理したいと仮定すると
>別のアプローチとしては
>JAVAのイベントリスナーのような仕組みを用意するとか、
>CMyListCtrlのイベントを仮想関数で定義する
そうですね、この前もいろいろ考えてたんだけど、今作っているクラスは、
CListCtrlの拡張クラスで、通用性が重要なんですが、
CWndクラスに 別の関数を 添加できないから,
インタクラスとかイベントリスナーとかはちょっと無理ですが…
えっと、やはりちょっとわからないところがあるんだけど、
どうすれば避けるのか分からないんです:
>NM_FIRST〜NM_LAST
>LVN_FIRST〜LVN_LAST
単にこう定義しては済まないんでしょう:
#define UM_MYMSGTOPARENT WM_APP + 1000
昨日のコード は わけも分からなく 正しく 行けました。
>BOOL CParentWnd::OnNotify(WPARAM wParam,LPARAM lParam,LRESULT* lR)
>{
> if((UINT)wParam == IDC_MYLISTID)
> {
> // ここで処理
// ヘッダーにUM_MYMSGTOPARENTが定義されてます。
// このヘッダーもインクルードされています
if( ((NMHDR*)lParam)->code == UM_MYMSGTOPARENT )
{
AfxMessageBox("メッセージが届いた!");
}
> }
> return CDialog::OnNotify(wParam,lParam,lR);
>}
今日も MSDN を探してみたら、こういう作り方はなさそうだ、
ON_NOTIFY_REFLECT が 独自のメッセージ を 親ウインドウに送信できるそうですが、
試してみたら、失敗しました…. メッセージが届いてなかったそうだ。
//////////////////////////////////////////////////////////////////////
>単に親ウインドウ側で処理したいと仮定すると
>別のアプローチとしては
>JAVAのイベントリスナーのような仕組みを用意するとか、
>CMyListCtrlのイベントを仮想関数で定義する
そうですね、この前もいろいろ考えてたんだけど、今作っているクラスは、
CListCtrlの拡張クラスで、通用性が重要なんですが、
CWndクラスに 別の関数を 添加できないから,
インタクラスとかイベントリスナーとかはちょっと無理ですが…
>どうすれば避けるのか分からないんです:
>>NM_FIRST〜NM_LAST
>>LVN_FIRST〜LVN_LAST
HDN_FIRST〜HDN_LASTもありましたね。
>単にこう定義しては済まないんでしょう:
> #define UM_MYMSGTOPARENT WM_APP + 1000
この場合のWM_APPはまったく無意味な値としか思えませんが
他の通知コードと重複していなければ正常に動作するのでしょう。
>今日も MSDN を探してみたら、こういう作り方はなさそうだ、
>ON_NOTIFY_REFLECT が 独自のメッセージ を 親ウインドウに送信できるそうですが、
>試してみたら、失敗しました…. メッセージが届いてなかったそうだ。
あまり詳しくないんですが普通はON_NOTIFYじゃないのかな?
subaru さん、
大変ありがとうございますm(_ _)m 、作り方が大体わかりました。
やっぱON_NOTIFYですね。
どうもありがとう。
ツイート | ![]() |