The other action a client can take is to parse a display name into a moniker, either to simply test whether the moniker is valid or to actually go all the way and bind the moniker. LinkUser does the latter in CApp::ParseAndBind in response to the Link/Parse Display Name And Bind menu item:
void CApp::ParseAndBind(void)
{
HRESULT hr;
IBindCtx *pbc;
IMoniker *pmk;
int i;
TCHAR szName[512];
ULONG chEaten=0;
i=(int)SendMessage(m_hWndList, LB_GETCURSEL, 0, 0L);
if (LB_ERR==i)
return;
SendMessage(m_hWndList, LB_GETTEXT, i, (LPARAM)(LPTSTR)szName);
if (FAILED(CreateBindCtx(0, &pbc)))
[Error message and return]
hr=MkParseDisplayName(pbc, szName, &chEaten, &pmk);
if (SUCCEEDED(hr))
{
MessageBox(m_hWnd, TEXT("Name parsed. Press OK to bind.")
, TEXT("Link User"), MB_OK);
BindAndShow(pmk, pbc);
pmk->Release();
}
else
{
//Tell user how far parsing got.
wsprintf(szName, TEXT("Parsing failed after %lu characters.")
, chEaten);
MessageBox(m_hWnd, szName, TEXT("Link User"), MB_OK);
}
pbc->Release();
return;
}
Just as with binding, MkParseDisplayName encapsulates all the magic for us. Because this API function takes a bind context and because the parsing process will contain registered bound objects after parsing is complete, we can use this same bind context to bind the moniker and show its description, thereby making the extra binding step more efficient. In other words, the server that did the parsing will still be running until we release the bind context, so subsequent binding with that same context is more efficient.
The pchEaten argument that comes back from MkParseDisplayName is important because it would allow a client to display where the parsing encountered an error. We'll see specific use of this value in Chapter 20, when we look at the Links dialog box standard for linked objects in OLE Documents.