小弟正在开发一个供自己使用的辅助工具,是基于对话框的。上面使用了两个控件,一个是自己写的浏览二进制数据的控件,一个是继承了CTreeCtrl的一个树控件(内部想加一些自己的处理函数)。
现在想要解决的问题是:
1.想在两个控件之间互相发送消息给对方,对方收到消息后进行处理。但是我用自定义消息做了之后发现都无法接受到对方发送的消息。
2.我现在采取了折衷的方案,就是两个控件都给父窗口Dialog发消息,然后由dialog调用另一个控件的对象来做响应。
这两种设计我都采用的同样的方法来定义自定义消息,但是第一种不成功,第二种可以实现,但是第二种似乎封装性没有第一种好,所以还是想实现第一种方案,请教各位高手给予指点!!!小弟不胜感激!在此先谢过了!

解决方案 »

  1.   

    你传消息的时候,两个控件之间都要能相互获得对方的句柄,而句柄的获得也一般就通过主窗口来获得,所以你的第一种方法比第二种方法也不会好多少。
    要想获得更好的效果,建议采用WTL写成COM组件
      

  2.   

    需要么?直接在你的dlg里面处理各个控件的联动就ok了,干吗这么麻烦。
      

  3.   

    恩,感谢楼上几位的指教!当初设计的时候没有考虑周全,现在也准备重新设计下。但是在实现的时候碰到了这个问题一直没有解决啊,希望高手帮忙指点一二啊!
    下面是实现中的部分代码:
    // 定义消息
    #define WM_NOTIFYDATAPOSITION WM_USER+100(CStructTree继承CTreeCtrl)
    类CStructTree的.h文件
    //{{AFX_MSG(CStructTree)
    afx_msg LRESULT OnNotifyDataPos(WPARAM wParam,LPARAM lParam);
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()类CStructTree的.cpp文件
    BEGIN_MESSAGE_MAP(CStructTree, CTreeCtrl)
    //{{AFX_MSG_MAP(CStructTree)
    ON_MESSAGE(WM_NOTIFYTREEPOSITION, OnNotifyDataPos)
    //}}AFX_MSG_MAP
    END_MESSAGE_MAP()
    LRESULT CStructTree::OnNotifyDataPos(WPARAM wParam,LPARAM lParam)
    {
    ....
    }
    父窗口Dlg的.cpp文件,CSuperEditControl是自己写的一个类,m_ptSuperEdit取控件对应的类对象,在OnInitDialog里面把树控件的句柄传给
    BOOL CMemoryReaderDlg::OnInitDialog() 
    {
    CDialog::OnInitDialog();  m_ptSuperEdit= (CSuperEditControl *)GetDlgItem(IDC_MEMORY_SUPEREDIT);
    m_ptTreeCtrl = (CStructTree *)GetDlgItem(IDC_STRUCT_TREE); // 将树控件的句柄传给自己写的控件m_ptSuperEdit
      if(m_ptSuperEdit != NULL && m_ptTreeCtrl != NULL)
      m_ptSuperEdit->SetMsgDestHand(m_ptTreeCtrl->m_hWnd);

    return TRUE; 
    }自定义控件的.cpp文件,响应左键起来的消息,m_hTreeCtrlWnd保存传进来的树控件的句柄
    void CSuperEditControl::OnLButtonUp(UINT nFlags, CPoint point) 
    {
    ....
    ::PostMessage(m_hTreeCtrlWnd,WM_NOTIFYDATAPOSITION,m_posStart,m_posEnd);
    }
    不知道实现方法对不对啊,我用这种方法向Dialog发消息是可以的,但是放到自己继承CTreeCtrl的类里就不行了,请大家指教问题所在!先谢过了!
      

  4.   

    真看不出问题...
    有几个地方可以考察一下.
    一是在PostMessage前::IsWindow(m_hTreeCtrlWnd),
    二是看PostMessageBox的值是否为TRUE
      

  5.   

    你在自己写的类的pretranslatemessage里面看看是否收到了消息
      

  6.   

    TO jasonshark:
    1.我之前也左过对::IsWindow(m_hTreeCtrlWnd)的检查了,返回是1。
    2.不好意思啊,你说的第二步我没看明白,我猜测是不是说::PostMessage()的返回值呢?我查了下,PostMessage不用等消息响应函数处理就返回了,而用SendMessage需要等消息响应函数处理后才返回是吧?我用PostMessage发消息返回为1,而用SendMessage发消息返回为0。To tomcat_jb:
    不知道我理解的对不对啊,我用自己写的控件发消息后,要提交到它的pretranslatemessage这个函数来转发消息是吧!只要消息发送出去了,在pretranslatemessage函数里面就能收到该消息吧!
    我的做法:我在里面判断ptMsg->message == 自定义消息宏,但是好像没有收到这个消息啊!感谢楼上大家的指教,但是问题还是没有解决啊,请问还可能是什么方面的问题啊!希望大家能帮帮小弟,再次谢谢啦!
      

  7.   

    没错是你说的意思,现在关键是你的消息没有传递到类中,我看了半天没什么问题的地方,下面这个地方你试试。BEGIN_MESSAGE_MAP(CStructTree, CTreeCtrl)
    //{{AFX_MSG_MAP(CStructTree)
    ON_MESSAGE(WM_NOTIFYTREEPOSITION, OnNotifyDataPos)
    //}}AFX_MSG_MAP
    END_MESSAGE_MAP()改为BEGIN_MESSAGE_MAP(CStructTree, CTreeCtrl)
    //{{AFX_MSG_MAP(CStructTree)
    //}}AFX_MSG_MAP
    ON_MESSAGE(WM_NOTIFYTREEPOSITION, OnNotifyDataPos)
    END_MESSAGE_MAP()
      

  8.   

    TO tomcat_jb:
    1.我按照你的方法改动了一下,拿到了//}}AFX_MSG_MAP外面.
    2.现在我采用了这样的方法,我在三个类的pretranslatemessage函数中都添加了对是否接受到WM_NOTIFYTREEPOSITION消息的判断,分别弹出提示框
    类CSuperEditControl中:
    BOOL CSuperEditControl::PreTranslateMessage( MSG* pMsg )
    {
    if(pMsg->message == WM_NOTIFYTREEPOSITION)
    {
    AfxMessageBox("Edit Ctrl Get Msg OK");
    }
             // CSuperEditControl这个类是继承CWnd写的一个类
    return(CWnd::PreTranslateMessage(pMsg));
    }父窗口Dlg中:
    BOOL CMemoryReaderDlg::PreTranslateMessage(MSG* pMsg) 
    {
    if(pMsg->message == WM_NOTIFYTREEPOSITION)
    {
    AfxMessageBox("Dlg Get Msg OK");
    }
    return CDialog::PreTranslateMessage(pMsg);
    }继承的树控件中:
    BOOL CStructTree::PreTranslateMessage(MSG* pMsg) 
    {
    if(pMsg->message == WM_NOTIFYTREEPOSITION)
    {
    AfxMessageBox("Tree Get Msg OK");
    }

    return CTreeCtrl::PreTranslateMessage(pMsg);
    }3.然后在自定义的控件中发消息
    void CSuperEditControl::OnLButtonUp(UINT nFlags, CPoint point) 
    {
      CWnd::OnLButtonUp(nFlags, point);
      BOOL flg = ::IsWindow(m_hTreeCtrlWnd);           // 判断是成功的
      flg = ::PostMessage(m_hTreeCtrlWnd,WM_NOTIFYTREEPOSITION,m_SelEnd,m_SelEnd);
    //flg = ::SendMessage(m_hTreeCtrlWnd,WM_NOTIFYTREEPOSITION,m_SelEnd,m_SelEnd);
    ....
    }结果是我在发消息的地方用PostMessage,返回1。结果只弹出Dlg中收到消息的box,在自定义控件和树控件中都不弹出MessageBox。
    若我用SendMessage发消息,返回0。但是没有一个类弹出MessageBox表示接受到消息。
    请问这应该怎么处理呢?
    十分感谢tomcat_jb耐心的帮助和指导,同时也恳请各位高手不吝赐教啊,帮帮小弟!小弟感谢了!
      

  9.   

    我实验过了你的控制变量设置的有问题,不能用
    m_ptSuperEdit= (CSuperEditControl *)GetDlgItem(IDC_MEMORY_SUPEREDIT);
    m_ptTreeCtrl = (CStructTree *)GetDlgItem(IDC_STRUCT_TREE);直接在类向导里面定义控件的控制变量,类型选择为你自定义的类
    Dlg::OnInitDialog()里面改为
    if(::IsWindow(m_myTree.m_hWnd))
    m_myEdit.SetMsgDestHand(m_myTree.m_hWnd);
    其中
    CmyEdit m_myEdit;
    CmyTree m_myTree;
    这样就OK了.
      

  10.   

    TO tomcat_jb:
    “我实验过了你的控制变量设置的有问题,不能用”
    m_ptSuperEdit= (CSuperEditControl *)GetDlgItem(IDC_MEMORY_SUPEREDIT);
    m_ptTreeCtrl = (CStructTree *)GetDlgItem(IDC_STRUCT_TREE);1.请问上面的操作不能取到控制变量吗?我以前也这么取过控制指针的啊,好像和在类向导中定义没有太大区别吧(个人感觉!不知道对否?)!但是我后面的其他操作都是用这两个指针完成的,没有问题啊。2.我实验了下你提供的方法,我在类向导里面可以找到其他的控件,但是找不到我用的那个编辑控件。所以没有办法用类向导生成变量啊!这是什么问题啊?最后我怀疑是不是和控件有关,因为正常情况似乎能够在类向导中看到控件ID的,但是我的工程里看不到那个自定义的控件ID啊。(因为控件不是我写的,是别人写的,他只是告诉我怎么用,我还没完全搞清楚啊!汗...)我下去在研究研究,虽然问题还是没有完全搞清楚,但是仍然感谢你啊!呵呵,还有jasonshark的一直关注!谢谢各位指教!稍后节贴送分啊!十分感谢!
      

  11.   

    1、那样的方法应该也可以控制,但是你肯定缺了一些东西,我也不太熟悉你那种控制方法,但是至少应该NEW出来控制变量吧,光声明指针应该不够。2、类向导有可能出不来,你可以声明一个基类的控制变量,然后手动将基类的类名换成你的类名就可以。例如:先声明CEdit  m_myEdit;
    再将CEdit 该成CMyEdit就OK网络上很多那种自己写的控件类,你看看他的类的基类是什么,可能不是控件基类。
      

  12.   

    TO tomcat_jb:
    我也认为可能是我的控制变量有点问题。但是你说要先new一个变量,我觉得似乎有点问题啊!我用GetDlgItem这个方法取去控制指针的时候就分配了内存啊,如果我new一个在把指针指向用GetDlgItem取得的控件,那我自己new的一块内存不是泄漏了吗?你看看是不是有这个问题啊!你提供的第二种方法应该说是最正规的做法啊!呵呵,一直也没有太注意这个问题,下去好好研究下!
      

  13.   

    呵呵,我也不清楚如何做你说的方法了,但是用你说的代码,每次DLG退出时候都报错,应该还是使用方法的问题。你再问问别人。