📄 olesvr1.cpp
字号:
if (HIWORD(hWnd) != 0)
return hWnd;
// otherwise convert by getting a DC...
HDC hDC = ::GetDC(hWnd);
if (hDC == NULL)
return hWnd;
// then, getting the HWND from the DC...
HWND hWnd32 = ::WindowFromDC(hDC);
if (hWnd32 == NULL)
hWnd32 = hWnd;
// then releasing the DC itself
::ReleaseDC(hWnd, hDC);
return hWnd32; // return full 32-bit HWND
}
BOOL COleServerDoc::ActivateInPlace()
{
ASSERT_VALID(this);
USES_CONVERSION;
LPCOLESTR lpszTitle = NULL;
if (m_lpClientSite == NULL)
return FALSE; // no client-side (may be a link)
// activate already in-place window if currently in-place active
if (m_pInPlaceFrame != NULL)
{
if (m_pInPlaceFrame->m_bUIActive)
{
m_lpClientSite->ShowObject(); // object should get focus
return TRUE;
}
// deactivate in-place session entirely before continuing
OnDeactivate();
}
// fail if already fully open
if (GetFirstFrame()->IsWindowVisible())
return FALSE;
// build object title/name (the container may use this in its caption)
CString strFileType, strTitle;
if (!GetFileTypeString(strFileType))
return FALSE;
AfxFormatString2(strTitle, AFX_IDS_OBJ_TITLE_INPLACE,
AfxGetAppName(), strFileType);
// attempt to get in-place client-site interface
LPOLEINPLACESITE lpInPlaceSite =
QUERYINTERFACE(m_lpClientSite, IOleInPlaceSite);
if (lpInPlaceSite == NULL)
{
// unable to get in-place client site interface
return FALSE;
}
// see if the container wants to go in-place right now
if (lpInPlaceSite->CanInPlaceActivate() != S_OK)
goto ReleaseAndFail;
// start activation sequence...
if (lpInPlaceSite->OnInPlaceActivate() != S_OK)
goto ReleaseAndFail;
// we'll need the parent window to create the COleIPFrameWnd
HWND hWnd;
VERIFY(lpInPlaceSite->GetWindow(&hWnd) == S_OK);
CWnd* pParentWnd;
pParentWnd = CWnd::FromHandle(hWnd);
// create the inplace frame window
COleIPFrameWnd* pFrameWnd;
pFrameWnd = CreateInPlaceFrame(pParentWnd);
if (pFrameWnd == NULL)
{
ASSERT(lpInPlaceSite != NULL);
lpInPlaceSite->OnInPlaceDeactivate();
goto ReleaseAndFail;
}
ASSERT(pFrameWnd->GetParent() == pParentWnd);
m_pInPlaceFrame = pFrameWnd;
// send activate notification.
if (lpInPlaceSite->OnUIActivate() != S_OK)
goto DestroyFrameAndFail;
// need to get frame & doc window interfaces as well as other info
RECT rcPosRect, rcClipRect;
if (lpInPlaceSite->GetWindowContext(
&pFrameWnd->m_lpFrame, &pFrameWnd->m_lpDocFrame,
&rcPosRect, &rcClipRect, &pFrameWnd->m_frameInfo) != S_OK)
{
goto DeactivateUIAndFail;
}
ASSERT(pFrameWnd->m_lpFrame != NULL);
// setup the shared menu
if (!pFrameWnd->BuildSharedMenu())
goto DeactivateUIAndFail;
// allow server to install frame controls in container
VERIFY(pFrameWnd->m_lpFrame->GetWindow(&hWnd) == S_OK);
// some containers (Works 4.0, for example) return only the lower
// 16-bits of the HWND and that confuses us; to work around this
// we convert the 16-bit HWND into the full 32-bit HWND.
hWnd = _AfxGetWindow32(hWnd);
pFrameWnd->m_pMainFrame = new COleCntrFrameWnd(pFrameWnd);
pFrameWnd->m_pMainFrame->Attach(hWnd);
if (pFrameWnd->m_lpDocFrame != NULL)
{
HWND hWndDocument;
VERIFY(pFrameWnd->m_lpDocFrame->GetWindow(&hWndDocument) == S_OK);
if (hWndDocument != hWnd)
{
pFrameWnd->m_pDocFrame = new COleCntrFrameWnd(pFrameWnd);
pFrameWnd->m_pDocFrame->Attach(hWndDocument);
}
else
{
RELEASE(pFrameWnd->m_lpDocFrame);
pFrameWnd->m_lpDocFrame = NULL;
}
}
// update zoom factor information before creating control bars
//WINBUG: some clients send an empty rectangle and expect the
// server to use the ClipRect for the PosRect
if (IsRectEmpty(&rcPosRect))
pFrameWnd->m_rectPos.CopyRect(&rcClipRect);
else
pFrameWnd->m_rectPos.CopyRect(&rcPosRect);
pFrameWnd->m_rectClip.CopyRect(&rcClipRect);
if (!pFrameWnd->OnCreateControlBars(pFrameWnd->m_pMainFrame,
pFrameWnd->m_pDocFrame))
{
goto DeactivateUIAndFail;
}
// resize the window to match the object
//WINBUG: some clients send an empty rectangle and expect the
// server to use the ClipRect for the PosRect
if (IsRectEmpty(&rcPosRect))
OnSetItemRects(&rcClipRect, &rcClipRect);
else
OnSetItemRects(&rcPosRect, &rcClipRect);
// set the active object
ASSERT(pFrameWnd->m_lpFrame != NULL);
LPOLEINPLACEACTIVEOBJECT lpActiveObject;
lpActiveObject = (LPOLEINPLACEACTIVEOBJECT)
GetInterface(&IID_IOleInPlaceActiveObject);
lpszTitle = T2COLE(strTitle);
pFrameWnd->m_lpFrame->SetActiveObject(lpActiveObject, lpszTitle);
if (pFrameWnd->m_lpDocFrame != NULL)
pFrameWnd->m_lpDocFrame->SetActiveObject(lpActiveObject, lpszTitle);
// add frame & document level frame controls
ASSERT(m_pInPlaceFrame->m_lpFrame != NULL);
OnShowControlBars(m_pInPlaceFrame->m_pMainFrame, TRUE);
if (m_pInPlaceFrame->m_lpDocFrame != NULL)
OnShowControlBars(m_pInPlaceFrame->m_pDocFrame, TRUE);
// show any hidden modeless dialogs as well...
m_pInPlaceFrame->ShowOwnedWindows(TRUE);
// attempt toolbar negotiation
OnResizeBorder(NULL, pFrameWnd->m_lpFrame, TRUE);
if (pFrameWnd->m_lpDocFrame != NULL)
OnResizeBorder(NULL, pFrameWnd->m_lpDocFrame, FALSE);
// install the menu (also installs a hook which forwards messages from
// the menu to the inplace frame window)
pFrameWnd->m_lpFrame->SetMenu(pFrameWnd->m_hSharedMenu,
pFrameWnd->m_hOleMenu, pFrameWnd->m_hWnd);
// make sure object is scrolled into view
m_lpClientSite->ShowObject(); // object should get focus
// finally -- show the inplace frame window and set focus
pFrameWnd->ShowWindow(SW_SHOW);
pFrameWnd->SetFocus();
pFrameWnd->UpdateWindow();
UpdateVisibleLock(TRUE, FALSE);
// allow the main window to be set
OnFrameWindowActivate(TRUE);
pFrameWnd->m_bUIActive = TRUE;
// cleanup and return
lpInPlaceSite->Release();
return TRUE;
DeactivateUIAndFail:
ASSERT(lpInPlaceSite != NULL);
lpInPlaceSite->OnUIDeactivate(FALSE);
DestroyFrameAndFail:
if (m_pInPlaceFrame != NULL)
{
ASSERT(pFrameWnd != NULL);
DestroyInPlaceFrame(pFrameWnd);
m_pInPlaceFrame = NULL;
// also need to send OnInPlaceDeactivate notification
ASSERT(lpInPlaceSite != NULL);
lpInPlaceSite->OnInPlaceDeactivate();
}
ReleaseAndFail:
ASSERT(lpInPlaceSite != NULL);
lpInPlaceSite->Release();
return FALSE;
}
COleIPFrameWnd* COleServerDoc::CreateInPlaceFrame(CWnd* pParentWnd)
{
ASSERT_VALID(this);
ASSERT_VALID(pParentWnd);
// get runtime class from the doc template
CDocTemplate* pTemplate = GetDocTemplate();
ASSERT_VALID(pTemplate);
// use existing view if possible
CWnd* pViewParent = NULL;
CView* pView = NULL;
CFrameWnd* pFrame = GetFirstFrame();
if (pFrame != NULL)
{
pView = (CView*)pFrame->GetDescendantWindow(AFX_IDW_PANE_FIRST, TRUE);
if (pView != NULL)
{
ASSERT_KINDOF(CView, pView);
pViewParent = pView->GetParent();
m_dwOrigStyle = pView->GetStyle();
m_dwOrigStyleEx = pView->GetExStyle();
}
}
// create the frame from the template
COleIPFrameWnd* pFrameWnd = (COleIPFrameWnd*)
pTemplate->CreateOleFrame(pParentWnd, this, pView == NULL);
if (pFrameWnd == NULL)
return NULL;
// connect the view to the frame window, if necessary
if (pView != NULL)
{
ConnectView(pFrameWnd, pView);
pView->ModifyStyleEx(WS_EX_CLIENTEDGE, 0, SWP_DRAWFRAME);
}
// remember original parent window for deactivate
m_pOrigParent = pViewParent;
// send OnInitialUpdate if new view was created
if (pView == NULL)
pTemplate->InitialUpdateFrame(pFrameWnd, this, FALSE);
// verify the type
ASSERT_VALID(pFrameWnd);
ASSERT_KINDOF(COleIPFrameWnd, pFrameWnd);
return pFrameWnd;
}
void COleServerDoc::DestroyInPlaceFrame(COleIPFrameWnd* pFrameWnd)
{
ASSERT_VALID(this);
ASSERT_VALID(pFrameWnd);
// connect view to original, if existing view was used
if (m_pOrigParent != NULL)
{
CView* pView = (CView*)pFrameWnd->GetDescendantWindow(
AFX_IDW_PANE_FIRST, TRUE);
ASSERT_VALID(pView);
// leaving the focus on an MDI child or one of its child windows
// causes Windows to get confused when the child window is
// destroyed, not to mention the fact that the focus will be
// out of sync with activation.
if (::GetFocus() == pView->m_hWnd)
{
// move focus to somewhere safe
HWND hWnd = ::GetParent(pFrameWnd->m_hWnd);
if (hWnd != NULL)
::SetFocus(hWnd);
// check again
if (::GetFocus() == pView->m_hWnd)
SetFocus(NULL); // last ditch effort
}
ConnectView(m_pOrigParent, pView);
m_pOrigParent = NULL;
// remove any scrollbars added because of in-place activation
if ((m_dwOrigStyle & (WS_HSCROLL|WS_VSCROLL)) == 0 &&
(pView->GetStyle() & (WS_HSCROLL|WS_VSCROLL)) != 0)
{
::SetScrollRange(pView->m_hWnd, SB_HORZ, 0, 0, TRUE);
::SetScrollRange(pView->m_hWnd, SB_VERT, 0, 0, TRUE);
}
// restore old 3D style
pView->ModifyStyleEx(0, m_dwOrigStyleEx & WS_EX_CLIENTEDGE,
SWP_DRAWFRAME);
// force recalc layout on splitter window
CSplitterWnd* pSplitter = CView::GetParentSplitter(pView, TRUE);
if (pSplitter != NULL)
pSplitter->RecalcLayout();
}
// no active view or document during destroy
pFrameWnd->SetActiveView(NULL);
// destroy in-place frame window
pFrameWnd->DestroyWindow();
}
void COleServerDoc::ConnectView(CWnd* pParentWnd, CView* pView)
{
ASSERT_VALID(this);
ASSERT_VALID(pParentWnd);
ASSERT_VALID(pView);
// move the view to the new parent
pView->SetParent(pParentWnd);
// Note: The currently active view on the original frame window is
// kept active, because some controls, especially Windows controls,
// continue to send notification messages to the original parent
// window of the control. So, the original frame window is kept
// alive with the original active view pointer intact, such that
// these notification messages do not get lost.
// set the active view of the new frame to newly moved view
CFrameWnd* pFrameWnd = pParentWnd->IsFrameWnd() ?
(CFrameWnd*)pParentWnd : pParentWnd->GetParentFrame();
pFrameWnd->SetActiveView(pView, FALSE);
pFrameWnd->RecalcLayout();
}
void COleServerDoc::OnFrameWindowActivate(BOOL bActivate)
{
ASSERT_VALID(this);
CFrameWnd* pFrameWnd = m_pInPlaceFrame;
ASSERT_VALID(pFrameWnd);
CWinThread* pThread = AfxGetThread();
if (bActivate)
{
// activating -- so set the main window
pThread->m_pActiveWnd = pFrameWnd;
// send activation notification messages
pFrameWnd->SendMessage(WM_ACTIVATEAPP, (WPARAM)TRUE);
pFrameWnd->SendMessage(WM_ACTIVATE, WA_ACTIVE);
}
else if (pFrameWnd == pThread->m_pActiveWnd)
{
// send deactivation notification messages
pFrameWnd->SendMessage(WM_ACTIVATEAPP, (WPARAM)FALSE);
pFrameWnd->SendMessage(WM_ACTIVATE, WA_INACTIVE);
// simulate deactivation notification messages
CView* pActiveView = pFrameWnd->GetActiveView();
if (pActiveView != NULL)
pActiveView->OnActivateView(FALSE, pActiveView, pActiveView);
// deactivating and was previously active -- reset the main window
pThread->m_pActiveWnd = NULL;
}
}
void COleServerDoc::OnDocWindowActivate(BOOL bActivate)
{
ASSERT_VALID(this);
CWinThread* pThread = AfxGetApp();
COleIPFrameWnd* pFrameWnd = m_pInPlaceFrame;
if (bActivate)
{
// attach frame windows back in the permanent map
pFrameWnd->m_pMainFrame->Attach(pFrameWnd->m_pMainFrame->Detach());
if (pFrameWnd->m_pDocFrame != NULL)
pFrameWnd->m_pDocFrame->Attach(pFrameWnd->m_pDocFrame->Detach());
// set active main window
pThread->m_pActiveWnd = pFrameWnd;
// show frame level controls
OnShowControlBars(pFrameWnd->m_pMainFrame, TRUE);
pFrameWnd->ShowOwnedWindows(TRUE);
// attempt toolbar negotiation
OnResizeBorder(NULL, pFrameWnd->m_lpFrame, TRUE);
// install the menu (also installs a hook which forwards messages from
// the menu to the inplace frame window)
pFrameWnd->m_lpFrame->SetMenu(
pFrameWnd->m_hSharedMenu, pFrameWnd->m_hOleMenu,
pFrameWnd->m_hWnd);
// set focus to the frame (it will probably set focus to the view)
// (by simulating normal application activate messages)
pFrameWnd->SendMessage(WM_ACTIVATE, WA_ACTIVE);
}
else
{
// clear active window for app if this object is active
if (pThread->m_pActiveWnd == pFrameWnd)
pThread->m_pActiveWnd = NULL;
// hide frame level controls -- this does not destroy them
pFrameWnd->ShowOwnedWindows(FALSE);
OnShowControlBars(pFrameWnd->m_pMainFrame, FALSE);
// attempt toolbar negotiation
OnResizeBorder(NULL, pFrameWnd->m_lpFrame, TRUE);
// simulate deactivation notification messages
CView* pActiveView = pFrameWnd->GetActiveView();
if (pActiveView != NULL)
pActiveView->OnActivateView(FALSE, pActiveView, pActiveView);
pFrameWnd->SendMessage(WM_ACTIVATE, WA_INACTIVE);
// set the m_hWnd members, but remove them from the maps
pFrameWnd->m_pMainFrame->m_hWnd = pFrameWnd->m_pMainFrame->Detach();
if (pFrameWnd->m_pDocFrame != NULL)
pFrameWnd->m_pDocFrame->m_hWnd = pFrameWnd->m_pDocFrame->Detach();
}
}
void COleServerDoc::OnShowControlBars(CFrameWnd* pFrameWnd, BOOL bShow)
{
ASSERT_VALID(this);
ASSERT(pFrameWnd == m_pInPlaceFrame->m_pMainFrame ||
pFrameWnd == m_pInPlaceFrame->m_pDocFrame);
ASSERT_VALID(pFrameWnd);
// show/hide all control bars
POSITION pos = pFrameWnd->m_listControlBars.GetHeadPosition();
while (pos != NULL)
{
// show/hide the next control bar
CControlBar* pBar =
(CControlBar*)pFrameWnd->m_listControlBars.GetNext(pos);
ASSERT_VALID(pBar);
if (bShow)
{
if (pBar->m_nStateFlags & CControlBar::tempHide)
{
pBar->m_nStateFlags &= ~CControlBar::tempHide;
pFrameWnd->ShowControlBar(pBar, bShow, TRUE);
}
}
else
{
if (pBar->IsVisible() && !pBar->IsFloating())
{
pBar->m_nStateFlags |= CControlBar::tempHide;
pFrameWnd->ShowControlBar(pBar, bShow, TRUE);
}
}
}
}
void COleServerDoc::OnResizeBorder(
LPCRECT lpRectBorder, LPOLEINPLACEUIWINDOW lpUIWindow, BOOL bFrame)
{
ASSERT_VALID(this);
ASSERT(lpRectBorder == NULL ||
AfxIsValidAddress(lpRectBorder, sizeof(RECT), FALSE));
ASSERT(lpUIWindow != NULL);
// use IOleInPlaceUIWindow::GetBorder if no border given
CRect rectBorder;
if (lpRectBorder != NULL)
{
// use border space passed in
rectBorder.CopyRect(lpRectBorder);
}
else
{
// GetBorderSpace may fail (WinWord6, for example)
if (lpUIWindow->GetBorder(&rectBorder) != S_OK)
{
// in that case, always call SetBorderSpace(NULL), but
// ignore the return value.
lpUIWindow->SetBorderSpace(NULL);
return;
}
}
// get CWnd* for the OLE window
CFrameWnd* pFrameWnd = bFrame ?
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -