// This is a part of the Microsoft Foundation Classes C++ library. // Copyright (C) 1992-1998 Microsoft Corporation // All rights reserved. // // This source code is only intended as a supplement to the // Microsoft Foundation Classes Reference and related // electronic documentation provided with the library. // See these sources for detailed information regarding the // Microsoft Foundation Classes product. #include "stdafx.h" #ifdef AFXCTL_CORE2_SEG #pragma code_seg(AFXCTL_CORE2_SEG) #endif #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #define new DEBUG_NEW struct _AFXCTL_UIACTIVE_INFO { OLEMENUGROUPWIDTHS m_menuWidths; HMENU m_hSharedMenu; HOLEMENU m_hOleMenu; _AFXCTL_UIACTIVE_INFO(HMENU hInPlaceMenu, LPOLEINPLACEFRAME pInPlaceFrame); ~_AFXCTL_UIACTIVE_INFO(); }; _AFXCTL_UIACTIVE_INFO::_AFXCTL_UIACTIVE_INFO(HMENU hInPlaceMenu, LPOLEINPLACEFRAME pInPlaceFrame) { memset(&m_menuWidths, 0, sizeof m_menuWidths); m_hSharedMenu = NULL; m_hOleMenu = NULL; if (hInPlaceMenu != NULL) { // Create shared menu if ((m_hSharedMenu = ::CreateMenu()) == NULL) return; // Start out by getting menu from container if (pInPlaceFrame->InsertMenus(m_hSharedMenu, &m_menuWidths) != S_OK) { ::DestroyMenu(m_hSharedMenu); m_hSharedMenu = NULL; } else { // Container shouldn't touch these ASSERT(m_menuWidths.width[1] == 0); ASSERT(m_menuWidths.width[3] == 0); ASSERT(m_menuWidths.width[5] == 0); // Only copy the popups if there is a menu loaded if (hInPlaceMenu != NULL) { // Insert our menu popups amongst the container menus AfxMergeMenus(m_hSharedMenu, hInPlaceMenu, &m_menuWidths.width[0], 1); } } } // Finally create the special OLE menu descriptor m_hOleMenu = ::OleCreateMenuDescriptor(m_hSharedMenu, &m_menuWidths); } _AFXCTL_UIACTIVE_INFO::~_AFXCTL_UIACTIVE_INFO() { if (m_hSharedMenu != NULL) ::DestroyMenu(m_hSharedMenu); if (m_hOleMenu != NULL) VERIFY(::OleDestroyMenuDescriptor(m_hOleMenu) == S_OK); } short AFXAPI _AfxShiftState(); void AFXAPI _GetClippingCoordinates(LPCRECT pPosRect, LPCRECT pClipRect, LPRECT pIntersectRect, LPPOINT pOffsetPoint) { int clipLeft = 0; int clipTop = 0; if ((pClipRect == NULL) || IsRectEmpty(pClipRect)) { CopyRect(pIntersectRect, pPosRect); } else { IntersectRect(pIntersectRect, pPosRect, pClipRect); clipLeft = pClipRect->left; clipTop = pClipRect->top; } pOffsetPoint->x = min(0, pPosRect->left - clipLeft); pOffsetPoint->y = min(0, pPosRect->top - clipTop); } HRESULT COleControl::OnActivateInPlace(BOOL bUIActivate, LPMSG pMsg) { #ifdef _AFXDLL if (m_bOpen) { m_pWndOpenFrame->SetActiveWindow(); SendAdvise(OBJECTCODE_SHOWWINDOW); return S_OK; } #endif // Initialize pointer to in-place site, if necessary. if (m_pInPlaceSite == NULL) { if (m_pClientSite == NULL) return E_UNEXPECTED; if ((GetControlFlags() & windowlessActivate) && SUCCEEDED(m_pClientSite->QueryInterface(IID_IOleInPlaceSiteWindowless, reinterpret_cast(&m_pInPlaceSiteWndless)))) { m_bInPlaceSiteWndless = m_bInPlaceSiteEx = TRUE; } else if ((GetControlFlags() & noFlickerActivate) && SUCCEEDED(m_pClientSite->QueryInterface(IID_IOleInPlaceSiteEx, reinterpret_cast(&m_pInPlaceSiteEx)))) { m_bInPlaceSiteEx = TRUE; } else if (SUCCEEDED(m_pClientSite->QueryInterface(IID_IOleInPlaceSite, reinterpret_cast(&m_pInPlaceSite)))) { m_bInPlaceSiteEx = FALSE; } else { m_pInPlaceSite = NULL; return E_FAIL; } } ASSERT(m_pInPlaceSite != NULL); if ((m_bInPlaceActive && !bUIActivate) || m_bUIActive) { CWnd* pWndOuter = GetOuterWindow(); HWND hwndParent; if ((pWndOuter != NULL) && SUCCEEDED(m_pInPlaceSite->GetWindow(&hwndParent)) && (hwndParent == ::GetParent(pWndOuter->m_hWnd))) { ::SetWindowPos(pWndOuter->m_hWnd, NULL, 0, 0, 0, 0, SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE| SWP_SHOWWINDOW); OnSetObjectRects(m_rcPos, NULL); return S_OK; } } // Check if container allows windowless activation. if (m_bInPlaceSiteWndless) { if (m_pInPlaceSiteWndless->CanWindowlessActivate() != S_OK) m_bInPlaceSiteWndless = FALSE; } HRESULT hr = E_FAIL; if (m_pInPlaceSite != NULL) hr = m_pInPlaceSite->CanInPlaceActivate(); if (hr != NOERROR) { // Site doesn't allow in-place activation. return OnOpen(FALSE, pMsg); } if (!m_bInPlaceActive) { if (m_bInPlaceSiteEx) { // flicker-free and/or windowless activation BOOL bNoRedraw; m_pInPlaceSiteEx->OnInPlaceActivateEx(&bNoRedraw, m_bInPlaceSiteWndless ? ACTIVATE_WINDOWLESS : 0); if (GetControlFlags() & noFlickerActivate) m_bNoRedraw = bNoRedraw; } else { // old-style activation m_pInPlaceSite->OnInPlaceActivate(); } } HWND hwndParent = NULL; if (SUCCEEDED(m_pInPlaceSite->GetWindow(&hwndParent))) { CRect rcClip; m_frameInfo.cb = sizeof(OLEINPLACEFRAMEINFO); RELEASE(m_pInPlaceFrame); RELEASE(m_pInPlaceDoc); if (SUCCEEDED(m_pInPlaceSite->GetWindowContext( &m_pInPlaceFrame, &m_pInPlaceDoc, &m_rcPos, &rcClip, &m_frameInfo))) { ASSERT(m_pInPlaceFrame != NULL); CRect rectClip; if (!m_bInPlaceSiteWndless) { _GetClippingCoordinates(&m_rcPos, &rcClip, rectClip, &m_ptOffset); m_bInPlaceActive = CreateControlWindow(hwndParent, m_rcPos, rectClip); } else { m_bInPlaceActive = TRUE; } if (m_bInPlaceActive) { if (bUIActivate) { if (m_bInPlaceSiteEx) { if (m_pInPlaceSiteEx->RequestUIActivate() != S_OK) m_pInPlaceSite->OnUIDeactivate(FALSE); } BuildSharedMenu(); m_bUIActive = TRUE; m_pInPlaceSite->OnUIActivate(); m_pInPlaceFrame->SetActiveObject( &m_xOleInPlaceActiveObject, NULL); if (m_pInPlaceDoc != NULL) m_pInPlaceDoc->SetActiveObject( &m_xOleInPlaceActiveObject, NULL); if (m_hWnd != NULL) { BOOL bHandles = AmbientShowGrabHandles(); BOOL bHatching = AmbientShowHatching(); if (bHandles || bHatching) CreateTracker(bHandles, bHatching, rcClip); } AddFrameLevelUI(); if (bUIActivate != -1 && (m_hWnd != NULL) && !IsChild(GetFocus())) { SetFocus(); } } // Pass thru the window message that caused us to be activated if ((m_hWnd != NULL || m_bInPlaceSiteWndless) && (pMsg != NULL)) ForwardActivationMsg(pMsg); // Send appropriate notifications... SendAdvise(OBJECTCODE_SHOWOBJECT); return S_OK; } } } RELEASE(m_pInPlaceFrame); RELEASE(m_pInPlaceDoc); return E_FAIL; } void COleControl::ForwardActivationMsg(LPMSG pMsg) { UINT uMsg = pMsg->message; LPARAM lParam = pMsg->lParam; if (m_bInPlaceSiteWndless) { // For mouse messages, convert to container window's coordinates if ((uMsg >= WM_MOUSEFIRST) && (uMsg <= WM_MOUSELAST)) { POINT ptNew = pMsg->pt; HWND hWndContainer = NULL; if (SUCCEEDED(m_pInPlaceSite->GetWindow(&hWndContainer))) { ::ScreenToClient(hWndContainer, &ptNew); lParam = MAKELONG((short)ptNew.x, (short)ptNew.y); } } // Process message on behalf of windowless control OnWindowlessMessage(uMsg, pMsg->wParam, lParam, NULL); } else { // For mouse messages, convert to this window's coordinates if ((uMsg >= WM_MOUSEFIRST) && (uMsg <= WM_MOUSELAST)) { POINT ptNew = pMsg->pt; ScreenToClient(&ptNew); lParam = MAKELONG((short)ptNew.x, (short)ptNew.y); } // Pass the message along to the control's window SendMessage(uMsg, pMsg->wParam, lParam); } } HMENU COleControl::OnGetInPlaceMenu() { // Default: no in-place menu return NULL; } BOOL COleControl::BuildSharedMenu() { // This can be called more than once on mouse clicks if (m_pUIActiveInfo != NULL) { ASSERT(m_pUIActiveInfo->m_hSharedMenu != NULL); return TRUE; } HMENU hMenu = m_bUIDead ? NULL : OnGetInPlaceMenu(); TRY { m_pUIActiveInfo = new _AFXCTL_UIACTIVE_INFO(hMenu, m_pInPlaceFrame); } END_TRY return (m_pUIActiveInfo != NULL) && (m_pUIActiveInfo->m_hOleMenu != NULL); } void COleControl::DestroySharedMenu() { ASSERT(m_pUIActiveInfo != NULL); if (m_pUIActiveInfo == NULL) return; HMENU hInPlaceMenu = NULL; if ((m_pUIActiveInfo->m_hSharedMenu != NULL) && ((hInPlaceMenu = OnGetInPlaceMenu()) != NULL)) { // remove our menu popups from the shared menu AfxUnmergeMenus(m_pUIActiveInfo->m_hSharedMenu, hInPlaceMenu); // allow container to remove its items from the menu ASSERT(m_pInPlaceFrame != NULL); VERIFY(m_pInPlaceFrame->RemoveMenus(m_pUIActiveInfo->m_hSharedMenu) == S_OK); } delete m_pUIActiveInfo; m_pUIActiveInfo = NULL; } void COleControl::AddFrameLevelUI() { ASSERT(m_pUIActiveInfo != NULL); if (m_pUIActiveInfo == NULL) return; m_pInPlaceFrame->SetMenu(m_pUIActiveInfo->m_hSharedMenu, m_pUIActiveInfo->m_hOleMenu, m_hWnd); OnShowToolBars(); } void COleControl::RemoveFrameLevelUI() { ASSERT(m_pUIActiveInfo != NULL); if (m_pUIActiveInfo == NULL) return; OnHideToolBars(); // allow container to remove its items from the menu ASSERT(m_pInPlaceFrame != NULL); if (m_pUIActiveInfo->m_hSharedMenu != NULL) VERIFY(m_pInPlaceFrame->RemoveMenus(m_pUIActiveInfo->m_hSharedMenu) == S_OK); } void COleControl::OnShowToolBars() { // Default sets border space to empty. // When overriding, don't call this implementation. m_pInPlaceFrame->SetBorderSpace(NULL); } void COleControl::OnHideToolBars() { // Default does nothing } ///////////////////////////////////////////////////////////////////////////// // COleControl::XOleInPlaceObject STDMETHODIMP_(ULONG) COleControl::XOleInPlaceObject::AddRef() { METHOD_PROLOGUE_EX_(COleControl, OleInPlaceObject) return (ULONG)pThis->ExternalAddRef(); } STDMETHODIMP_(ULONG) COleControl::XOleInPlaceObject::Release() { METHOD_PROLOGUE_EX_(COleControl, OleInPlaceObject) return (ULONG)pThis->ExternalRelease(); } STDMETHODIMP COleControl::XOleInPlaceObject::QueryInterface( REFIID iid, LPVOID* ppvObj) { METHOD_PROLOGUE_EX_(COleControl, OleInPlaceObject) return (HRESULT)pThis->ExternalQueryInterface(&iid, ppvObj); } STDMETHODIMP COleControl::XOleInPlaceObject::GetWindow(HWND* lphwnd) { METHOD_PROLOGUE_EX_(COleControl, OleInPlaceObject) *lphwnd = pThis->m_bInPlaceActive ? pThis->GetOuterWindow()->m_hWnd : NULL; return (*lphwnd != NULL) ? S_OK : E_FAIL; } STDMETHODIMP COleControl::XOleInPlaceObject::ContextSensitiveHelp(BOOL) { return E_NOTIMPL; } STDMETHODIMP COleControl::XOleInPlaceObject::InPlaceDeactivate() { METHOD_PROLOGUE_EX(COleControl, OleInPlaceObject) if (!pThis->m_bInPlaceActive) return S_OK; pThis->m_bInPlaceActive = FALSE; if (pThis->m_bUIActive) UIDeactivate(); // hide the window if (pThis->m_bInPlaceSiteEx && (pThis->GetControlFlags() & noFlickerActivate)) { // flicker-free deactivation if (! pThis->m_bInPlaceSiteWndless) { pThis->UpdateWindow(); pThis->OnHide(); } pThis->m_pInPlaceSiteEx->OnInPlaceDeactivateEx(TRUE); } else { // old-style deactivation pThis->OnHide(); pThis->m_pInPlaceSite->OnInPlaceDeactivate(); } return S_OK; } STDMETHODIMP COleControl::XOleInPlaceObject::UIDeactivate() { METHOD_PROLOGUE_EX(COleControl, OleInPlaceObject) pThis->m_bPendingUIActivation = FALSE; if (!pThis->m_bUIActive) return S_OK; pThis->DestroyTracker(); pThis->m_bUIActive = FALSE; if (pThis->m_pInPlaceDoc != NULL) pThis->m_pInPlaceDoc->SetActiveObject(NULL, NULL); pThis->m_pInPlaceFrame->SetActiveObject(NULL, NULL); pThis->RemoveFrameLevelUI(); pThis->DestroySharedMenu(); pThis->m_pInPlaceSite->OnUIDeactivate(FALSE); return S_OK; } STDMETHODIMP COleControl::XOleInPlaceObject::SetObjectRects(LPCRECT lprcPosRect, LPCRECT lprcClipRect) { METHOD_PROLOGUE_EX(COleControl, OleInPlaceObject) return pThis->OnSetObjectRects(lprcPosRect, lprcClipRect) ? S_OK : E_FAIL; } BOOL COleControl::OnSetObjectRects(LPCRECT lprcPosRect, LPCRECT lprcClipRect) { ASSERT(lprcPosRect != NULL); // Remember the position rectangle for later m_rcPos = *lprcPosRect; // Calculate complete rectangle including the tracker (if present) CRect rectPos = m_rcPos; if (m_bUIActive && m_pRectTracker != NULL) { // Save new clipping rectangle (for DestroyTracker) if (lprcClipRect != NULL) m_pRectTracker->m_rectClip = *lprcClipRect; // Adjust tracker rectangle to new dimensions CRect rectTmp = rectPos; rectTmp.OffsetRect(-rectTmp.left, -rectTmp.top); m_pRectTracker->m_rect = rectTmp; // Adjust the "true" rectangle to include handles/hatching UINT nHandleSize = m_pRectTracker->m_nHandleSize - 1; rectPos.InflateRect(nHandleSize, nHandleSize); } // Now clip that rectangle as appropriate CRect rectClip; _GetClippingCoordinates(rectPos, lprcClipRect, rectClip, &m_ptOffset); // Move outer window first. then inner window if (!m_bInPlaceSiteWndless) { CWnd* pWndOuter = GetOuterWindow(); pWndOuter->MoveWindow(rectClip); if (pWndOuter != this) MoveWindow(m_ptOffset.x, m_ptOffset.y, rectPos.Width(), rectPos.Height()); } return TRUE; } STDMETHODIMP COleControl::XOleInPlaceObject::ReactivateAndUndo() { return E_NOTIMPL; } ///////////////////////////////////////////////////////////////////////////// // COleControl::XOleInPlaceActiveObject STDMETHODIMP_(ULONG) COleControl::XOleInPlaceActiveObject::AddRef() { METHOD_PROLOGUE_EX_(COleControl, OleInPlaceActiveObject) return (ULONG)pThis->ExternalAddRef(); } STDMETHODIMP_(ULONG) COleControl::XOleInPlaceActiveObject::Release() { METHOD_PROLOGUE_EX_(COleControl, OleInPlaceActiveObject) return (ULONG)pThis->ExternalRelease(); } STDMETHODIMP COleControl::XOleInPlaceActiveObject::QueryInterface( REFIID iid, LPVOID* ppvObj) { METHOD_PROLOGUE_EX_(COleControl, OleInPlaceActiveObject) return (HRESULT)pThis->ExternalQueryInterface(&iid, ppvObj); } STDMETHODIMP COleControl::XOleInPlaceActiveObject::GetWindow(HWND* lphwnd) { METHOD_PROLOGUE_EX_(COleControl, OleInPlaceActiveObject) return pThis->m_xOleInPlaceObject.GetWindow(lphwnd); } STDMETHODIMP COleControl::XOleInPlaceActiveObject::ContextSensitiveHelp(BOOL) { return E_NOTIMPL; } STDMETHODIMP COleControl::XOleInPlaceActiveObject::TranslateAccelerator( LPMSG lpmsg) { METHOD_PROLOGUE_EX(COleControl, OleInPlaceActiveObject) // Give the control the first chance. if (pThis->PreTranslateMessage(lpmsg)) return S_OK; // Give the site a chance. HRESULT hr = S_FALSE; if (pThis->m_pControlSite != NULL) hr = pThis->m_pControlSite->TranslateAccelerator(lpmsg, (DWORD)_AfxShiftState()); return hr; } STDMETHODIMP COleControl::XOleInPlaceActiveObject::OnFrameWindowActivate(BOOL) { return S_OK; } STDMETHODIMP COleControl::XOleInPlaceActiveObject::OnDocWindowActivate( BOOL fActivate) { METHOD_PROLOGUE_EX(COleControl, OleInPlaceActiveObject) if (fActivate && pThis->m_bUIActive) pThis->AddFrameLevelUI(); else pThis->OnHideToolBars(); return S_OK; } STDMETHODIMP COleControl::XOleInPlaceActiveObject::ResizeBorder( LPCRECT, LPOLEINPLACEUIWINDOW, BOOL) { return S_OK; } STDMETHODIMP COleControl::XOleInPlaceActiveObject::EnableModeless(BOOL) { return S_OK; } ///////////////////////////////////////////////////////////////////////////// // Force any extra compiler-generated code into AFX_INIT_SEG #ifdef AFX_INIT_SEG #pragma code_seg(AFX_INIT_SEG) #endif