none
急!!C++如何为控件绑定事件 RRS feed

  • 问题

  •         在C++中,如何为一个已经写好某个事件的控件的同类控件绑定已经写好某个事件的控件的那个事件应该如何绑定事件?

             例如,C++中一个“选择学期toolStripMenuItem”的控件已写好的一个事件:“选择学期toolStripMenuItem_DropDownItemClicked”事件。而我还有一个“新的toolStripMenuItem”控件,我想为其绑定“选择学期toolStripMenuItem_DropDownItemClicked”,使“新的toolStripMenuItem”控件在发生DropDownItemClicked事件时调用“选择学期toolStripMenuItem_DropDownItemClicked”事件。请问大牛们应该如何绑定?

    2013年8月3日 7:48

答案

  • 你好,

    请注意你的代码类型。以上提供的代码是基于MFC的事件示例。一些框架如MFC和ATL等都可以用来开发控件。

    在 Visual C++中进行事件处理时使用统一事件模型,能够让你为所有类型的C++类的事件处理使用相同的编程模型: 

    • 本机C++类(没有实现COM对象的C++类).
    • COM 类(实现COM 对象的C++ 类,通常使用 ATL 类或 coclass 属性).
    • 托管类(用关键字__gc 声明的C++类,或在托管环境中声明).

    <sentencetext xmlns="http://www.w3.org/1999/xhtml">事件处理主要由 COM 类支持,具体请查看COM事件处理。</sentencetext>

    事件处理也由本机C++类支持,然而这种支持是过时的并且会在将来版本中移除。具体请查看本机C++事件处理。

    在COM事件处理,在事件接收器类中,可以使用内部函数 __hook 关联事件和事件处理程序,使用 __unhook 取消事件与事件处理程序的关联。<sentencetext xmlns="http://www.w3.org/1999/xhtml">可以将多个事件挂钩(hook)到事件处理程序,或多个事件处理程序添加到事件。下面代码为 __hook的使用:</sentencetext>

    [coclass, event_receiver(com, true)]
    class CReceiver {
    public:
       HRESULT MyEvent1(int nValue) {  // name and signature matches MyEvent1
          ...
       }
       HRESULT MyEvent2(E c, char* pc) {  // signature doesn't match MyEvent2
          ...
       }
       HRESULT MyHandler1(int nValue) {  // name doesn't match MyEvent1 (or 2)
          ...
       }
       void HookEvent(IEventSource* pSource) {
          __hook(IFace, pSource);  // Hooks up all name-matched events 
                                   // under layout_dependent = true
          __hook(&IFace::MyEvent1, pSource, &CReceive::MyEvent1);   // valid
          __hook(&IFace::MyEvent2, pSource, &CSink::MyEvent2);   // not valid
          __hook(&IFace::MyEvent1, pSource, &CSink:: MyHandler1); // not valid
       }
    };

    打开如何在C++/CLI中使用事件,可以查看具体的事件处理方法。

    一个事件和事件处理程序可以定义在一个组件内,同时由其它组件调用,如下所示:

    // mcppv2_events8.cpp
    // compile with: /LD /clr
    using namespace System;
    
    public delegate void Del(String^ s);
    
    public ref class Source {
    public:
       event Del^ Event;
       void Fire(String^ s) {
          Event(s);
       }
    };

    由客户端代码调用事件:

    // mcppv2_events9.cpp
    // compile with: /clr
    #using "mcppv2_events8.dll"
    using namespace System;
    
    ref class Receiver {
    public:
       void Handler(String^ s) {
          Console::WriteLine(s);
       }
    };
    
    int main() {
       Source^ src = gcnew Source;
       Receiver^ rc1 = gcnew Receiver;
       Receiver^ rc2 = gcnew Receiver;
       src -> Event += gcnew Del(rc1, &Receiver::Handler);
       src -> Event += gcnew Del(rc2, &Receiver::Handler);
       src->Fire("hello");
       src -> Event -= gcnew Del(rc1, &Receiver::Handler);
       src -> Event -= gcnew Del(rc2, &Receiver::Handler);
    }

     


    Jane Wang
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2013年8月5日 9:57
    版主

全部回复

  • 你好,

    可以先给相关控件赋连续的ID值,然后调用ON_COMMAND_RANGE(FIRST_BUTTON_ID, LAST_BUTTON_ID, HandlerFunction),函数HandlerFunction通过识别nID处理事件。以下是代码样例:

    // 以下代码段展示如何使用宏ON_COMMAND_RANGE // 映射连续范围的控制ID到一个消息处理函数(例如下例中的 OnFileMenuItems()即HandlerFunction).

    // 另外,本例也展示了如何使用CheckMenuRadioItem()来查看选定的菜单项并使其成为单选项

    BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) // ... ON_COMMAND_RANGE(ID_FILE_MENUITEM1, ID_FILE_MENUITEM3, OnFileMenuItems) END_MESSAGE_MAP() void CMainFrame::OnFileMenuItems(UINT nID) { CMenu* mmenu = GetMenu(); CMenu* submenu = mmenu->GetSubMenu(0); submenu->CheckMenuRadioItem(ID_FILE_MENUITEM1, ID_FILE_MENUITEM3, nID, MF_BYCOMMAND); }

    或者,使用ON_CONTROL_RANGE(wNotifyCode, ID1, ID2, HandlerFunction),如下例所示:

     ON_CONTROL_RANGE(BN_CLICKED, IDC_BUTTON_1, IDC_BUTTON_XX, OnButtonClick)
    
     void CXXXDlg::OnButtonClick(UINT nID)
     {
      int nIndex = nID - IDC_BUTTON_1;
      CString str;
      str.Format(_T("Index: %d"), nIndex);
      AfxMessageBox(str);
     }
    

    更多详细信息,请参考:

    ON_COMMAND_RANGE

    ON_CONTROL_RANGE


    Jane Wang
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2013年8月4日 9:06
    版主
  • 我我记得在C#中绑定事件可以通过一句代码就可以实现;

    例如,newWebBrowser.Navigated += new WebBrowserNavigatedEventHandler(webBrowser1_Navigated)

    那C++下是否有这种用法呢?

    2013年8月4日 11:39
  • 不可以

    VC下没有这种机制


    新浪微博http://weibo.com/xianglitian,欢迎围观

    2013年8月5日 1:37
  • 你好,

    请注意你的代码类型。以上提供的代码是基于MFC的事件示例。一些框架如MFC和ATL等都可以用来开发控件。

    在 Visual C++中进行事件处理时使用统一事件模型,能够让你为所有类型的C++类的事件处理使用相同的编程模型: 

    • 本机C++类(没有实现COM对象的C++类).
    • COM 类(实现COM 对象的C++ 类,通常使用 ATL 类或 coclass 属性).
    • 托管类(用关键字__gc 声明的C++类,或在托管环境中声明).

    <sentencetext xmlns="http://www.w3.org/1999/xhtml">事件处理主要由 COM 类支持,具体请查看COM事件处理。</sentencetext>

    事件处理也由本机C++类支持,然而这种支持是过时的并且会在将来版本中移除。具体请查看本机C++事件处理。

    在COM事件处理,在事件接收器类中,可以使用内部函数 __hook 关联事件和事件处理程序,使用 __unhook 取消事件与事件处理程序的关联。<sentencetext xmlns="http://www.w3.org/1999/xhtml">可以将多个事件挂钩(hook)到事件处理程序,或多个事件处理程序添加到事件。下面代码为 __hook的使用:</sentencetext>

    [coclass, event_receiver(com, true)]
    class CReceiver {
    public:
       HRESULT MyEvent1(int nValue) {  // name and signature matches MyEvent1
          ...
       }
       HRESULT MyEvent2(E c, char* pc) {  // signature doesn't match MyEvent2
          ...
       }
       HRESULT MyHandler1(int nValue) {  // name doesn't match MyEvent1 (or 2)
          ...
       }
       void HookEvent(IEventSource* pSource) {
          __hook(IFace, pSource);  // Hooks up all name-matched events 
                                   // under layout_dependent = true
          __hook(&IFace::MyEvent1, pSource, &CReceive::MyEvent1);   // valid
          __hook(&IFace::MyEvent2, pSource, &CSink::MyEvent2);   // not valid
          __hook(&IFace::MyEvent1, pSource, &CSink:: MyHandler1); // not valid
       }
    };

    打开如何在C++/CLI中使用事件,可以查看具体的事件处理方法。

    一个事件和事件处理程序可以定义在一个组件内,同时由其它组件调用,如下所示:

    // mcppv2_events8.cpp
    // compile with: /LD /clr
    using namespace System;
    
    public delegate void Del(String^ s);
    
    public ref class Source {
    public:
       event Del^ Event;
       void Fire(String^ s) {
          Event(s);
       }
    };

    由客户端代码调用事件:

    // mcppv2_events9.cpp
    // compile with: /clr
    #using "mcppv2_events8.dll"
    using namespace System;
    
    ref class Receiver {
    public:
       void Handler(String^ s) {
          Console::WriteLine(s);
       }
    };
    
    int main() {
       Source^ src = gcnew Source;
       Receiver^ rc1 = gcnew Receiver;
       Receiver^ rc2 = gcnew Receiver;
       src -> Event += gcnew Del(rc1, &Receiver::Handler);
       src -> Event += gcnew Del(rc2, &Receiver::Handler);
       src->Fire("hello");
       src -> Event -= gcnew Del(rc1, &Receiver::Handler);
       src -> Event -= gcnew Del(rc2, &Receiver::Handler);
    }

     


    Jane Wang
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2013年8月5日 9:57
    版主
  • 请问有没有更简单点的方法绑定时间。
    2013年8月7日 9:51
  • 你好,

    有无相生,难易相成。

    你可以参照以上提供的方案绑定事件,如果能成功解决问题,在熟练之后自然能够得出“更简单的方法”。


    Jane Wang
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2013年8月8日 1:15
    版主