You may have noticed by now that DataUser has an Advise menu on which appear the items shown in Figure 10-4 on the following page. Through this menu, you can tell DataUser to call IDataObject::DAdvise on the current object with any of the three data formats. The GetData On Change and Paint On Change items are enabled only for in-process objects and allow you to control what happens inside DataUser's implementation of IAdviseSink, which is found in the file IADVSINK.CPP.
Figure 10-4.
The DataUser program showing the Advise menu along with the large bitmap.
DataUser implements the advise sink through the class CAdviseSink, creating one such object on startup and using that same instance throughout DataUser's lifetime. DataUser holds the sink's IAdviseSink pointer in the variable m_pIAdviseSink, releasing it on shutdown. The implementation of CAdviseSink holds a backpointer to the main application class CApp to tell the application when to repaint or change its data, but otherwise, it is an independent object with its own QueryInterface behavior and a Release function that destroys it when no more references are extant.
When you tell DataUser to create an advisory connection, it passes its m_pIAdviseSink pointer to IDataObject::DAdvise along with the FORMATETC matching the menu item you select and the ADVF_NODATA flag (allowing us to time the raw notification rates exclusive of the time it takes to render data). The connection key is stored in m_dwConn inside CApp. DataUser makes all of these formats mutually exclusive, so selecting one will tear down any existing advisory connection for another:
//In the WM_COMMAND message case of DataUserWndProc
case IDM_ADVISETEXT:
case IDM_ADVISEBITMAP:
case IDM_ADVISEMETAFILEPICT:
if (NULL==pApp->m_pIDataObject)
break;
//Terminate old connection
if (0!=pApp->m_dwConn)
{
pApp->m_pIDataObject->DUnadvise(pApp
->m_dwConn);
}
CheckMenuItem(hMenu, pApp->m_cfAdvise
+IDM_ADVISEMIN, MF_UNCHECKED);
CheckMenuItem(hMenu, wID, MF_CHECKED);
//New format is wID-IDM_ADVISEMIN.
pApp->m_cfAdvise=(UINT)(wID-IDM_ADVISEMIN);
fe.cfFormat=pApp->m_cfAdvise;
pApp->m_pIDataObject->DAdvise(&fe, ADVF_NODATA
, pApp->m_pIAdviseSink, &pApp->m_dwConn);
break;
Keep in mind that an advise connection is always associated with not only a specific data format but also the dwAspect contained in the FORMATETC structure passed to DAdvise. If the data object does not support that aspect, it can refuse the connection; otherwise, it uses that aspect to determine when it needs to send a notification.