親ウインドウにメッセージをおくるには

解決


清原  2006-04-21 04:47:32  No: 61279

MFC Visual C++.NET  WindowXPで開発しています

CListCtrlから派生したクラスを作っています。
ですが、あるタイミングで親ウインドウに自作メッセージを送りたいんです

親ウインドウで  WM_NOTIFY  で処理すると思っていますけど、
でもうまくいってないんです。どうすればいいのでしょうか?
よろしくおねがいします


桑田  2006-04-21 14:23:40  No: 61280

親子関係はともかくとして、派生クラスから別な派生クラスを操作するなら、

http://homepage3.nifty.com/mitui707/VisualC/VCotherclassoperate.html/

というのがありました。
SDIで、ダイアログ→ダイアログとなっていますが、要は派生クラス → 派生クラスです。

はずしていたら、ごめんなさい。


subaru  2006-04-22 00:34:39  No: 61281

ユーザー定義のメッセージを送る場合は
SendMessageでWM_USER以降のメッセージを
送るのが簡単だし一般的ではないでしょうか。
(ユーザー定義のイベントのようなものを作りたいということなら
スマートではないかもしれませんが)

WM_NOTIFYで送ることもできないわけではないですが
自作コントロールでもないですし勝手に通知コードを
定義しても大丈夫かというとわかりません。


通りすがり  2006-04-22 04:09:04  No: 61282

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.


subaru  2006-04-22 05:26:02  No: 61283

>送り先がコモンコントロール等の場合には既存のメッセージと被る可能性があるので、WM_APP以降にすべきです。
たしかに親ウインドウがコントロールでないということが
この質問からはわかりませんね。。。
同様の理由から「CListCtrlから派生したクラス」というものに再利用性を求めるなら
これらの方法はオススメではありません。


清原  2006-04-22 08:53:26  No: 61284

この前は問題をはっきりにしていなくて申し訳ないんですが…
実は…

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)
  {
      // ここで処理
  }
}

ちょっと自分で試したんだが
こうしては大丈夫なのかな?もっといい方法があるのかな?


清原  2006-04-22 08:56:08  No: 61285

すみません、

ステートメントひとつ忘れちゃった:
return CDialog::OnNotify(wParam,lParam,lR);


subaru  2006-04-22 21:52:55  No: 61286

>#define UM_MYMSGTOPARENT  WM_USER+100
この定義は通知コードとして安全に使えるものでしょうか?
たしかにWM_NOTIFYを送ることはできるでしょうが
問題はどんな通知コードを送るかですね。
おそらくWM_NOTIFYはサブクラス化されたウインドウから
ユーザー定義の通知コードを増やすことを想定してないので、
WM_APPに相当するような定数は用意されてないのかもしれません。

今回の場合は少なくとも
NM_FIRST〜NM_LAST
LVN_FIRST〜LVN_LAST
は避けなければならない感じでしょうか(?)

>ちょっと自分で試したんだが
>こうしては大丈夫なのかな?もっといい方法があるのかな?
単に親ウインドウ側で処理したいと仮定すると
別のアプローチとしては
JAVAのイベントリスナーのような仕組みを用意するとか、
CMyListCtrlのイベントを仮想関数で定義する
(実装はCParentWndのインナークラスにでもする)
とかの方法があると思います。


清原  2006-04-23 03:06:01  No: 61287

えっと、やはりちょっとわからないところがあるんだけど、

どうすれば避けるのか分からないんです:
>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クラスに  別の関数を  添加できないから,
インタクラスとかイベントリスナーとかはちょっと無理ですが…


清原  2006-04-23 03:06:21  No: 61288

えっと、やはりちょっとわからないところがあるんだけど、

どうすれば避けるのか分からないんです:
>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クラスに  別の関数を  添加できないから,
インタクラスとかイベントリスナーとかはちょっと無理ですが…


subaru  2006-04-24 19:41:33  No: 61289

>どうすれば避けるのか分からないんです:
>>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じゃないのかな?


清原  2006-04-25 04:32:56  No: 61290

subaru さん、
大変ありがとうございますm(_ _)m 、作り方が大体わかりました。
やっぱON_NOTIFYですね。
どうもありがとう。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加