65.9K
CodeProject 正在变化。 阅读更多。
Home

Windows 消息广播器

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.52/5 (14投票s)

2004年12月14日

CPOL

3分钟阅读

viewsIcon

77391

downloadIcon

1602

使用此类,您可以在无需知道窗口句柄的情况下将消息广播到窗口。您还可以同时将同一消息广播到多个窗口。

引言

在使用 MFC 开发文档/视图应用程序时,我经常发现需要将消息从一个视图或窗口发送到另一个窗口,而这些视图并不共享一个公共文档。例如,可以在一个视图中显示某个对象的属性,并在属性窗口中显示。正如任何尝试过这样做的人都知道,这涉及一个痛苦的过程:在创建时获取属性窗口的句柄,然后将其传递给所有需要使用该属性窗口的其他窗口。或者,您可以广播消息,任何人都可能告诉您 Microsoft Windows 没有有效的广播机制。我的 CBroadcaster 类可以轻松地处理消息广播。它还可以通过一次调用将同一消息发送到多个窗口。

工作原理

通过调用 CBroadcaster::InitBroadcaster(); 来初始化 broadcaster 类。该方法目前什么都不做。它只是一个占位符,与 CBroadcaster::UninitBroadcaster() 配对。

注册接收

对接收广播消息感兴趣的窗口只需通过 CBroadcaster::Register(…)broadcast 类注册自己。该方法允许一个窗口通过重复调用并传入新的 Message 值来注册多个消息。
注意:一个好的做法是在窗口类的析构函数中调用 CBroadcaster::Unregister(this)

发送消息

有两种发送消息的方法。一种方法允许调用者检查每个窗口处理过的消息的返回值,另一种方法则只将消息发送到所有已注册的窗口并忽略返回值。

为了检查每个发送/发布消息的返回值,调用者必须调用 CBoardcaster::StartSendCBoardcaster::StartPost 来初始化发送/发布过程。然后,用户可以调用 CBoardcaster::SendNextCBoardcaster::PostNext 来发送消息。当这些方法返回 true 时,表示找到了感兴趣于指定消息的窗口,并且消息已发送。返回 FALSE 表示收件人列表的结束。

要直接广播消息而不考虑返回值,请调用 CBroadcaster::SendToAll()CBroadcaster::PostToAll()

清理。

在程序退出之前,不要忘记调用 CBroadcaster::UninitBroadCaster()。由于这是一个 static 类,不需要实例化,因此析构函数不会被调用。该方法将在窗口未从 CBroadcaster Unregister 自身的情况下进行所有必要的清理。

示例代码:

BOOL CMyApp::InitInstance()
{
   ...
   CBroadcaster::InitBroadcaster();
   ...
}

int CMyApp::ExitInstance()
{
   ...
   CBroadcaster::UninitBroadcaster();
   ...
}

void CView1::OnInitalUpdate()
{
   CView::OnInitalUpdate();
   CBroadcaster::Register(this,WM_MYMESSAGE);
}

void CView2::OnInitalUpdate()
{
   CView::OnInitalUpdate();
   CBroadcaster::Register(this,WM_MYMESSAGE);
   CBroadcaster::Register(this,WM_ANOTHERMESSAGE);
}

void CView3::OnItemSelected()
{
   LRESULT Result
   CBoardcaster::StartSend(WM_MYMESSAGE,0,pItem,Result);
   while (CBroadcaster::SendNext(Result))
   {
      if (Result == 0)
      {
          MessageBox(“The result was not good”);
      }
   }
}

void CView4::OnListSelChanged()
{
   CBroadcaster::PostToAll(WM_ANOTHERMESSAGE,0,ItemIndex);
}

更新 - 版本 2

CBroadcaster 类的第一个版本存在一个弱点。当一个窗口在响应由 CBroadcaster 发送的消息时取消注册自身时,该问题就会暴露出来,当它向某个窗口发送消息,而该窗口正在迭代其内部的 CRegisteredWindows 列表时。当它向某个窗口发送消息,而该窗口因此取消注册了自身,取消注册可能会从列表中删除 CRegisteredWindow 对象,这将导致“消息发送”函数的迭代器处于不良状态,因为当前它所指向的项目已不再存在。

解决此问题的唯一方法是不要删除实际的 CRegisteredWindow 对象,而是将其标记为已删除,然后在稍后进行实际删除。因此,在版本 2 中,有一个名为 CheckDeleted 的新函数,它将遍历已注册的窗口,并删除那些被标记为已删除的窗口。此方法可以调用在代码中的任何位置(当然,除了在响应 CBroadcaster 的消息时)。如果您更喜欢使用版本 2,我建议将对此方法的调用放在应用程序的 OnIdle 方法中。

© . All rights reserved.