Manage and Process Accelerators

The UI-active object always has first crack at accelerators. If the object is implemented in a local server, your own message loop will be the first to retrieve keystrokes headed for its window, in which case you process accelerators by calling the Windows function TranslateAccelerator as you always have. If you have an in-process object, however, the container's message loop will pick up the message and call your IOleInPlaceActiveObject::TranslateAccelerator function before it dares to translate the accelerator itself. This member of IOleInPlaceActiveObject is not called in a local object, so Cosmo leaves it empty. The Polyline sample in this chapter doesn't do anything with it either because it has no accelerators.

Nevertheless, Cosmo, as a local server, has two other considerations for its message loop in order to handle accelerators properly. First, it must avoid calling the Windows function TranslateMDISysAccel if it is an MDI application because the Window menu is not available during an in-place session. Second, it must call OleTranslateAccelerator to give the container a shot at the accelerators before the server dumps the message to TranslateMessage and DispatchMessage. Therefore, Cosmo's message loop, CCosmoFrame::MessageLoop, appears as follows:


WPARAM CCosmoFrame::MessageLoop(void)
{
MSG msg;

while (GetMessage(&msg, NULL, 0,0 ))
{
//If we're in place, don't bother with MDI accelerators.
if (NULL==m_pIOleIPFrame)
{
if (m_pCL->TranslateAccelerator(&msg))
continue;
}

//Translate our accelerators.
if (TranslateAccelerator(m_hWnd, m_hAccel, &msg))
continue;

if (NULL!=m_pIOleIPFrame)
{
if (NOERROR==OleTranslateAccelerator(m_pIOleIPFrame
, &m_frameInfo, &msg))
continue;
}

TranslateMessage(&msg);
DispatchMessage(&msg);
}

return msg.wParam;
}

The IOleInPlaceFrame pointer (m_pIOleIPFrame) and the OLEINPLACEFRAMEINFO structure (m_frameInfo) passed to OleTranslateAccelerator are those obtained from IOleInPlaceSite::GetWindowContext. We saved these earlier in CFigure::InPlaceActivate.

Note: A local MDI and multiple-use server will have a more complex test to determine whether to call OleTranslateAccelerator. You must call the function with the IOleInPlaceFrame pointer and OLEINPLACEFRAMEINFO structure of the container that's involved with the in-place object in the currently active document.