📄 olecli2.cpp
字号:
// 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 AFX_OLE2_SEG
#pragma code_seg(AFX_OLE2_SEG)
#endif
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define new DEBUG_NEW
/////////////////////////////////////////////////////////////////////////////
// COleFrameHook Construction & Destruction
COleFrameHook::COleFrameHook(CFrameWnd* pFrameWnd, COleClientItem* pItem)
{
ASSERT_VALID(pItem);
ASSERT_VALID(pFrameWnd);
m_lpActiveObject = NULL;
m_pActiveItem = pItem;
m_pFrameWnd = pFrameWnd;
m_hWnd = pFrameWnd->m_hWnd;
m_bToolBarHidden = FALSE;
m_hAccelTable = NULL;
m_bInModalState = FALSE;
m_nModelessCount = 0;
pFrameWnd->m_pNotifyHook = this; // assume start out hooked
ASSERT_VALID(this);
}
COleFrameHook::~COleFrameHook()
{
if (m_pFrameWnd != NULL)
{
ASSERT_VALID(m_pFrameWnd);
if (m_pFrameWnd->m_pNotifyHook == this)
m_pFrameWnd->m_pNotifyHook = NULL;
}
ASSERT_VALID(this);
}
/////////////////////////////////////////////////////////////////////////////
// COleFrameHook overrides
void COleFrameHook::OnRecalcLayout()
{
ASSERT_VALID(this);
if (m_lpActiveObject == NULL)
return;
// get current border size (without current server control bars)
RECT rectBorder;
m_pFrameWnd->NegotiateBorderSpace(CFrameWnd::borderGet, &rectBorder);
// allow server to resize/move its control bars
m_lpActiveObject->ResizeBorder(&rectBorder, &m_xOleInPlaceFrame,
m_pActiveItem->m_pInPlaceFrame == this);
}
BOOL COleFrameHook::OnDocActivate(BOOL bActive)
{
ASSERT_VALID(this);
if (m_lpActiveObject == NULL)
return TRUE;
// allow server to do document activation related actions
m_lpActiveObject->OnDocWindowActivate(bActive);
// make sure window caption gets updated later
COleFrameHook* pNotifyHook = m_pActiveItem->m_pInPlaceFrame;
pNotifyHook->m_pFrameWnd->DelayUpdateFrameTitle();
if (!bActive)
{
// clear border space
pNotifyHook->m_xOleInPlaceFrame.SetBorderSpace(NULL);
if (m_pActiveItem->m_pInPlaceDoc != NULL)
m_pActiveItem->m_pInPlaceDoc->m_xOleInPlaceFrame.SetBorderSpace(NULL);
// remove the menu hook when the doc is not active
pNotifyHook->m_xOleInPlaceFrame.SetMenu(NULL, NULL, NULL);
// unhook top-level frame if not needed
if (pNotifyHook != this)
{
// shouldn't be removing some other hook
ASSERT(pNotifyHook->m_pFrameWnd->m_pNotifyHook == pNotifyHook);
pNotifyHook->m_pFrameWnd->m_pNotifyHook = NULL;
}
}
else
{
// rehook top-level frame if necessary (no effect if top-level == doc-level)
pNotifyHook->m_pFrameWnd->m_pNotifyHook = pNotifyHook;
}
// don't do default if activating
return bActive;
}
BOOL COleFrameHook::OnContextHelp(BOOL bEnter)
{
ASSERT_VALID(this);
if (m_lpActiveObject == NULL || m_pActiveItem->m_pInPlaceFrame != this)
return TRUE;
// allow all servers to enter/exit context sensitive help mode
return NotifyAllInPlace(bEnter, &COleFrameHook::DoContextSensitiveHelp);
}
/////////////////////////////////////////////////////////////////////////////
// COleFrameHook callbacks for the top-level frame
BOOL COleFrameHook::OnMenuSelect(UINT nItemID, UINT nFlags, HMENU hSysMenu)
{
UNUSED_ALWAYS(nFlags);
UNUSED_ALWAYS(nItemID);
// if we're over a docobject item, we need to reflect messages
COleDocObjectItem* pActiveDocObjectItem = DYNAMIC_DOWNCAST(COleDocObjectItem, m_pActiveItem);
if (pActiveDocObjectItem != NULL)
{
CWnd* pWnd = pActiveDocObjectItem->GetInPlaceWindow();
// if we're popping up a menu, figure out what menu is
// apparing; if it's in the help menu and it's not the
// first element, it's the object's menu.
if (nFlags & MF_POPUP)
{
if (pActiveDocObjectItem->m_pHelpPopupMenu->GetSafeHmenu() ==
hSysMenu)
{
pActiveDocObjectItem->m_bInHelpMenu = (nItemID != 0);
if (pActiveDocObjectItem->m_bInHelpMenu && pWnd != NULL)
{
pWnd->SendMessage(WM_MENUSELECT,
MAKEWPARAM(nItemID, nFlags), (LPARAM) hSysMenu);
return TRUE;
}
}
}
else
{
if (pActiveDocObjectItem->m_bInHelpMenu && pWnd != NULL)
{
pWnd->SendMessage(WM_MENUSELECT,
MAKEWPARAM(nItemID, nFlags), (LPARAM) hSysMenu);
return TRUE;
}
}
}
return FALSE;
}
void COleFrameHook::OnInitMenu(CMenu* pMenu)
{
UNUSED_ALWAYS(pMenu);
// reset the help menu flag when a new menu is opening
COleDocObjectItem* pActiveDocObjectItem = DYNAMIC_DOWNCAST(COleDocObjectItem, m_pActiveItem);
if (pActiveDocObjectItem != NULL)
pActiveDocObjectItem->m_bInHelpMenu = FALSE;
return;
}
BOOL COleFrameHook::OnInitMenuPopup(CMenu* pMenu, int nIndex, BOOL bSysMenu)
{
UNUSED_ALWAYS(nIndex);
if (bSysMenu)
return FALSE;
COleDocObjectItem* pActiveDocObjectItem = DYNAMIC_DOWNCAST(COleDocObjectItem, m_pActiveItem);
if (pActiveDocObjectItem == NULL)
return FALSE;
// if we're popping up a new menu, for the object,
// reflect the message and don't let MFC handle it
// with ON_COMMAND_UI stuff
if (pActiveDocObjectItem->m_bInHelpMenu)
{
CWnd* pWnd = pActiveDocObjectItem->GetInPlaceWindow();
if (pWnd != NULL)
{
pWnd->SendMessage(WM_INITMENUPOPUP, (WPARAM) pMenu->m_hMenu,
MAKELPARAM(nIndex, bSysMenu));
return TRUE;
}
}
return FALSE;
}
BOOL COleFrameHook::OnPreTranslateMessage(MSG* pMsg)
{
ASSERT_VALID(this);
if (m_lpActiveObject == NULL || m_pActiveItem->m_pInPlaceFrame != this)
return FALSE;
// allow server to translate accelerators
if (pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST)
return m_lpActiveObject->TranslateAccelerator(pMsg) == S_OK;
// if we've finally gotten a WM_COMMAND message, make sure
// that it is appropriately reflected to the docobject
if (pMsg->message == WM_COMMAND)
{
COleDocObjectItem* pActiveDocObjectItem = DYNAMIC_DOWNCAST(COleDocObjectItem, m_pActiveItem);
if (pActiveDocObjectItem != NULL)
{
LRESULT lResult = 0;
if (pActiveDocObjectItem->m_bInHelpMenu)
{
CWnd* pWnd = pActiveDocObjectItem->GetInPlaceWindow();
if (pWnd != NULL)
lResult = pWnd->SendMessage(WM_COMMAND, pMsg->wParam, pMsg->lParam);
}
return lResult;
}
}
return FALSE;
}
void COleFrameHook::OnActivate(BOOL bActive)
{
ASSERT_VALID(this);
if (m_lpActiveObject == NULL || m_pActiveItem->m_pInPlaceFrame != this)
return;
if (m_pFrameWnd->IsWindowEnabled())
{
// allow active server to do frame level activation
m_lpActiveObject->OnFrameWindowActivate(bActive);
}
}
void COleFrameHook::OnEnableModeless(BOOL bEnable)
{
ASSERT_VALID(this);
if (m_lpActiveObject == NULL || m_pActiveItem->m_pInPlaceFrame != this)
return;
// allow server to disable/enable modeless dialogs
NotifyAllInPlace(bEnable, &COleFrameHook::DoEnableModeless);
}
BOOL COleFrameHook::OnUpdateFrameTitle()
{
ASSERT_VALID(this);
ASSERT_VALID(m_pActiveItem);
if (m_lpActiveObject == NULL || m_pActiveItem->m_pInPlaceFrame != this)
return FALSE;
return m_pActiveItem->OnUpdateFrameTitle();
}
void COleFrameHook::OnPaletteChanged(CWnd* pFocusWnd)
{
CWnd* pWnd = m_pActiveItem->GetInPlaceWindow();
if (pWnd != NULL)
pWnd->SendMessage(WM_PALETTECHANGED, (WPARAM)pFocusWnd->GetSafeHwnd());
}
BOOL COleFrameHook::OnQueryNewPalette()
{
CWnd* pWnd = m_pActiveItem->GetInPlaceWindow();
if (pWnd != NULL)
return pWnd->SendMessage(WM_QUERYNEWPALETTE);
return FALSE;
}
/////////////////////////////////////////////////////////////////////////////
// Helpers for notifications that have to affect all in-place windows
BOOL COleFrameHook::NotifyAllInPlace(
BOOL bParam, BOOL (COleFrameHook::*pNotifyFunc)(BOOL bParam))
{
ASSERT_VALID(this);
HWND hWndFrame = m_hWnd;
CWinApp* pApp = AfxGetApp();
// no doc manager - no templates
if (pApp->m_pDocManager == NULL)
return TRUE;
// walk all templates in the application
CDocTemplate* pTemplate;
POSITION pos = pApp->m_pDocManager->GetFirstDocTemplatePosition();
while (pos != NULL)
{
pTemplate = pApp->m_pDocManager->GetNextDocTemplate(pos);
ASSERT_VALID(pTemplate);
ASSERT_KINDOF(CDocTemplate, pTemplate);
// walk all documents in the template
POSITION pos2 = pTemplate->GetFirstDocPosition();
while (pos2)
{
COleDocument* pDoc = (COleDocument*)pTemplate->GetNextDoc(pos2);
ASSERT_VALID(pDoc);
if (pDoc->IsKindOf(RUNTIME_CLASS(COleDocument)))
{
// walk all COleClientItem objects in the document
COleClientItem* pItem;
POSITION pos3 = pDoc->GetStartPosition();
while ((pItem = pDoc->GetNextClientItem(pos3)) != NULL)
{
if (pItem->m_pInPlaceFrame != NULL &&
pItem->m_pInPlaceFrame->m_lpActiveObject != NULL &&
pItem->m_pView != NULL &&
AfxIsDescendant(hWndFrame, pItem->m_pView->m_hWnd))
{
// Whew! Found an in-place active item that is
// part of this frame window hierarchy.
COleFrameHook* pNotifyHook = pItem->m_pInPlaceFrame;
if (!(pNotifyHook->*pNotifyFunc)(bParam))
return FALSE;
}
}
}
}
}
return TRUE;
}
BOOL COleFrameHook::DoContextSensitiveHelp(BOOL bEnter)
{
ASSERT_VALID(this);
ASSERT(m_lpActiveObject != NULL);
return !FAILED(m_lpActiveObject->ContextSensitiveHelp(bEnter));
}
BOOL COleFrameHook::DoEnableModeless(BOOL bEnable)
{
ASSERT_VALID(this);
ASSERT(m_lpActiveObject != NULL);
// allow server to enable/disable any modeless windows
if (!bEnable)
{
if (m_nModelessCount++ == 0)
m_lpActiveObject->EnableModeless(FALSE);
}
else
{
if (m_nModelessCount != 0 && --m_nModelessCount == 0)
m_lpActiveObject->EnableModeless(TRUE);
}
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// COleClientItem - default in-place activation implementation
BOOL COleClientItem::CanActivate()
{
// don't allow in-place activations with iconic aspect items
if (m_nDrawAspect == DVASPECT_ICON)
return FALSE;
// if no view has been set, attempt to find suitable one.
// (necessary to get links to embeddings to work correctly)
if (m_pView == NULL)
{
// only use pActivateView if this item is in same document
_AFX_OLE_STATE* pOleState = _afxOleState;
if (pOleState->m_pActivateView != NULL &&
pOleState->m_pActivateView->GetDocument() != GetDocument())
{
pOleState->m_pActivateView = NULL; // not in same document
}
CView* pView = pOleState->m_pActivateView;
if (pView == NULL)
{
// no routing view available - try to use the one with focus
CWnd* pWnd = CWnd::GetFocus();
while (pWnd != NULL && !pWnd->IsKindOf(RUNTIME_CLASS(CView)))
pWnd = pWnd->GetParent();
pView = STATIC_DOWNCAST(CView, pWnd);
if (pView == NULL)
{
// still no routing view available - just use first one
COleDocument* pDoc = GetDocument();
POSITION pos = pDoc->GetFirstViewPosition();
pView = pDoc->GetNextView(pos);
}
}
m_pView = pView;
}
return m_pView->GetSafeHwnd() != NULL;
}
void COleClientItem::OnActivate()
{
ASSERT_VALID(this);
// it is necessary to lock the object when it is in-place
// (without this, a link to an embedding may disconnect unexpectedly)
if (!m_bLocked)
{
OleLockRunning(m_lpObject, TRUE, FALSE);
m_bLocked = TRUE;
}
// notify the item of the state change
if (m_nItemState != activeState)
{
OnChange(OLE_CHANGED_STATE, (DWORD)activeState);
m_nItemState = activeState;
}
}
void COleClientItem::OnActivateUI()
{
ASSERT_VALID(this);
// notify the item of the state change
if (m_nItemState != activeUIState)
{
OnChange(OLE_CHANGED_STATE, (DWORD)activeUIState);
m_nItemState = activeUIState;
}
// the container window must have WS_CLIPCHILDREN set
ASSERT_VALID(m_pView);
m_dwContainerStyle = m_pView->GetStyle();
m_pView->ModifyStyle(0, WS_CLIPCHILDREN);
// cache the server's HWND for later
LPOLEINPLACEOBJECT lpInPlaceObject =
QUERYINTERFACE(m_lpObject, IOleInPlaceObject);
ASSERT(lpInPlaceObject != NULL);
// get the HWND for the in-place active object
HWND hWnd;
if (lpInPlaceObject->GetWindow(&hWnd) != S_OK)
hWnd = NULL;
lpInPlaceObject->Release();
m_hWndServer = hWnd;
// make sure top-level frame is hooked
if (m_pInPlaceFrame != NULL)
{
ASSERT_VALID(m_pInPlaceFrame->m_pFrameWnd);
m_pInPlaceFrame->m_pFrameWnd->m_pNotifyHook = m_pInPlaceFrame;
}
// make sure doc-level frame is hooked
if (m_pInPlaceDoc != NULL)
{
ASSERT_VALID(m_pInPlaceDoc->m_pFrameWnd);
m_pInPlaceDoc->m_pFrameWnd->m_pNotifyHook = m_pInPlaceDoc;
}
}
BOOL COleClientItem::OnShowControlBars(CFrameWnd* pFrameWnd, BOOL bShow)
{
ASSERT_VALID(pFrameWnd);
ASSERT_VALID(this);
// show/hide all bars marked with CBRS_HIDE_INPLACE style
BOOL bResult = FALSE;
if (bShow)
{
POSITION pos = pFrameWnd->m_listControlBars.GetHeadPosition();
while (pos)
{
CControlBar* pBar =
(CControlBar*)pFrameWnd->m_listControlBars.GetNext(pos);
ASSERT_VALID(pBar);
if ((pBar->GetBarStyle() & CBRS_HIDE_INPLACE) &&
(pBar->m_nStateFlags & CControlBar::tempHide))
{
pBar->m_nStateFlags &= ~CControlBar::tempHide;
pFrameWnd->ShowControlBar(pBar, TRUE, TRUE);
bResult = TRUE;
}
}
}
else
{
POSITION pos = pFrameWnd->m_listControlBars.GetHeadPosition();
while (pos)
{
CControlBar* pBar =
(CControlBar*)pFrameWnd->m_listControlBars.GetNext(pos);
ASSERT_VALID(pBar);
if (pBar->IsVisible() && (pBar->GetBarStyle() & CBRS_HIDE_INPLACE))
{
pBar->m_nStateFlags |= CControlBar::tempHide;
pFrameWnd->ShowControlBar(pBar, FALSE, TRUE);
bResult = TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -