WEB开发网
开发学院软件开发VC 事件编程(一) 阅读

事件编程(一)

 2007-03-15 21:53:34 来源:WEB开发网   
核心提示: // in CPrimeCalculator::FindPrimesfor (UINT p=2; p<max; p++) {// figure out if p is primeif (/* every now and then */)NotifyProgress(GetNumber
// in CPrimeCalculator::FindPrimes
for (UINT p=2; p<max; p++) {
// figure out if p is prime
if (/* every now and then */)
NotifyProgress(GetNumberOfPrimes());
...
}
NotifyDone();

CPrimeCalculator 调用内部辅助函数 NotifyProgress 和 NotifyDone 来触发事件。这些函数遍历客户机对象列表,为每个客户机调用相应的事件处理器。代码如下:

void CPrimeCalculator::NotifyProgress(UINT nFound)
{
  list<IPrimeEvents*>::iterator it;
  for (it=m_clients.begin(); it!=m_clients.end(); it++) {
    (*it)->OnProgress(nFound);
  }
}

如果你对 STL 不熟悉,去看看有关迭代器反引用操作符的内容,它返回当前指向的对象,上面代码段中,for 循环里的代码等同于:

IPrimeEvents* obj = *it;
obj->OnProgress(nFound);

触发 Done 事件的 NotifyDone 函数做法类似,它没有参数,如 Figure 3 所示。你也许觉得 Done 事件是多余的,因为当 FindPrimes 返回控制时,客户机已经知道 CPrimeCalculator 完成了工作。没错——但有一种情况除外,那就是多个客户机注册接收的事件,并且调用 CPrimeCalculator::FindPrimes 的对象可能不是同一个。Figure 4 是我的测试程序 PrimeCalc。该程序为素数事件实现了两个不同的事件处理器。第一个处理器是主对话框本身,CMyDlg,它利用多继承实现 IPrimeEvents。该对话框处理 OnProgress 和 OnDone,并在对话窗口显示进度,完成后发出蜂鸣声。其它的事件处理器,如 CTracePrimeEvents 也实现了 IPrimeEvents,这个实现显示诊断(TRACE)流中的信息。如 Figure 6 所示,在我的 TraceWin 程序(参见 2004 年三月的专栏)中显示的范例输出。我写的 CTracePrimeEvents 展示了多个客户机如何注册相同的事件。


Figure 5 运行中的 PrimeCalc

从使用 CPrimeCalculator 来编写应用的程序员角度看,处理事件简单而直白。从 IPrimeEvents 派生,实现处理器函数,然后调用 Register。从编写触发事件的类的程序员看来,这个过程有些冗长乏味。首先你得定义事件接口。这并没有什么不好。但接着你得编写 Register 和 Unregister 函数,每个 Foo 事件都得有一个相应的 NotifyFoo 函数。如果有 15 个事件的话,那就十分令人不爽了,尤其是每个 NotifyFoo 函数的模式都相同:

void CMyClass::NotifyFoo(/* args */)
{
  list<IPrimeEvents*>::iterator it;
  for (it=m_clients.begin(); it!=m_clients.end(); it++) {
    (*it)->OnFoo(/* args */);
  }
}


Figure 6 PrimeCalc 在 TraceWin 中的输出

NotifyFoo 迭代客户机列表,为每个注册的客户机调用相应的 OnFoo 处理器,并传递任何需要的参数。有没有什么方法实现这个一般过程,比如用宏或者模板来封装这种繁琐而固定的样板代码,将自己从重复性劳动中解放出来呢?实际上是有的。下个月的专栏文章我们将讨论这个问题。记住在同一时间,同一频道,咱们再见——顺祝编程愉快!

上一页  1 2 3 4 5 

Tags:事件 编程

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接