2007-12-10 20:53:52 +00:00

4313 lines
144 KiB
C++

/***************************************************************************
* DSOFCONTROL.CPP
*
* CDsoFramerControl: The Base Control
*
* Copyright ©1999-2004; Microsoft Corporation. All rights reserved.
* Written by Microsoft Developer Support Office Integration (PSS DSOI)
*
* This code is provided via KB 311765 as a sample. It is not a formal
* product and has not been tested with all containers or servers. Use it
* for educational purposes only. See the EULA.TXT file included in the
* KB download for full terms of use and restrictions.
*
* THIS CODE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
* EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
*
***************************************************************************/
#include "dsoframer.h"
////////////////////////////////////////////////////////////////////////
// CDsoFramerControl - The Main Control Class
//
// Serves as a base for the ActiveX Document site object which will do
// the actual embedding.
//
CDsoFramerControl::CDsoFramerControl(LPUNKNOWN punk)
{
ODS("CDsoFramerControl::CDsoFramerControl\n");
m_pOuterUnknown = ((punk) ? punk : (IUnknown*)&m_xInternalUnknown);
}
CDsoFramerControl::~CDsoFramerControl(void)
{
ODS("CDsoFramerControl::~CDsoFramerControl\n");
SAFE_RELEASE_INTERFACE(m_ptiDispType);
SAFE_RELEASE_INTERFACE(m_pClientSite);
SAFE_RELEASE_INTERFACE(m_pControlSite);
SAFE_RELEASE_INTERFACE(m_pInPlaceSite);
SAFE_RELEASE_INTERFACE(m_pInPlaceFrame);
SAFE_RELEASE_INTERFACE(m_pInPlaceUIWindow);
SAFE_RELEASE_INTERFACE(m_pViewAdviseSink);
SAFE_RELEASE_INTERFACE(m_pOleAdviseHolder);
SAFE_RELEASE_INTERFACE(m_pDataAdviseHolder);
SAFE_RELEASE_INTERFACE(m_dispEvents);
SAFE_RELEASE_INTERFACE(m_pOleStorage);
SAFE_FREESTRING(m_pwszHostName);
}
////////////////////////////////////////////////////////////////////////
// CDsoFramerControl::InitializeNewInstance
//
// Sets up the inital state for the control. Any other member variable
// not set here will be NULL/FALSE thanks to zero-init in MemAlloc.
//
STDMETHODIMP CDsoFramerControl::InitializeNewInstance()
{
m_clrBorderColor = 0x80000010; // System Button Shadow Color
m_clrBackColor = 0x80000005; // System Window Background Color
m_clrForeColor = 0x80000008; // System Window Text Color
m_clrTBarColor = 0x8000000D; // System Highlight Color
m_clrTBarTextColor = 0x8000000E; // System Highlight Text Color
m_fBorderStyle = dsoBorderFlat;
m_fShowTitlebar = TRUE;
m_fShowToolbars = TRUE;
m_fShowMenuBar = TRUE;
m_wFileMenuFlags = 0xFFFF; // All items are "enabled" by default
m_Size.cx = 240;
m_Size.cy = 240;
return S_OK;
}
////////////////////////////////////////////////////////////////////////
// CDsoFramerControl::InPlaceActivate
//
// Does all the work in-place activating and/or ui activating the
// control when asked to do so. Sets up the main control window, the
// needed interfaces, and (if not in design) subclasses the main top-level
// window we can monitor messages that must be forwarded to an ip active
// DocObject when we have one loaded.
//
STDMETHODIMP CDsoFramerControl::InPlaceActivate(LONG lVerb)
{
HRESULT hr;
SIZEL sizel;
TRACE1("CDsoFramerControl::InPlaceActivate - %d\n", lVerb);
// if we don't have a client site, then there's not much to do.
if (!m_pClientSite) return S_OK;
// get an InPlace site pointer.
if (NULL == m_pInPlaceSite)
{
hr = m_pClientSite->QueryInterface(IID_IOleInPlaceSite, (void **)&m_pInPlaceSite);
RETURN_ON_FAILURE(hr);
}
// if we're not already active, go and do it.
if (!m_fInPlaceActive)
{
OLEINPLACEFRAMEINFO InPlaceFrameInfo;
RECT rcPos, rcClip;
hr = m_pInPlaceSite->CanInPlaceActivate();
if (hr != S_OK){ if (!FAILED(hr)) hr = E_FAIL; goto cleanup;}
// if we are here, then we have permission to go in-place active.
// now, announce our intentions to actually go ahead and do this.
hr = m_pInPlaceSite->OnInPlaceActivate();
GOTO_ON_FAILURE(hr, cleanup);
// if we're here, we're ready to go in-place active. we just need
// to set up some flags, and then create the window [if we have one]
m_fInPlaceActive = TRUE;
// we need to get some information about our location in the parent
// window, as well as some information about the parent
hr = m_pInPlaceSite->GetWindow(&m_hwndParent);
if (FAILED(hr) || !IsWindow(m_hwndParent))
{
hr = OLE_E_INVALIDHWND;
goto cleanup;
}
InPlaceFrameInfo.cb = sizeof(OLEINPLACEFRAMEINFO);
hr = m_pInPlaceSite->GetWindowContext(&m_pInPlaceFrame, &m_pInPlaceUIWindow, &rcPos, &rcClip, &InPlaceFrameInfo);
GOTO_ON_FAILURE(hr, cleanup);
// make sure we'll display ourselves in the correct location with the correct size
sizel.cx = rcPos.right - rcPos.left;
sizel.cy = rcPos.bottom - rcPos.top;
m_Size = sizel;
m_xOleInplaceObject.SetObjectRects(&rcPos, &rcClip);
// finally, create our window if we have to!
if (NULL == m_hwnd)
{
WNDCLASS wndclass;
EnterCriticalSection(&v_csecThreadSynch);
// if class info has not yet been registered, need to do that now...
if (GetClassInfo(v_hModule, "DSOFramerOCXWnd", &wndclass) == 0)
{
memset(&wndclass, 0, sizeof(WNDCLASS));
wndclass.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS;
wndclass.lpfnWndProc = CDsoFramerControl::ControlWindowProc;
wndclass.hInstance = v_hModule;
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.lpszClassName = "DSOFramerOCXWnd";
RegisterClass(&wndclass);
}
// create the window with the extent size and position...
m_hwnd = CreateWindowEx(0, "DSOFramerOCXWnd", NULL,
WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE,
rcPos.left, rcPos.top, m_Size.cx, m_Size.cy,
m_hwndParent, NULL, v_hModule, NULL);
if (m_hwnd) SetWindowLong(m_hwnd, GWL_USERDATA, (LONG)this);
LeaveCriticalSection(&v_csecThreadSynch);
if (!m_hwnd) {hr = E_FAIL; goto cleanup;}
}
// finally, tell the host of this
m_pClientSite->ShowObject();
}
// if we're not inplace visible yet, do so now.
if (!m_fInPlaceVisible)
SetInPlaceVisible(TRUE);
// if we were asked to UIActivate, and we currently are not, do so!
if ((lVerb == OLEIVERB_PRIMARY ||
lVerb == OLEIVERB_UIACTIVATE) && (!m_fUIActive))
{
// It is not typical to UI activate ocx during design mode, but if it happens and host
// has not customized the hook policy, let's switch to delay set so that we don't
// accidently hook the VS/VB IDE designer window.
if (FRunningInDesignMode() && (m_lHookPolicy == 0))
m_lHookPolicy = dsoSetOnFirstOpen;
// if we don't have it already, hook top-level parent window when we go
// ui active; this is needed to track WM_ACTIVATEAPP and other critical messages
// needed by ole docobjs....
if ((m_pHookManager == NULL) && FUseFrameHook() && !FDelayFrameHookSet())
{
m_pHookManager = CDsoFrameHookManager::RegisterFramerControl(m_hwndParent, m_hwnd);
if (!m_pHookManager)
{
ODS(" ** UIActivate FAILED (DSO_E_FRAMEHOOKFAILED)\n");
return ProvideErrorInfo(DSO_E_FRAMEHOOKFAILED);
}
}
// Now UI activate the control for the host. This implies taking focus and
// setting up the control as the current active object...
hr = UIActivate(FALSE);
}
// Setup drop file support (but only when there is no current embedding)...
if (m_pDocObjFrame == NULL)
EnableDropFile(TRUE);
return S_OK; // be-de-be-de-be-de that's all folks!
cleanup:
// something catastrophic happened [or, at least something bad].
// die a horrible fiery mangled painful death...
TRACE1(" *** InPlaceActivate FAILED (hr=0x%X) ***\n", hr);
m_fInPlaceActive = FALSE;
return hr;
}
////////////////////////////////////////////////////////////////////////
// CDsoFramerControl::UIActivate
//
// Make sure our control is UI Active and set as ActiveObject for host.
//
STDMETHODIMP CDsoFramerControl::UIActivate(BOOL fForceUIActive)
{
HRESULT hr = S_FALSE;
TRACE1("CDsoFramerControl::UIActivate(fForceUIActive=%d)\n", fForceUIActive);
// We can't do anything if we aren't inplace active and visible!
if (!(m_fInPlaceActive) || !(m_fInPlaceVisible))
return E_UNEXPECTED;
// If we are not already UI active or are being asked to force it, do the call
if ((!(m_fUIActive) || (fForceUIActive)) && (m_pInPlaceSite))
{
m_fUIActive = TRUE;
// inform the container of our intent
hr = m_pInPlaceSite->OnUIActivate();
if (SUCCEEDED(hr) || (fForceUIActive))
{
// take the focus [which is what UI Activation is all about !]
SetFocus(m_hwnd);
// set ourselves up in the host.
if (m_pInPlaceFrame)
m_pInPlaceFrame->SetActiveObject((IOleInPlaceActiveObject*)&m_xOleInplaceActiveObject, NULL);
if (m_pInPlaceUIWindow)
m_pInPlaceUIWindow->SetActiveObject((IOleInPlaceActiveObject*)&m_xOleInplaceActiveObject, NULL);
// we have to explicitly say we don't wany any border space.
if (m_pInPlaceFrame)
m_pInPlaceFrame->SetBorderSpace(NULL);
if (m_pInPlaceUIWindow)
m_pInPlaceUIWindow->SetBorderSpace(NULL);
// Ensure docobj component state is active as well...
if (!m_fComponentActive)
{
// Tell manager we are the active component now...
if (m_pHookManager) m_pHookManager->SetActiveComponent(m_hwnd);
else OnComponentActivationChange(TRUE);
}
}
}
return hr;
}
////////////////////////////////////////////////////////////////////////
// CDsoFramerControl::SetInPlaceVisible
//
// Make sure our control is visible or not (does not actually take ui
// focus, that should be done in InPlaceActivate).
//
STDMETHODIMP_(void) CDsoFramerControl::SetInPlaceVisible(BOOL fShow)
{
BOOL fVisible;
m_fInPlaceVisible = fShow;
// don't do anything if we don't have a window. otherwise, set it
if (m_hwnd)
{
fVisible = IsWindowVisible(m_hwnd);
if (fVisible && !fShow)
ShowWindow(m_hwnd, SW_HIDE);
else if (!fVisible && fShow)
ShowWindow(m_hwnd, SW_SHOWNA);
}
}
////////////////////////////////////////////////////////////////////////
// CDsoFramerControl::OnDraw
//
// Drawing is largely limited to border and titlebar, except when in
// design mode. We don't do any background painting to avoid paint problems
// when we have an ui active DocObject. It should do any painting for us.
//
STDMETHODIMP_(void) CDsoFramerControl::OnDraw(DWORD dvAspect, HDC hdcDraw, LPRECT prcBounds, LPRECT prcWBounds, HDC hicTargetDev, BOOL fOptimize)
{
COLORREF clrBackground, clrForeground, clrBorder, clrT;
HBRUSH hbshBackground, hbshBorder;
HFONT hfontText, hfontOld;
HPALETTE hpal, hpalOld;
LOGFONT lfText = {-11,0,0,0,FW_NORMAL,0,0,0,0,0,0,0,FF_SWISS, "Tahoma"};
RECT rc, rcT;
int iTxtMode, iMapMode;
// Copy out the bounding rect...
CopyRect(&rc, prcBounds);
// On 256 color systems, we may need a palette...
if ((GetDeviceCaps(hdcDraw, RASTERCAPS) & RC_PALETTE) &&
((GetDeviceCaps(hdcDraw, BITSPIXEL) * GetDeviceCaps(hdcDraw, PLANES)) == 8))
{
hpal = CreateHalftonePalette(hdcDraw);
hpalOld = SelectPalette(hdcDraw, hpal, TRUE);
RealizePalette(hdcDraw);
}
else hpal = NULL;
// Translate the OLE_COLOR values to a matching COLORREF in palette...
OleTranslateColor(m_clrBackColor, hpal, &clrBackground);
OleTranslateColor(m_clrForeColor, hpal, &clrForeground);
OleTranslateColor(m_clrBorderColor, hpal, &clrBorder);
// Create the resources we need for drawing and setting up the DC...
hbshBackground = CreateSolidBrush(clrBackground);
hbshBorder = CreateSolidBrush(clrBorder);
hfontText = CreateFontIndirect(&lfText);
hfontOld = (HFONT)SelectObject(hdcDraw, hfontText);
iTxtMode = SetBkMode(hdcDraw, TRANSPARENT);
iMapMode = SetMapMode(hdcDraw, MM_TEXT);
// Based on the choosen border style, draw the border and deflate the
// drawing rect accordingly...
switch (m_fBorderStyle)
{
case 1:
{
HBRUSH hbT = GetSysColorBrush(COLOR_BTNFACE);
FrameRect(hdcDraw, &rc, hbshBorder); InflateRect(&rc, -1, -1);
FrameRect(hdcDraw, &rc, hbT); InflateRect(&rc, -1, -1);
FrameRect(hdcDraw, &rc, hbshBorder); InflateRect(&rc, -1, -1);
}
break;
case 2:
DrawEdge(hdcDraw, &rc, EDGE_SUNKEN, BF_RECT);
InflateRect(&rc, -2, -2);
break;
case 3:
DrawEdge(hdcDraw, &rc, BDR_SUNKENOUTER, BF_RECT);
InflateRect(&rc, -1, -1);
break;
//default: no border...
}
// Draw the titlebar if visible...
if (m_fShowTitlebar)
{
COLORREF clrTitlebar, clrTitlebarText;
HBRUSH hbshTitlebar, hbshT;
LPWSTR pwszDCaption = NULL;
LPWSTR pwszROCaption = NULL;
LPWSTR pwszCaption = ((m_bstrCustomCaption) ?
m_bstrCustomCaption : L"KB311765: Office Framer Control Sample");
CopyRect(&rcT, &rc);
rcT.bottom = rcT.top + 21;
OleTranslateColor(m_clrTBarColor, hpal, &clrTitlebar);
OleTranslateColor(m_clrTBarTextColor, hpal, &clrTitlebarText);
hbshTitlebar = CreateSolidBrush(clrTitlebar);
FillRect(hdcDraw, &rcT, hbshTitlebar);
DrawIconEx(hdcDraw, rcT.left+2, rcT.top+2, v_icoOffDocIcon, 16, 16, 0, NULL, DI_NORMAL);
clrT = SetTextColor(hdcDraw, clrTitlebarText);
rcT.left += 22;
// If we have an embedded object, check to see if it is an open doc and
// append the name to the titlebar. Also append "Read-Only" string if file
// was open in read-only mode.
if (m_pDocObjFrame)
{
if ((pwszDCaption = (LPWSTR)m_pDocObjFrame->GetSourceDocName()) != NULL)
{
LPCWSTR pwszCat[2] = {L" - ", pwszDCaption};
pwszDCaption = DsoCopyStringCatEx(pwszCaption, 2, pwszCat);
pwszCaption = pwszDCaption;
}
if (m_pDocObjFrame->IsReadOnly())
{
pwszROCaption = DsoCopyStringCat(pwszCaption, L" (Read-Only)");
pwszCaption = pwszROCaption;
}
}
// Draw out the custom titlebar caption in Unicode if on NT/XP OS, since
// a custom caption may have non-ANSI characters...
FDrawText(hdcDraw, pwszCaption, &rcT, DT_VCENTER|DT_SINGLELINE);
// Cleanup temp strings...
if (pwszROCaption) DsoMemFree(pwszROCaption);
if (pwszDCaption) DsoMemFree(pwszDCaption);
CopyRect(&rcT, &rc);
rcT.bottom = rcT.top + 21;
rcT.top = rcT.bottom - 1;
hbshT = GetSysColorBrush(COLOR_BTNSHADOW);
FillRect(hdcDraw, &rcT, hbshT);
SetTextColor(hdcDraw, clrT);
DeleteObject(hbshTitlebar);
}
// Draw menu bar if visible...
if (m_fShowMenuBar)
{
GetSizeRectForMenuBar(prcBounds, &rcT);
FillRect(hdcDraw, &rcT, GetSysColorBrush(COLOR_BTNFACE));
// When in design mode, we just draw placeholder...
if (FRunningInDesignMode())
{
clrT = SetTextColor(hdcDraw, GetSysColor(COLOR_BTNSHADOW));
DrawText(hdcDraw, "Menu Bar", -1, &rcT, DT_SINGLELINE|DT_VCENTER|DT_CENTER);
SetTextColor(hdcDraw, clrT);
}
else
{
HMENU hCurMenu;
CHAR szbuf[DSO_MAX_MENUNAME_LENGTH];
UINT i, yTop, yBottom, xLast, xNext;
SIZE ptMItem; RECT rcMDraw;
BOOL fSelected;
DWORD dwDTFlags = (DT_SINGLELINE | DT_VCENTER);
// Get the current menu and setup to draw the number of items in it...
if (hCurMenu = GetActivePopupMenu())
{
yTop = rcT.top + 3; yBottom = rcT.bottom - 3; xLast = rcT.left + 2;
if (hCurMenu == m_hmenuFilePopup)
{ m_cMenuItems = 1; }
else
{
if ((m_cMenuItems = (USHORT)GetMenuItemCount(hCurMenu)) > DSO_MAX_MENUITEMS)
m_cMenuItems = DSO_MAX_MENUITEMS;
}
// If we are on an OS that supports it, hide the prefix when we are not UI active
// or if the host has disabled menu accelerators for this instance...
if (v_fWindows2KPlus && (!(m_fUIActive) || (m_fDisableMenuAccel)))
dwDTFlags |= DT_HIDEPREFIX;
// For each item in the menu, get the menu name and draw it to the
// menu bar. We need to calculate the size taken by the font used and
// store the information in an array used by mouse move handler to
// determine which menu item the user is over...
for (i = 0; i < m_cMenuItems; i++)
{
szbuf[0] = '\0';
if (i == 0) lstrcpy(szbuf, "&File");
else GetMenuString(hCurMenu, i, szbuf, DSO_MAX_MENUNAME_LENGTH, MF_BYPOSITION);
GetTextExtentPoint32(hdcDraw, szbuf, lstrlen(szbuf), &ptMItem);
xNext = (xLast + ptMItem.cx + 2);
if (xNext > (UINT)(rcT.right)){ m_cMenuItems = (USHORT)i; break; }
SetRect(&rcMDraw, xLast, yTop, xNext, yBottom);
if (fOptimize)
CopyRect(&m_rgrcMenuItems[i], &rcMDraw);
// If user is over this particular item, we draw it as selected...
fSelected = ((m_wSelMenuItem) && (i == (UINT)(m_wSelMenuItem - 1)));
if (fSelected)
{
FillRect(hdcDraw, &rcMDraw, GetSysColorBrush(COLOR_HIGHLIGHT));
clrT = SetTextColor(hdcDraw, GetSysColor(COLOR_HIGHLIGHTTEXT));
}
rcMDraw.left += 4;
DrawText(hdcDraw, szbuf, lstrlen(szbuf), &rcMDraw, dwDTFlags);
if (fSelected)
SetTextColor(hdcDraw, clrT);
xLast = xNext + 2;
}
}
}
rcT.top = rcT.bottom - 1; // Draw a line to separate menu from workspace...
FillRect(hdcDraw, &rcT, GetSysColorBrush(COLOR_BTNSHADOW));
}
// Fill in the background (but only if there is no active object)...
if (!m_pDocObjFrame)
{
GetSizeRectForDocument(prcBounds, &rcT);
FillRect(hdcDraw, &rcT, hbshBackground);
// When in design mode, we do a little extra stuff to help the
// developer visualize some of the control settings (toolbars,
// foreground color, etc.)...
if (FRunningInDesignMode())
{
if (m_fShowToolbars)
{
rcT.bottom = rcT.top + 25;
FillRect(hdcDraw, &rcT, GetSysColorBrush(COLOR_BTNFACE));
clrT = SetTextColor(hdcDraw, GetSysColor(COLOR_BTNSHADOW));
DrawText(hdcDraw, "Toolbar Space", -1, &rcT, DT_SINGLELINE|DT_VCENTER|DT_CENTER);
SetTextColor(hdcDraw, clrT);
GetSizeRectForDocument(prcBounds, &rcT);
rcT.top = rcT.top + 25;
}
clrT = SetTextColor(hdcDraw, GetSysColor(COLOR_BTNSHADOW));
DrawText(hdcDraw, "ActiveX Document Object", -1, &rcT, DT_SINGLELINE|DT_VCENTER|DT_CENTER);
SetTextColor(hdcDraw, clrT);
}
}
else if ((m_pDocObjFrame) && (!m_fAppActive || !m_fComponentActive) && (FDrawBitmapOnAppDeactive() || FIPDeactivateOnCompChange()))
{
// In the case we have more than one component, and this component is
// has an object but is not ui active we draw a bitmap representation
// of the obect to fill the area. This gives the user a sense the object
// is there but in background, and can click to reactivate...
GetSizeRectForDocument(prcBounds, &rcT);
if (m_hbmDeactive)
{
HDC hdcT = CreateCompatibleDC(hdcDraw);
HBITMAP bmpOld = (HBITMAP)SelectObject(hdcT, m_hbmDeactive);
BITMAP bm;
if (GetObject(m_hbmDeactive, sizeof(BITMAP), &bm))
{
StretchBlt(hdcDraw, rcT.left, rcT.top,
(rcT.right - rcT.left), (rcT.bottom - rcT.top),
hdcT, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
}
else
{
BitBlt(hdcDraw, rcT.left, rcT.top,
(rcT.right - rcT.left), (rcT.bottom - rcT.top), hdcT, 0,0, SRCCOPY);
}
SelectObject(hdcT, bmpOld);
DeleteDC(hdcT);
}
else if (!m_fInDocumentLoad)
{
FillRect(hdcDraw, &rcT, hbshBackground);
rcT.top = ((rc.bottom - rc.top) / 2);
clrT = SetTextColor(hdcDraw, clrForeground);
DrawText(hdcDraw, "Unable to display inactive document. Click here to reactivate the object.", -1, &rcT, DT_WORDBREAK | DT_CENTER);
SetTextColor(hdcDraw, clrT);
}
} // else The docobj draws the rest...
// Cleanup the hDC as required...
DeleteObject(hbshBackground);
DeleteObject(hbshBorder);
SelectObject(hdcDraw, hfontOld);
DeleteObject(hfontText);
if (hpal)
{
SelectPalette(hdcDraw, hpalOld, TRUE);
DeleteObject(hpal);
}
SetBkMode(hdcDraw, iTxtMode);
SetMapMode(hdcDraw, iMapMode);
return;
}
////////////////////////////////////////////////////////////////////////
// CDsoFramerControl::OnDestroyWindow
//
// When the window closes make sure the object closes and release the
// subclass we have on the parent's top-level window.
//
STDMETHODIMP_(void) CDsoFramerControl::OnDestroyWindow()
{
ODS("CDsoFramerControl::OnDestroyWindow\n");
if (m_pDocObjFrame)
Close();
if (m_pHookManager)
{
m_pHookManager->DetachComponent(m_hwnd);
m_pHookManager = NULL;
}
m_hwnd = NULL;
if (m_pServerLock)
SetTempServerLock(FALSE);
if (m_hbmDeactive)
{
DeleteObject(m_hbmDeactive);
m_hbmDeactive = NULL;
}
if (m_hmenuFilePopup)
{
DestroyMenu(m_hmenuFilePopup);
m_hmenuFilePopup = NULL;
}
}
////////////////////////////////////////////////////////////////////////
// CDsoFramerControl::OnResize
//
// Resize the window and notify the doc site.
//
STDMETHODIMP_(void) CDsoFramerControl::OnResize()
{
RECT rcPlace;
ODS("CDsoFramerControl::OnResize\n");
if (m_pDocObjFrame)
{
if (FChangeObjActiveOnFocusChange() && (!m_fUIActive))
UIActivate(FALSE);
GetSizeRectForDocument(NULL, &rcPlace);
m_pDocObjFrame->OnNotifySizeChange(&rcPlace);
}
}
////////////////////////////////////////////////////////////////////////
// CDsoFramerControl::OnMouseMove
//
// We watch for mouse movement on menu bar (when visible).
//
STDMETHODIMP_(void) CDsoFramerControl::OnMouseMove(UINT x, UINT y)
{
// TRACE2("CDsoFramerControl::OnMouseMove(%d, %d)\n", x, y);
// TRACE3(" fAppActive=%d, fUIActive=%d, fCompActive=%d\n", m_fAppActive, m_fUIActive, m_fComponentActive);
// TRACE2(" fModalState=%d, fNoInteractive=%d\n", m_fModalState, m_fNoInteractive);
// When we are in mouse move, watch for menu selection. Only need to
// do this if bar is visible and we are not in modal state...
if ((m_fShowMenuBar) && (m_fComponentActive) && (m_fUIActive) && (m_fAppActive) &&
(!m_fModalState) && (!m_fNoInteractive))
{
UINT item;
POINT pt; pt.x = x; pt.y = y;
// If we already have item selected, check to see if we are still
// over it. If so, we can exit now. If not, we sould unselect it.
if (m_wSelMenuItem)
{
item = m_wSelMenuItem - 1;
if (PtInRect(&m_rgrcMenuItems[item], pt))
return;
ReleaseCapture(); m_wSelMenuItem = 0;
InvalidateRect(m_hwnd, &m_rgrcMenuItems[item], FALSE);
}
// Now loop through the menu items and see if mouse is over them.
// If it is, we set a mouse capture and draw item as selected...
for (item = 0; item < m_cMenuItems; item++)
{
if (PtInRect(&m_rgrcMenuItems[item], pt))
{
SetCapture(m_hwnd);
m_wSelMenuItem = (USHORT)(item + 1);
InvalidateRect(m_hwnd, &m_rgrcMenuItems[item], FALSE);
break;
}
}
}
return;
}
////////////////////////////////////////////////////////////////////////
// CDsoFramerControl::OnButtonDown
//
// We watch for mouse button down events when the titlebar is visible
// so we can drop down our popup menu if the user clicks around the
// area of the file icon. This is our workaround for menu merging.
//
STDMETHODIMP_(void) CDsoFramerControl::OnButtonDown(UINT x, UINT y)
{
HMENU hCurMenu = NULL;
RECT rc;
// Don't do anything if we are in modal state...
if (m_fModalState) return;
// We don't handle commands when m_fNoInteractive is set, except for the
// condition where we are in print preview and want to display custom menu
// item to end the preview. Office apps have toolbar button to do this, but
// we will provide this option just in case user needs it to exit preview mode...
if (m_fNoInteractive)
{
if ((m_pDocObjFrame) && (m_pDocObjFrame->InPrintPreview()))
{
// If we don't have UI focus, take it...
if (!m_fUIActive) UIActivate(TRUE);
// Create a temp popup menu. We do this on fly to save resources since
// this is only needed in rare cases...
if ((m_fShowTitlebar) && ((x < 22) && (y < 22)))
{
hCurMenu = CreatePopupMenu();
if (hCurMenu)
{
// Add the command to the menu...
AppendMenu(hCurMenu, MF_STRING, MNU_PRINTPV, "E&xit Preview");
// Display the menu...
GetSizeRectAfterTitlebar(NULL, &rc);
MapWindowPoints(m_hwnd, HWND_DESKTOP, (POINT*)&rc, 2);
TrackPopupMenu(hCurMenu, 0, rc.left, rc.top - 1, 0, m_hwnd, NULL);
// Cleanup...
DestroyMenu(hCurMenu);
hCurMenu = NULL;
}
}
}
// Otherwise we do nothing when m_fNoInteractive == TRUE.
return;
}
// We know we must be app active if user clicked on control...
if (!m_fAppActive) m_fAppActive = TRUE;
// If we don't have UI focus, take it...
if (!m_fUIActive) UIActivate(TRUE);
// If the caption is showing, we are not modal, and user clicked in the
// area around the office doc icon, show the popup menu...
if ((m_fShowTitlebar) && (!m_fShowMenuBar) && ((x < 22) && (y < 22)))
{
// This will get the File menu or the merged menu based on current state...
hCurMenu = GetActivePopupMenu();
if (hCurMenu)
{
// We'll place it right below the titlebar just like sys menu...
GetSizeRectAfterTitlebar(NULL, &rc);
MapWindowPoints(m_hwnd, HWND_DESKTOP, (POINT*)&rc, 2);
TrackPopupMenu(hCurMenu, 0, rc.left, rc.top - 1, 0, m_hwnd, NULL);
}
}
else if ((m_fShowMenuBar) && (m_wSelMenuItem))
{
POINT pt;
UINT item = m_wSelMenuItem - 1;
// If we are over a visible menu bar item, find the right popup
// menu for the item using the selitem as an index...
if (item == 0)
{ hCurMenu = m_hmenuFilePopup; }
else
{
hCurMenu = GetActivePopupMenu();
if (hCurMenu) hCurMenu = GetSubMenu(hCurMenu, item);
}
// Map the location to display the popup into screen points...
pt.x = m_rgrcMenuItems[item].left;
pt.y = m_rgrcMenuItems[item].bottom;
MapWindowPoints(m_hwnd, HWND_DESKTOP, (POINT*)&pt, 1);
HWND hwndCurFocus = GetFocus();
m_fInFocusChange = TRUE;
if (hwndCurFocus && (hwndCurFocus != m_hwnd))
SetFocus(m_hwnd);
// Display the menu...
TrackPopupMenu(hCurMenu, 0, pt.x, pt.y, 0, m_hwnd, NULL);
if (hwndCurFocus && (hwndCurFocus != m_hwnd))
SetFocus(hwndCurFocus);
m_fInFocusChange = FALSE;
// When user clicks off, we will resolve the mouse location to
// our control coordinates and call mousemove to free/reset selection...
if (GetCursorPos(&pt))
{
RECT rcMenu; GetSizeRectForMenuBar(NULL, &rcMenu);
MapWindowPoints(HWND_DESKTOP, m_hwnd, (POINT*)&pt, 1);
if (!PtInRect(&rcMenu, pt)) {pt.x = 0; pt.y = 0;}
}
else {pt.x = 0; pt.y = 0;}
OnMouseMove(pt.x, pt.y);
}
return;
}
////////////////////////////////////////////////////////////////////////
// CDsoFramerControl::OnMenuMessage
//
// We should get these messages when we are displaying the popup menu.
// The "File" menu is ours, but the popup may have other menus copied
// from the merged menu set by the ui active docobject, so we need to
// forward those messages (as needed) to the right window handler.
//
// In addition, code is added to enable/disable File menu items based
// on flags set by developer in EnableFileCommand, and/or call the
// correct function if one of those commands was selected by user.
//
STDMETHODIMP_(void) CDsoFramerControl::OnMenuMessage(UINT msg, WPARAM wParam, LPARAM lParam)
{
HMENU hmenu, hmenuMerged = NULL;
BOOL fAlwaysSendMessage = FALSE;
HWND hwndObjectMenu = NULL;
if (m_pDocObjFrame)
{
hwndObjectMenu = m_pDocObjFrame->GetMenuHWND();
hmenuMerged = m_pDocObjFrame->GetMergedMenu();
}
switch (msg)
{
case WM_INITMENU: m_fObjectMenu = FALSE; //fall through...
case WM_ENTERIDLE: fAlwaysSendMessage = TRUE;
break;
case WM_MENUSELECT:
if ((lParam == 0) && (HIWORD(wParam) == 0xFFFF))
fAlwaysSendMessage = TRUE;
break;
case WM_INITMENUPOPUP:
hmenu = (HMENU)wParam;
m_fObjectMenu = ((hmenu != m_hmenuFilePopup) && (hmenu != hmenuMerged));
if ((!m_fObjectMenu) && (hmenu == m_hmenuFilePopup))
{
EnableMenuItem(hmenu, MNU_NEW, MF_BYCOMMAND | ((m_wFileMenuFlags & 1) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
EnableMenuItem(hmenu, MNU_OPEN, MF_BYCOMMAND | ((m_wFileMenuFlags & 2) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
EnableMenuItem(hmenu, MNU_CLOSE, MF_BYCOMMAND | (((m_wFileMenuFlags & 4) && (m_pDocObjFrame)) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
EnableMenuItem(hmenu, MNU_SAVE, MF_BYCOMMAND | (((m_wFileMenuFlags & 8) && (m_pDocObjFrame)) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
EnableMenuItem(hmenu, MNU_SAVEAS, MF_BYCOMMAND | (((m_wFileMenuFlags & 16) && (m_pDocObjFrame)) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
EnableMenuItem(hmenu, MNU_PGSETUP, MF_BYCOMMAND | (((m_wFileMenuFlags & 64) && (m_pDocObjFrame)) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
EnableMenuItem(hmenu, MNU_PRINTPV, MF_BYCOMMAND | (((m_wFileMenuFlags & 256) && (m_pDocObjFrame)) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
EnableMenuItem(hmenu, MNU_PRINT, MF_BYCOMMAND | (((m_wFileMenuFlags & 32) && (m_pDocObjFrame)) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
EnableMenuItem(hmenu, MNU_PROPS, MF_BYCOMMAND | (((m_wFileMenuFlags & 128) && (m_pDocObjFrame)) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
}
break;
case WM_COMMAND:
// We handle one special case for print preview exit, but otherwise
// we need to either forward to the merged menu handler (if enabled),
// or handle command through an asynchronous callback...
if ((m_fNoInteractive) && (LOWORD(wParam) == MNU_PRINTPV))
{
PrintPreviewExit();
}
else if ((m_fObjectMenu) && (hwndObjectMenu))
{
PostMessage(hwndObjectMenu, msg, wParam, lParam);
}
else
{
DWORD dwCmd = 0;
switch ((int)LOWORD(wParam))
{
case MNU_NEW: dwCmd = OLECMDID_NEW; break;
case MNU_OPEN: dwCmd = OLECMDID_OPEN; break;
case MNU_SAVE: dwCmd = OLECMDID_SAVE; break;
case MNU_SAVEAS: dwCmd = OLECMDID_SAVEAS; break;
case MNU_PGSETUP: dwCmd = OLECMDID_PAGESETUP; break;
case MNU_PRINT: dwCmd = OLECMDID_PRINT; break;
case MNU_PROPS: dwCmd = OLECMDID_PROPERTIES; break;
case MNU_PRINTPV: dwCmd = OLECMDID_PRINTPREVIEW; break;
}
PostMessage(m_hwnd, DSO_WM_ASYNCH_OLECOMMAND, dwCmd, 0);
}
return; // we just return
}
if ((hwndObjectMenu) && ((m_fObjectMenu) || (fAlwaysSendMessage)))
SendMessage(hwndObjectMenu, msg, wParam, lParam);
return;
}
////////////////////////////////////////////////////////////////////////
// CDsoFramerControl::OnToolbarAction
//
// Does an associated OLECMDID action and raises the OnFileCommand event
// for developer to override as needed. The name comes from the fact that
// most Office servers will call this (via IOleCommandTarget) when user
// clicks on a toolbar button for file-command item. It also serves for
// our menu commands to keep the code consistant. Both menu and toolbar
// call this method asynchronously (via PostMessage) to avoid blocking the
// remote docobject server.
//
STDMETHODIMP_(void) CDsoFramerControl::OnToolbarAction(DWORD cmd)
{
ODS("CDsoFramerControl::OnToolbarAction\n");
HRESULT hr = S_OK;
VARIANT_BOOL wCancelAction = VARIANT_FALSE;
VARIANT rgargs[2];
VARIANT vtT = {0};
// We don't reenter if in a modal state already...
if (m_fModalState) return;
// If not interactive, we cannot run command...
if (m_fNoInteractive)
{
// unless we are in preview, in which case we can force exit
// and then run command after preview completes...
if ((m_pDocObjFrame) && (m_pDocObjFrame->InPrintPreview()))
{
PrintPreviewExit();
if (cmd != OLECMDID_PRINTPREVIEW)
PostMessage(m_hwnd, DSO_WM_ASYNCH_OLECOMMAND, cmd, 0);
}
return;
}
// We will do a default action by default, but give developer a chance
// to override in OnFileCommand event...
rgargs[0].vt = VT_BOOL|VT_BYREF;
rgargs[0].pboolVal = &wCancelAction;
// Map the OLECMDID to one of our values...
rgargs[1].vt = VT_I4;
switch (cmd)
{
case OLECMDID_NEW: rgargs[1].lVal = dsoFileNew; break;
case OLECMDID_OPEN: rgargs[1].lVal = dsoFileOpen; break;
case OLECMDID_SAVE: rgargs[1].lVal = dsoFileSave; break;
case OLECMDID_SAVEAS: rgargs[1].lVal = dsoFileSaveAs; break;
case OLECMDID_PRINT: rgargs[1].lVal = dsoFilePrint; break;
case OLECMDID_PAGESETUP: rgargs[1].lVal = dsoFilePageSetup; break;
case OLECMDID_PROPERTIES: rgargs[1].lVal = dsoFileProperties; break;
case OLECMDID_PRINTPREVIEW: rgargs[1].lVal = dsoFilePrintPreview; break;
default: rgargs[1].lVal = dsoFileClose;
}
// Only do action if item is enabled...
if ((1 << rgargs[1].lVal) & m_wFileMenuFlags)
{
// Let control developer handle the event first...
hr = RaiseAutomationEvent(DSOF_DISPID_FILECMD, 2, rgargs);
TRACE1("Disp event returned 0x%X \n", hr);
// If the event was canceled (or event handler threw an
// unhandled error from user code), bail out now...
if ((wCancelAction) || (hr == DISP_E_EXCEPTION))
return;
// Do the action based on the event...
switch (rgargs[1].lVal)
{
case dsoFileClose: hr = Close(); break;
case dsoFilePrint: hr = ShowDialog(dsoDialogPrint); break;
case dsoFilePageSetup: hr = ShowDialog(dsoDialogPageSetup); break;
case dsoFileProperties: hr = ShowDialog(dsoDialogProperties); break;
case dsoFilePrintPreview: hr = PrintPreview(); break;
case dsoFileSave:
hr = Save(vtT, vtT, vtT, vtT);
if ((hr != DSO_E_DOCUMENTREADONLY) &&
(hr != DSO_E_NOTBEENSAVED))
break; // fall through to SaveAs if file is read-only or never been saved...
default:
hr = DoDialogAction(
(rgargs[1].lVal == dsoFileNew) ? dsoDialogNew :
(rgargs[1].lVal == dsoFileOpen) ? dsoDialogOpen : dsoDialogSave);
}
// Display error information to user if we failed...
if (FAILED(hr) && (hr != E_ABORT))
FAlertUser(hr, NULL);
}
return;
}
////////////////////////////////////////////////////////////////////////
// CDsoFramerControl::FAlertUser
//
// Display an error alert to the user based on failed HRESULT.
//
STDMETHODIMP_(BOOL) CDsoFramerControl::FAlertUser(HRESULT hr, LPWSTR pwsFileName)
{
LPSTR pszError = NULL;
LPSTR pszTitle = NULL;
DWORD dwFlags = MB_ICONINFORMATION|MB_SETFOREGROUND;
switch (hr)
{
case STG_E_ACCESSDENIED:
case STG_E_SHAREVIOLATION:
case STG_E_LOCKVIOLATION:
case MK_E_CANTOPENFILE:
case E_ACCESSDENIED:
pszError = "Unable to Open/Save the file selected due to security permissions or a share violation.";
pszTitle = "Access Denied";
break;
case DSO_E_DOCUMENTNOTOPEN:
pszError = "The operation could not be performed because no document is currently open.";
pszTitle = "Unable to Perform Command";
break;
case DSO_E_DOCUMENTREADONLY:
pszError = "The operation could not be performed because the document was opened read-only.";
pszTitle = "Unable to Update Document";
break;
case CO_E_MSI_ERROR:
case DSO_E_INVALIDSERVER:
case DSO_E_INVALIDPROGID:
case STG_E_NOTFILEBASEDSTORAGE:
pszError = "There is no ActiveX Document server currently registered or installed for the item selected. "
"It cannot be loaded into the control.";
pszTitle = "Unable to Insert Document";
break;
case DSO_E_INMODALSTATE:
MessageBeep(0);
return FALSE; // Unable to alert user if in a modal condition!
case DSO_E_COMMANDNOTSUPPORTED:
pszError = "This operation could not be performed because the document server "
"does not support the command, or it is disabled when embedded.";
pszTitle = "Command Not Supported";
break;
case STG_E_TOOMANYOPENFILES:
pszError = "You can only open one document at a time. Please choose a single file to open.";
pszTitle = "Command Not Supported";
break;
case DSO_E_REQUIRESMSDAIPP:
pszError = "You cannot open/save to a web folder unless MDAC 2.5 is installed. The operation cannot be performed.";
pszTitle = "Unable to Gain Write Access for URL";
break;
default:
pszError = "The program encountered an error trying to perform the command. "
"If the problem persists, contact the program vendor for a possible solution.";
pszTitle = "Command Error";
dwFlags = MB_ICONHAND|MB_SETFOREGROUND;
}
MessageBox(m_hwnd, pszError, pszTitle, dwFlags);
return TRUE;
}
////////////////////////////////////////////////////////////////////////
// CDsoFramerControl::EnableDropFile
//
// Decide when to allow file drop for open.
//
STDMETHODIMP_(void) CDsoFramerControl::EnableDropFile(BOOL fEnable)
{
TRACE1("CDsoFramerControl::EnableDropFile(%d)\n", fEnable);
DragAcceptFiles(m_hwnd, fEnable);
}
////////////////////////////////////////////////////////////////////////
// CDsoFramerControl::OnDropFile
//
// Open file dropped by user on the control.
//
STDMETHODIMP_(void) CDsoFramerControl::OnDropFile(HDROP hdrpFile)
{
DWORD cbItems;
CHAR szFileDrop[MAX_PATH];
VARIANT vtFile;
ODS("CDsoFramerControl::OnDropFile()\n");
cbItems = DragQueryFile(hdrpFile, 0xFFFFFFFF, NULL, 0);
if (cbItems == 0)
return;
if (cbItems > 1)
{
FAlertUser(STG_E_TOOMANYOPENFILES, NULL);
return;
}
szFileDrop[0] = 0;
vtFile.vt = VT_BSTR;
if (DragQueryFile(hdrpFile, 0, szFileDrop, MAX_PATH) &&
(vtFile.bstrVal = DsoConvertToBSTR(szFileDrop)))
{
HRESULT hr;
VARIANT vtMissing;
vtMissing.vt = VT_ERROR;
vtMissing.scode = DISP_E_PARAMNOTFOUND;
hr = Open(vtFile, vtMissing, vtMissing, vtMissing, vtMissing);
if (FAILED(hr)) FAlertUser(hr, vtFile.bstrVal);
VariantClear(&vtFile);
}
return;
}
////////////////////////////////////////////////////////////////////////
// CDsoFramerControl::OnTimer
//
// Timer event fired.
//
STDMETHODIMP_(void) CDsoFramerControl::OnTimer(UINT id)
{
// TRACE1("CDsoFramerControl::OnTimer(%d)\n", id);
switch (id)
{
case SYNCPAINT_TIMER_ID:
{
DWORD dwTick = GetTickCount();
if ((dwTick - m_uiSyncPaint) > 300)
{
ODS("CDsoFramerControl::OnSyncPaint() Invalidate\n");
KillTimer(m_hwnd, SYNCPAINT_TIMER_ID);
m_fSyncPaintTimer = FALSE;
InvalidateAllChildWindows(m_hwnd);
}
}
break;
}
return;
}
////////////////////////////////////////////////////////////////////////
// CDsoFramerControl::OnSyncPaint
//
// Notifies redraw is needed b/c of external window movement.
//
STDMETHODIMP_(void) CDsoFramerControl::OnSyncPaint()
{
// ODS("CDsoFramerControl::OnSyncPaint()\n");
m_uiSyncPaint = GetTickCount();
if ((!m_fSyncPaintTimer) && (!m_fAppActive))
{
SetTimer(m_hwnd, SYNCPAINT_TIMER_ID, 50, NULL);
m_fSyncPaintTimer = TRUE;
}
}
////////////////////////////////////////////////////////////////////////
// CDsoFramerControl::OnForegroundCompChange
//
// Shows/Hide embedding when window goes foreground/background active.
//
STDMETHODIMP_(void) CDsoFramerControl::OnForegroundCompChange(BOOL fCompActive)
{
ODS("CDsoFramerControl::OnForegroundCompChange\n");
if (m_pDocObjFrame)
{
HWND hwndEmbed = m_pDocObjFrame->GetDocWindow();
if (fCompActive)
{
// Make sure embed window is visible when active...
if (!IsWindowVisible(hwndEmbed))
ShowWindow(hwndEmbed, SW_SHOW);
if (m_hbmDeactive) DeleteObject(m_hbmDeactive);
m_hbmDeactive = NULL;
}
else if ((FDrawBitmapOnAppDeactive() || FIPDeactivateOnCompChange()) && (m_hbmDeactive == NULL))
{
// The default behavior on app deactive is to grap bitmap of active object before
// telling it we lost app activation. This allows us to draw the last state of the
// object while it is deactive. There is now an option to avoid this and keep object
// UI active while app deactive, but it may not work for all DocObj servers.
m_hbmDeactive = DsoGetBitmapFromWindow(hwndEmbed);
ShowWindow(hwndEmbed, SW_HIDE);
}
}
}
////////////////////////////////////////////////////////////////////////
// CDsoFramerControl::OnAppActivationChange
//
// Notifes embedded object when the host app gains/loses foreground status
// as the active application. This notification is critical to DocObjects since
// it is the primary means for the host and server to synch which top-level
// frame window (the host or the server's native main window) should be on the
// z-order stack for the shared thread input state. Thus allowing dialogs and tool
// windows to appear the correct order when displayed.
//
STDMETHODIMP_(void) CDsoFramerControl::OnAppActivationChange(BOOL fAppActive, DWORD dwThreadID)
{
TRACE2("CDsoFramerControl::OnAppActivationChange(fAppActive=%d, tid=0x%X)\n", fAppActive, dwThreadID);
m_fAppActive = fAppActive;
if ((m_pDocObjFrame) && (m_fComponentActive))
{
// Create/Free bitmap for background appearance..
OnForegroundCompChange(fAppActive);
// Notify it that it should be app active ofr deactive...
m_pDocObjFrame->OnNotifyAppActivate(fAppActive, (dwThreadID ? dwThreadID : GetCurrentThreadId()));
}
}
////////////////////////////////////////////////////////////////////////
// CDsoFramerControl::OnComponentActivationChange
//
// Handles showing/hiding doc object during activation state changes.
// This is needed to properly handle focus changes when more than one
// instance of the control is running on the same top-level window.
//
STDMETHODIMP_(void) CDsoFramerControl::OnComponentActivationChange(BOOL fActivate)
{
TRACE1("CDsoFramerControl::OnComponentActivationChange(fActive=%d)\n", fActivate);
if (fActivate)
{
// Set us active if we currently are not and raise activation change event...
if (!m_fComponentActive)
{
m_fComponentActive = TRUE;
OnForegroundCompChange(TRUE);
// Raise event to component host on state change...
PostMessage(m_hwnd, DSO_WM_ASYNCH_STATECHANGE, DSO_STATE_ACTIVATION, (LPARAM)fActivate);
}
// Notify the embedded object...
if (m_pDocObjFrame)
{
// Determine if we should restore from IP deactivation...
if (FIPDeactivateOnCompChange() && !(m_pDocObjFrame->IsIPActive()))
{
m_pDocObjFrame->IPActivateView();
OnForegroundCompChange(TRUE);
}
}
}
else
{
// Inform embedded object we lost activation...
if (m_pDocObjFrame)
{
// If we are in print preview, we need to exit in case other control will
// end up talking to same OLE server...
if (m_pDocObjFrame->InPrintPreview())
{
PrintPreviewExit();
UpdateWindow(m_hwnd);
}
// Provide control host option to IP deactive view when another framer control
// takes primary focus. This helps certain resource problems if you a lot of controls
// all IP active at the same time. This should not normally be used.
if (FIPDeactivateOnCompChange() && m_pDocObjFrame->IsIPActive())
{
OnForegroundCompChange(FALSE);
m_pDocObjFrame->IPDeactivateView();
}
}
// Change the current activation state and raise event...
if (m_fComponentActive)
{
m_fComponentActive = FALSE;
OnForegroundCompChange(FALSE);
// Raise event to component host on state change...
PostMessage(m_hwnd, DSO_WM_ASYNCH_STATECHANGE, DSO_STATE_ACTIVATION, (LPARAM)fActivate);
}
}
}
////////////////////////////////////////////////////////////////////////
// CDsoFramerControl::OnCtrlFocusChange
//
// Checks if window (or one of its children) is getting or losing focus so
// that can notify both the host and embed server using OnUIFocusChange.
//
STDMETHODIMP_(void) CDsoFramerControl::OnCtrlFocusChange(BOOL fCtlGotFocus, HWND hFocusWnd)
{
TRACE2("CDsoFramerControl::OnCtrlFocusChange(fCtlGotFocus=%d, hwndCurFocus=%x)\n", fCtlGotFocus, hFocusWnd);
if (!(m_fInFocusChange) && ((fCtlGotFocus) || !IsWindowChild(m_hwnd, hFocusWnd)))
{
OnUIFocusChange(fCtlGotFocus);
}
}
////////////////////////////////////////////////////////////////////////
// CDsoFramerControl::OnUIFocusChange
//
// Selectively handle focus changes to make sure both host and ui
// active docobject are in synch.
//
STDMETHODIMP_(void) CDsoFramerControl::OnUIFocusChange(BOOL fUIActive)
{
BOOL fFocusUpdated = FALSE;
TRACE1("CDsoFramerControl::OnUIFocusChange(fUIActive=%d)\n", fUIActive);
// We shouldn't try to do focus change when modal...
if ((m_fModalState) || (m_fInFocusChange))
{
ODS(" -- Got focus while modal or in change (do nothing) --\n");
return;
}
// When IP active, notify the control host of focus change...
if ((m_fInPlaceActive) && (m_pControlSite))
{
// Set flag to prevent recursion during focus changes...
m_fInFocusChange = TRUE;
if (fUIActive) // If we got focus...
{
// Notify host we have focus (we only need
// to do this if we are not already UI Active)...
if (!(m_fHasFocus))
{
ODS(" -- Tell host app we should have focus --\n");
m_fHasFocus = (fFocusUpdated = TRUE);
m_pControlSite->OnFocus(TRUE);
}
// Let the hook manager know that this control is the active object...
if (m_pHookManager)
m_pHookManager->SetActiveComponent(m_hwnd);
// If so configured, force component to show up active...
if (FChangeObjActiveOnFocusChange())
{
ODS(" -- Do component active on focus gain --\n");
OnComponentActivationChange(TRUE);
}
// If we have an active document, forward the focus...
if (m_pDocObjFrame)
m_pDocObjFrame->OnNotifyControlFocus(TRUE);
}
else // else we lost focus...
{
// When we lose focus, only notify host if we lost to window
// that does not belong to us...
if (m_pDocObjFrame)
m_pDocObjFrame->OnNotifyControlFocus(FALSE);
// If so configured, force component loss on focus loss...
if (FChangeObjActiveOnFocusChange())
{
ODS(" -- Do component deactive on focus loss --\n");
OnComponentActivationChange(FALSE);
m_fActivateOnStatus = TRUE;
}
// If we are UI active still, we need to tell host that we lost
// focus and are now UI deactive.
if (m_fHasFocus)
{
ODS(" -- Notify host of lost focus (ie, UI deactivate us) --\n");
m_fHasFocus = FALSE; fFocusUpdated = TRUE;
m_pControlSite->OnFocus(FALSE);
}
}
// Clear focus change flag...
m_fInFocusChange = FALSE;
// Redraw menu bar in case of state change
if ((fFocusUpdated) && (m_fShowMenuBar))
{
RECT rc; GetSizeRectForMenuBar(NULL, &rc);
InvalidateRect(m_hwnd, &rc, TRUE);
}
}
return;
}
////////////////////////////////////////////////////////////////////////
// CDsoFramerControl::UpdateModalState
//
// Called either by developer (ModalState property) or by the embedded
// DocObject to notify host (VB/IE) that we are modal.
//
STDMETHODIMP_(void) CDsoFramerControl::UpdateModalState(BOOL fModeless, BOOL fNotifyIPObject)
{
TRACE2("CDsoFramerControl::UpdateModalState(AllowModeless=%d, NotifyIP=%d)\n", fModeless, fNotifyIPObject);
if (fModeless == (int)m_fModalState)
{
IOleInPlaceActiveObject* pipao;
m_fModalState = !(fModeless);
ODS("Modal state changed\n");
// Excel doesn't like us to notify the host of changes in modality
// if it is the one who initialied the call. So, we check the
// NotifyIPObj flag and only notify host when the IPObj is not the caller...
if ((fNotifyIPObject) && (m_pInPlaceFrame))
m_pInPlaceFrame->EnableModeless(fModeless);
// Again, if IPObj is not the caller and we have Ipobj, let it know
// of the change in modal state...
if ((fNotifyIPObject) && (m_pDocObjFrame) &&
(pipao = m_pDocObjFrame->GetActiveObject()))
pipao->EnableModeless(fModeless);
// Post notification of return from modal...
if (fModeless)
PostMessage(m_hwnd, DSO_WM_ASYNCH_STATECHANGE, DSO_STATE_RETURNFROMMODAL, (LPARAM)TRUE);
}
}
////////////////////////////////////////////////////////////////////////
// CDsoFramerControl::UpdateInteractiveState
//
// Called when interactivity changes (mostly due to print preview).
//
STDMETHODIMP_(void) CDsoFramerControl::UpdateInteractiveState(BOOL fActive)
{
if (fActive)
{
m_fNoInteractive = FALSE;
if (m_fShowMenuPrev) put_Menubar(VARIANT_TRUE);
if (!m_fShowToolsPrev) put_Toolbars(VARIANT_FALSE);
// Notify control host that preview mode has ended...
RaiseAutomationEvent(DSOF_DISPID_ENDPREVIEW, 0, NULL);
}
else
{
m_fShowMenuPrev = m_fShowMenuBar;
m_fShowToolsPrev = m_fShowToolbars;
if (m_fShowMenuBar) put_Menubar(VARIANT_FALSE);
if (!m_fShowToolbars) put_Toolbars(VARIANT_TRUE);
m_fNoInteractive = TRUE;
}
return;
}
////////////////////////////////////////////////////////////////////////
// CDsoFramerControl::OnPaletteChanged
//
// This method is also called from the subclassed parent. Per docobject
// spec, a ui active object should get first chance of any palette updates.
//
STDMETHODIMP_(void) CDsoFramerControl::OnPaletteChanged(HWND hwndPalChg)
{
ODS("CDsoFramerControl::OnPaletteChanged\n");
if (m_pDocObjFrame) m_pDocObjFrame->OnNotifyPaletteChanged(hwndPalChg);
}
////////////////////////////////////////////////////////////////////////
// CDsoFramerControl::OnSysCommandMenu
//
// Checks for menu shortcut keys when ui active.
//
STDMETHODIMP_(BOOL) CDsoFramerControl::OnSysCommandMenu(CHAR ch)
{
if (m_fUIActive)
{
TRACE1("CDsoFramerControl::OnSysCommandMenu(%d)\n", (DWORD)ch);
return TRUE;
}
return FALSE;
}
////////////////////////////////////////////////////////////////////////
// CDsoFramerControl::GetActivePopupMenu
//
// Constructs our popup menu and returns the handle. The menu can be
// either the File menu by itself (no docobj is open) or the merged
// menu as a popup.
//
STDMETHODIMP_(HMENU) CDsoFramerControl::GetActivePopupMenu()
{
HMENU hPopup, hMergedMenu, hServerMenu;
// If we haven't made a File menu yet, make it. Here is where you might
// want to add custom items if you have other file-level commands you would
// the control to support. These are the basics...
if (!m_hmenuFilePopup)
{
m_hmenuFilePopup = CreatePopupMenu(); m_cMenuItems = 0;
if (!m_hmenuFilePopup) return NULL;
AppendMenu(m_hmenuFilePopup, MF_STRING, MNU_NEW, "&New...\tCtrl+N");
AppendMenu(m_hmenuFilePopup, MF_STRING, MNU_OPEN, "&Open...\tCtrl+O");
AppendMenu(m_hmenuFilePopup, MF_STRING, MNU_CLOSE, "&Close");
AppendMenu(m_hmenuFilePopup, MF_SEPARATOR, 0, NULL);
AppendMenu(m_hmenuFilePopup, MF_STRING, MNU_SAVE, "&Save\tCtrl+S");
AppendMenu(m_hmenuFilePopup, MF_STRING, MNU_SAVEAS, "Save &As...");
AppendMenu(m_hmenuFilePopup, MF_SEPARATOR, 0, NULL);
AppendMenu(m_hmenuFilePopup, MF_STRING, MNU_PGSETUP, "Page Set&up...");
AppendMenu(m_hmenuFilePopup, MF_STRING, MNU_PRINTPV, "Print Pre&view");
AppendMenu(m_hmenuFilePopup, MF_STRING, MNU_PRINT, "&Print...");
AppendMenu(m_hmenuFilePopup, MF_SEPARATOR, 0, NULL);
AppendMenu(m_hmenuFilePopup, MF_STRING, MNU_PROPS, "Propert&ies");
}
// If we have a docobj and it has a merged menu, then lets return a
// merged menu between the docobj and our file menu...
if ((m_pDocObjFrame) && (m_pDocObjFrame->GetMenuHWND()))
{
// We only need to create the merged copy once.
if (!(hMergedMenu = m_pDocObjFrame->GetMergedMenu()))
{
hMergedMenu = CreatePopupMenu(); m_cMenuItems = 0;
if ((hMergedMenu) && (hServerMenu = (m_pDocObjFrame->GetActiveMenu())))
{
CHAR szbuf[MAX_PATH];
HMENU hT;
CHAR *pch;
InsertMenu(hMergedMenu, 0, MF_BYPOSITION|MF_POPUP, (UINT)m_hmenuFilePopup, "&File");
m_rgchMenuAccel[0] = 'f';
int cbMenuCnt = GetMenuItemCount(hServerMenu);
if (cbMenuCnt > DSO_MAX_MENUITEMS) cbMenuCnt = DSO_MAX_MENUITEMS;
for (int i = 0; i < cbMenuCnt; i++)
{
hT = GetSubMenu(hServerMenu, i);
if (hT)
{
szbuf[0] = '\0';
GetMenuString(hServerMenu, i, szbuf, MAX_PATH, MF_BYPOSITION);
InsertMenu(hMergedMenu, (i + 1), MF_BYPOSITION|MF_POPUP, (UINT)hT, szbuf);
pch = szbuf;
while (*pch && (*pch++ != '&'))
;
m_rgchMenuAccel[i + 1] = (CHAR)((*pch) ? ASCII_LOWERCASE(*pch) : 0xFF);
}
}
if (cbMenuCnt < DSO_MAX_MENUITEMS)
m_rgchMenuAccel[cbMenuCnt + 1] = 0x00;
m_pDocObjFrame->SetMergedMenu(hMergedMenu);
}
}
hPopup = hMergedMenu;
}
else
{
hPopup = m_hmenuFilePopup;
m_rgchMenuAccel[0] = 'f';
m_rgchMenuAccel[1] = 0;
}
return hPopup;
}
////////////////////////////////////////////////////////////////////////
// CDsoFramerControl::FRunningInDesignMode
//
// Determines if we are in design mode. Called when painting the control
// and when deciding whether to subclass the parent.
//
STDMETHODIMP_(BOOL) CDsoFramerControl::FRunningInDesignMode()
{
IDispatch *pdisp;
// We must have a control site.
CHECK_NULL_RETURN(m_pClientSite, FALSE);
// If we have done this before, we don't need to keep doing it unless
// the host has notified us of the state change (see our code in
// XOleControl::OnAmbientPropertyChange)...
if ((!m_fModeFlagValid) &&
SUCCEEDED(m_pClientSite->QueryInterface(IID_IDispatch, (void **)&pdisp)))
{
VARIANT vtUserMode;
m_fDesignMode = FALSE; // assume run mode
if (SUCCEEDED(DsoDispatchInvoke(pdisp, NULL,
DISPID_AMBIENT_USERMODE, DISPATCH_PROPERTYGET, 0, NULL, &vtUserMode)))
{
// UserMode is True when control is in Run mode, False when in design.
// We assume run mode, so we only care to set the flag if in design.
m_fDesignMode = !(BOOL_FROM_VARIANT(vtUserMode, TRUE));
VariantClear(&vtUserMode);
}
m_fModeFlagValid = TRUE;
// Release the IDispatch pointer...
pdisp->Release();
}
return m_fDesignMode;
}
////////////////////////////////////////////////////////////////////////
// CDsoFramerControl::InvalidateAllChildWindows
//
// Invalidate all child windows attached to the window passed.
//
STDMETHODIMP_(BOOL) CDsoFramerControl::InvalidateAllChildWindows(HWND hwnd)
{
ODS("CDsoFramerControl::InvalidateAllChildWindows()\n");
return EnumChildWindows(hwnd, InvalidateAllChildWindowsCallback, 0);
}
STDMETHODIMP_(BOOL) CDsoFramerControl::InvalidateAllChildWindowsCallback(HWND hwnd, LPARAM lParam)
{
RECT rc;
GetClientRect(hwnd, &rc);
InvalidateRect(hwnd, &rc, TRUE);
return TRUE;
}
////////////////////////////////////////////////////////////////////////
// CDsoFramerControl::RaiseAutomationEvent
//
// Raises automation events to host application.
//
STDMETHODIMP CDsoFramerControl::RaiseAutomationEvent(DISPID did, ULONG cargs, VARIANT *pvtargs)
{
HRESULT hr = ((m_fModalState) ? DISP_E_EXCEPTION : S_FALSE);
TRACE1("CDsoFramerControl::RaiseAutomationEvent(%d)\n", did);
// We should only raise event if we have sink, not already in a event, and
// we are not in modal condition with respect to the remote server...
if ((m_dispEvents) && (!m_fFreezeEvents) && (!m_fModalState))
{
m_fFreezeEvents = TRUE;
hr = DsoDispatchInvoke(m_dispEvents, NULL, did, 0, cargs, pvtargs, NULL);
m_fFreezeEvents = FALSE;
}
return hr;
}
////////////////////////////////////////////////////////////////////////
//
// CDsoFramerControl::DoDialogAction
//
// A very simple implementation of a New/Open/Save dialogs to serve as
// default actions in case developer does not override these "File"
// commands in OnFileCommand.
//
STDMETHODIMP CDsoFramerControl::DoDialogAction(dsoShowDialogType item)
{
HRESULT hr = S_FALSE;
BSTR bstr;
BOOL fReadOnly;
VARIANT vT[3];
static const WCHAR v_wszFileFilter[] =
L"Microsoft Office Files\0*.doc;*.docx;*.docm;*.rtf;*.xls;*.xlsx;*.xlsm;*.csv;*.ppt;*.pptx;*.pptm;*.mpp;*.vsd;*.vdx\0"
L"Microsoft Word Files\0*.doc;*.docx;*.docm;*.rtf\0"
L"Microsoft Excel Files\0*.xls;*.xlsx;*.xlsm;*.csv\0"
L"Microsoft PowerPoint Files\0*.ppt;*.pptx;*.pptm\0"
L"Microsoft Project Files\0*.mpp\0"
L"Microsoft Visio Files\0*.vsd;*.vdx\0"
L"All Files (*.*)\0*.*\0\0";
// Switch on the action type...
switch (item)
{
case dsoDialogOpen: // Get file from user and call Open...
if (SUCCEEDED(DsoGetFileFromUser(m_hwnd, NULL, (OFN_FILEMUSTEXIST|OFN_EXPLORER),
v_wszFileFilter, 1, NULL, NULL, FALSE, &bstr, &fReadOnly)))
{
vT[0].vt = VT_BSTR; vT[0].bstrVal = bstr;
vT[1].vt = VT_BOOL; vT[1].boolVal = (fReadOnly ? VARIANT_TRUE : VARIANT_FALSE);
vT[2].vt = VT_ERROR; vT[2].scode = DISP_E_PARAMNOTFOUND;
hr = Open(vT[0], vT[1], vT[2], vT[2], vT[2]);
SysFreeString(bstr);
}
break;
case dsoDialogSave: // Get file from user and call Save...
{
LPWSTR pwszSaveType = NULL;
LPWSTR pwszDefExt = NULL;
if (m_pDocObjFrame)
m_pDocObjFrame->GetDocumentTypeAndFileExtension(&pwszSaveType, &pwszDefExt);
if (SUCCEEDED(DsoGetFileFromUser(m_hwnd, NULL, (OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT|OFN_EXPLORER),
((pwszSaveType) ? pwszSaveType : v_wszFileFilter), 1, pwszDefExt, NULL, TRUE, &bstr, NULL)))
{
vT[0].vt = VT_BSTR; vT[0].bstrVal = bstr;
vT[1].vt = VT_BOOL; vT[1].boolVal = VARIANT_TRUE;
vT[2].vt = VT_ERROR; vT[2].scode = DISP_E_PARAMNOTFOUND;
hr = Save(vT[0], vT[1], vT[2], vT[2]);
SysFreeString(bstr);
}
if (pwszSaveType) DsoMemFree(pwszSaveType);
if (pwszDefExt) DsoMemFree(pwszDefExt);
}
break;
case dsoDialogNew: // Get either ProgID or File to create new object from...
if (SUCCEEDED(DsoGetOleInsertObjectFromUser(m_hwnd, L"Insert New Document Object",
(IOF_SELECTCREATENEW | IOF_DISABLELINK | IOF_DISABLEDISPLAYASICON | IOF_HIDECHANGEICON),
TRUE, FALSE, &bstr, NULL)))
{
hr = CreateNew(bstr);
SysFreeString(bstr);
}
break;
default: MessageBeep(0);
}
return hr;
}
////////////////////////////////////////////////////////////////////////
// CDsoFramerControl::SetTempServerLock
//
// Sets up lock of OLE server to make unload and new load of files faster
// and to avoid race conditions on reload of file.
//
STDMETHODIMP CDsoFramerControl::SetTempServerLock(BOOL fLock)
{
HRESULT hr = S_FALSE;
TRACE1("CDsoFramerControl::SetTempServerLock(%d)\n", fLock);
if (fLock)
{
CLSID *pclsid;
// First get the the CLSID of the current loaded object...
pclsid = m_pDocObjFrame->GetServerCLSID();
// If we already have a lock, determine if user is asking us to lock
// the same server (we only lock once for a given server type)...
if (m_pServerLock)
{
if (*(m_pServerLock->GetServerCLSID()) == *pclsid)
return S_FALSE;
// If the current document is from a different server, free the old lock...
hr = SetTempServerLock(FALSE);
ASSERT(SUCCEEDED(hr)); // Sanity check in debug...
}
// To lock the server, just make a dummy OLE object and don't ever site it...
m_pServerLock = CDsoDocObject::CreateInstance((IDsoDocObjectSite*)&m_xDsoDocObjectSite);
hr = ((m_pServerLock) ? m_pServerLock->CreateDocObject(*pclsid) : E_OUTOFMEMORY);
if (SUCCEEDED(hr))
{
hr = m_pServerLock->SetRunningServerLock(TRUE);
// If we lock Excel, it steals focus from this host to the lock object, so we
// need to take it back so the real object isn't mixed up state...
if (SUCCEEDED(hr) && (m_pServerLock->IsExcelObject()) && (m_fAppActive))
{
OnAppActivationChange(TRUE, 0);
}
}
else
{
delete m_pServerLock;
m_pServerLock = NULL;
}
}
else if (m_pServerLock)
{
SEH_TRY
hr = m_pServerLock->SetRunningServerLock(FALSE);
hr = m_pServerLock->Close();
SEH_EXCEPT(hr)
ASSERT(SUCCEEDED(hr)); // Sanity check in debug...
delete m_pServerLock;
m_pServerLock = NULL;
}
return hr;
}
////////////////////////////////////////////////////////////////////////
// CDsoFramerControl::ResetFrameHook
//
// Allows host to reset the frame hook.
//
STDMETHODIMP CDsoFramerControl::ResetFrameHook(HWND hwndFrameWindow)
{
DWORD dwProcessId;
TRACE1("CDsoFramerControl::ResetFrameHook(%d)\n", hwndFrameWindow);
// If the control is in modal state, we can't do anything...
if ((m_fModalState) || (m_fNoInteractive))
return ProvideErrorInfo(DSO_E_INMODALSTATE);
// Verify that hwnd passed is a valid window handle and belogs to same thread
// as the control for parenting purposes...
if ((hwndFrameWindow) && (!IsWindow(hwndFrameWindow) ||
(GetWindowThreadProcessId(hwndFrameWindow, &dwProcessId), dwProcessId != GetCurrentProcessId())))
return E_INVALIDARG;
// We must have a window already created for this to work...
if ((m_hwnd == NULL) || !IsWindow(m_hwnd) ||
(m_hwndParent == NULL) || !IsWindow(m_hwndParent))
return E_ACCESSDENIED;
// Detach from the current window (removing that hook if this is the last component)...
if (m_pHookManager)
{
HRESULT hr = m_pHookManager->DetachComponent(m_hwnd);
if (FAILED(hr)) return hr;
m_pHookManager = NULL;
}
// Now attach to the new parent window (or reattach based on the parent from our window)...
m_pHookManager = CDsoFrameHookManager::RegisterFramerControl((hwndFrameWindow ? hwndFrameWindow : m_hwndParent), m_hwnd);
if (m_pHookManager == NULL) return E_FAIL;
return S_OK;
}
////////////////////////////////////////////////////////////////////////
// CDsoFramerControl::RaiseActivationEvent
//
// Called to raise component change event on activation switch.
//
STDMETHODIMP_(void) CDsoFramerControl::RaiseActivationEvent(BOOL fActive)
{
VARIANT rgargs[1]; rgargs[0].vt = VT_BOOL;
rgargs[0].boolVal = (fActive ? VARIANT_TRUE : VARIANT_FALSE);
RaiseAutomationEvent(DSOF_DISPID_ACTIVATE, 1, rgargs);
return;
}
////////////////////////////////////////////////////////////////////////
// CDsoFramerControl::ControlWindowProc
//
// The window proc for our control.
//
STDMETHODIMP_(LRESULT) CDsoFramerControl::ControlWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
CDsoFramerControl* pCtl = (CDsoFramerControl*)GetWindowLong(hwnd, GWL_USERDATA);
if (pCtl)
{
switch (msg)
{
case WM_PAINT:
{
// call the OnDraw routine.
PAINTSTRUCT ps;
RECT rc;
HDC hdc;
hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rc);
pCtl->OnDraw(DVASPECT_CONTENT, hdc, (RECT*)&rc, NULL, NULL, TRUE);
EndPaint(hwnd, &ps);
}
break;
case WM_SIZE:
pCtl->OnResize();
break;
case WM_DESTROY:
pCtl->OnDestroyWindow();
SetWindowLong(hwnd, GWL_USERDATA, 0);
break;
case WM_SETFOCUS:
case WM_KILLFOCUS:
pCtl->OnCtrlFocusChange((BOOL)(msg == WM_SETFOCUS), (HWND)wParam);
break;
case WM_MOUSEMOVE:
pCtl->OnMouseMove(LOWORD(lParam), HIWORD(lParam));
break;
case WM_LBUTTONDOWN:
pCtl->OnButtonDown(LOWORD(lParam), HIWORD(lParam));
break;
case DSO_WM_ASYNCH_OLECOMMAND:
ODS(" -- Got DSO_WM_ASYNCH_OLECOMMAND -- \n");
pCtl->OnToolbarAction((DWORD)wParam);
break;
case DSO_WM_ASYNCH_STATECHANGE:
TRACE1(" -- Got DSO_WM_ASYNCH_STATECHANGE %d --\n", wParam);
{
BOOL fCondition = (lParam != 0);
switch (wParam)
{
case DSO_STATE_MODAL:
pCtl->UpdateModalState(fCondition, FALSE);
break;
case DSO_STATE_ACTIVATION:
pCtl->RaiseActivationEvent(fCondition);
break;
case DSO_STATE_INTERACTIVE:
pCtl->UpdateInteractiveState(fCondition);
break;
case DSO_STATE_RETURNFROMMODAL:
{
if ((pCtl->m_fModalState == FALSE) &&
(pCtl->m_fAppActive))
{
pCtl->OnUIFocusChange(TRUE);
}
}
break;
default:
ODS(" -- Unknown State Change!! --\n");
break;
}
}
break;
case DSO_WM_HOOK_NOTIFY_COMPACTIVE:
pCtl->OnComponentActivationChange((BOOL)wParam);
wParam = lParam; lParam = 0;
// falls through with wParam swapped...
case DSO_WM_HOOK_NOTIFY_APPACTIVATE:
pCtl->OnAppActivationChange((BOOL)wParam, (DWORD)lParam);
break;
case DSO_WM_HOOK_NOTIFY_SYNCPAINT:
pCtl->OnSyncPaint();
break;
case DSO_WM_HOOK_NOTIFY_PALETTECHANGE:
pCtl->OnPaletteChanged((HWND)wParam);
break;
case WM_ENABLE:
pCtl->OnWindowEnable((BOOL)wParam);
break;
case WM_MENUSELECT:
case WM_DRAWITEM:
case WM_MEASUREITEM:
case WM_ENTERIDLE:
case WM_INITMENU:
case WM_INITMENUPOPUP:
case WM_COMMAND:
pCtl->OnMenuMessage(msg, wParam, lParam);
break;
case WM_DROPFILES:
pCtl->OnDropFile((HDROP)wParam);
break;
case WM_TIMER:
pCtl->OnTimer((UINT)wParam);
break;
case WM_SYSCOMMAND:
if ((wParam & 0xFFF0) == SC_KEYMENU)
{
if (pCtl->m_xDsoDocObjectSite.SysMenuCommand((UINT)lParam) == S_OK)
{
ODS(" -- Eat SC_KeyMenu message --\n");
return 1;
}
}
// fall through to defwinproc...
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return (LRESULT)0;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
////////////////////////////////////////////////////////////////////////
//
// OCX Interfaces for CDsoFramerControl
//
// NOTE: The automation interfaces are implemented in dsofauto.cpp.
// The interfaces that follow are largely the interfaces used by the
// OCX host for normal control containment.
//
////////////////////////////////////////////////////////////////////////
//
// CDsoFramerControl::XInternalUnknown -- Internal IUnknown interface
// !!! Controls lifetime of CDsoFramerControl !!!
//
// STDMETHODIMP QueryInterface(REFIID riid, void ** ppv);
// STDMETHODIMP_(ULONG) AddRef(void);
// STDMETHODIMP_(ULONG) Release(void);
//
STDMETHODIMP CDsoFramerControl::XInternalUnknown::QueryInterface(REFIID riid, void** ppv)
{
// ODS("CDsoFramerControl::InternalQueryInterface\n");
CHECK_NULL_RETURN(ppv, E_POINTER);
HRESULT hr = S_OK;
METHOD_PROLOGUE(CDsoFramerControl, InternalUnknown);
if (IID_IUnknown == riid)
{
*ppv = (IUnknown*)this;
}
else if ((IID_IDispatch == riid) || (IID__FramerControl == riid))
{
*ppv = (_FramerControl*)pThis;
}
else if (IID_IOleObject == riid)
{
*ppv = (IOleObject*)&(pThis->m_xOleObject);
}
else if (IID_IOleControl == riid)
{
*ppv = (IOleControl*)&(pThis->m_xOleControl);
}
else if (IID_IPersistPropertyBag == riid)
{
*ppv = (IPersistPropertyBag*)&(pThis->m_xPersistPropertyBag);
}
else if ((IID_IPersistStreamInit == riid) || (IID_IPersistStream == riid) || (IID_IPersist == riid))
{
*ppv = (IPersistStreamInit*)&(pThis->m_xPersistStreamInit);
}
else if ((IID_IOleInPlaceObject == riid) || (IID_IOleWindow == riid))
{
*ppv = (IOleInPlaceObject*)&(pThis->m_xOleInplaceObject);
}
else if (IID_IOleInPlaceActiveObject == riid)
{
*ppv = (IOleInPlaceActiveObject*)&(pThis->m_xOleInplaceActiveObject);
}
else if ((IID_IViewObjectEx == riid) || (IID_IViewObject == riid) || (IID_IViewObject2 == riid))
{
*ppv = (IViewObjectEx*)&(pThis->m_xViewObjectEx);
}
else if (IID_IDataObject == riid)
{
*ppv = (IDataObject*)&(pThis->m_xDataObject);
}
else if (IID_ISupportErrorInfo == riid)
{
*ppv = (ISupportErrorInfo*)&(pThis->m_xSupportErrorInfo);
}
else if (IID_IProvideClassInfo == riid)
{
*ppv = (IProvideClassInfo*)&(pThis->m_xProvideClassInfo);
}
else if (IID_IConnectionPointContainer == riid)
{
*ppv = (IConnectionPointContainer*)&(pThis->m_xConnectionPointContainer);
}
else if (IID_IConnectionPoint == riid)
{
*ppv = (IConnectionPoint*)&(pThis->m_xConnectionPoint);
}
else if (IID_IEnumConnectionPoints == riid)
{
*ppv = (IEnumConnectionPoints*)&(pThis->m_xEnumConnectionPoints);
}
else if (IID_IPersistStorage == riid)
{
*ppv = (IPersistStorage*)&(pThis->m_xPersistStorage);
}
else if (IID_IObjectSafety == riid)
{
*ppv = (IObjectSafety*)&(pThis->m_xObjectSafety);
}
else if (IID_IOleCommandTarget == riid)
{
*ppv = (IOleCommandTarget*)&(pThis->m_xOleCommandTarget);
}
else if ((IID_IDsoDocObjectSite == riid) || (IID_IServiceProvider == riid))
{
*ppv = (IDsoDocObjectSite*)&(pThis->m_xDsoDocObjectSite);
}
else
{
*ppv = NULL;
hr = E_NOINTERFACE;
}
if (NULL != *ppv) // AddRef those interfaces we will return...
((IUnknown*)(*ppv))->AddRef();
return hr;
}
STDMETHODIMP_(ULONG) CDsoFramerControl::XInternalUnknown::AddRef(void)
{
METHOD_PROLOGUE(CDsoFramerControl, InternalUnknown);
//TRACE1("CDsoFramerControl::InternalAddRef - %d\n", (pThis->m_cRef + 1));
return ++(pThis->m_cRef);
}
STDMETHODIMP_(ULONG) CDsoFramerControl::XInternalUnknown::Release(void)
{
METHOD_PROLOGUE(CDsoFramerControl, InternalUnknown);
//TRACE1("CDsoFramerControl::InternalRelease - %d\n", (pThis->m_cRef - 1));
if (0 != --(pThis->m_cRef)) return (pThis->m_cRef);
ODS("CDsoFramerControl delete\n");
InterlockedDecrement((LPLONG)&v_cLocks);
delete pThis; return 0;
}
////////////////////////////////////////////////////////////////////////
//
// CDsoFramerControl::XPersistStreamInit -- IPersistStreamInit Implementation
//
// STDMETHODIMP GetClassID(CLSID *pClassID);
// STDMETHODIMP IsDirty(void);
// STDMETHODIMP Load(LPSTREAM pStm);
// STDMETHODIMP Save(LPSTREAM pStm, BOOL fClearDirty);
// STDMETHODIMP GetSizeMax(ULARGE_INTEGER* pcbSize);
// STDMETHODIMP InitNew(void);
//
IMPLEMENT_INTERFACE_UNKNOWN(CDsoFramerControl, PersistStreamInit)
STDMETHODIMP CDsoFramerControl::XPersistStreamInit::GetClassID(CLSID *pClassID)
{
ODS("CDsoFramerControl::XPersistStreamInit::GetClassID\n");
if (pClassID) *pClassID = CLSID_FramerControl;
return S_OK;
}
STDMETHODIMP CDsoFramerControl::XPersistStreamInit::IsDirty(void)
{
METHOD_PROLOGUE(CDsoFramerControl, PersistStreamInit);
ODS("CDsoFramerControl::XPersistStreamInit::IsDirty\n");
return (pThis->m_fDirty) ? S_OK : S_FALSE;
}
#define STREAMHDR_SIGNATURE_OLD 0x1234ABCD // Signature to identify our format (avoid crashes!)
#define STREAMHDR_SIGNATURE_NEW 0xD501D501 // Signature to identify our format (avoid crashes!)
STDMETHODIMP CDsoFramerControl::XPersistStreamInit::Load(LPSTREAM pStm)
{
HRESULT hr;
DWORD dwSig, dwT;
METHOD_PROLOGUE(CDsoFramerControl, PersistStreamInit);
ODS("CDsoFramerControl::XPersistStreamInit::Load\n");
// look for our header structure, so we can verify stream validity.
hr = pStm->Read(&dwSig, sizeof(DWORD), NULL);
RETURN_ON_FAILURE(hr);
if ((dwSig != STREAMHDR_SIGNATURE_NEW) &&
(dwSig != STREAMHDR_SIGNATURE_OLD))
return E_UNEXPECTED;
// we like the stream. let's go load in our two properties.
hr = pStm->Read(&(pThis->m_Size), sizeof(SIZEL), NULL);
RETURN_ON_FAILURE(hr);
DsoHimetricToPixels(&(pThis->m_Size.cx), &(pThis->m_Size.cy));
hr = pStm->Read(&(pThis->m_clrBorderColor), sizeof(OLE_COLOR), NULL);
RETURN_ON_FAILURE(hr);
hr = pStm->Read(&(pThis->m_clrBackColor), sizeof(OLE_COLOR), NULL);
RETURN_ON_FAILURE(hr);
hr = pStm->Read(&(pThis->m_clrForeColor), sizeof(OLE_COLOR), NULL);
RETURN_ON_FAILURE(hr);
hr = pStm->Read(&(pThis->m_clrTBarColor), sizeof(OLE_COLOR), NULL);
RETURN_ON_FAILURE(hr);
hr = pStm->Read(&(pThis->m_clrTBarTextColor), sizeof(OLE_COLOR), NULL);
RETURN_ON_FAILURE(hr);
hr = pStm->Read(&dwT, sizeof(DWORD), NULL);
RETURN_ON_FAILURE(hr);
pThis->m_fBorderStyle = LOBYTE(LOWORD(dwT));
pThis->m_fShowMenuBar = HIBYTE(LOWORD(dwT));
pThis->m_fShowToolbars = LOBYTE(HIWORD(dwT));
pThis->m_fShowTitlebar = HIBYTE(HIWORD(dwT));
hr = pStm->Read(&dwT, sizeof(DWORD), NULL);
RETURN_ON_FAILURE(hr);
if (dwT)
{
LPWSTR pwsz = (LPWSTR)DsoMemAlloc(dwT+2);
if (pwsz)
{
hr = pStm->Read(pwsz, dwT, NULL);
if (SUCCEEDED(hr))
pThis->m_bstrCustomCaption = SysAllocString(pwsz);
}
DsoMemFree(pwsz);
}
// Read in new properties for 1.3 version control...
if (dwSig == STREAMHDR_SIGNATURE_NEW)
{
DWORD dwValue;
hr = pStm->Read(&dwValue, sizeof(DWORD), NULL);
RETURN_ON_FAILURE(hr);
pThis->m_lActivationPolicy = LOWORD(dwValue);
pThis->m_lHookPolicy = HIWORD(dwValue);
hr = pStm->Read(&dwValue, sizeof(DWORD), NULL);
RETURN_ON_FAILURE(hr);
pThis->m_fDisableMenuAccel = LOBYTE(LOWORD(dwT));
}
return S_OK;
}
STDMETHODIMP CDsoFramerControl::XPersistStreamInit::Save(LPSTREAM pStm, BOOL fClearDirty)
{
HRESULT hr;
DWORD dwT, dwSig = STREAMHDR_SIGNATURE_NEW;
SIZEL slSize;
METHOD_PROLOGUE(CDsoFramerControl, PersistStreamInit);
ODS("CDsoFramerControl::XPersistStreamInit::Save\n");
// first thing to do is write out our stream sig...
hr = pStm->Write(&dwSig, sizeof(DWORD), NULL);
RETURN_ON_FAILURE(hr);
// the only properties we're currently persisting here are the size
// properties for this control. make sure we do that in HiMetric
slSize = pThis->m_Size;
DsoPixelsToHimetric(&(slSize.cx), &(slSize.cy));
hr = pStm->Write(&slSize, sizeof(SIZEL), NULL);
RETURN_ON_FAILURE(hr);
hr = pStm->Write(&(pThis->m_clrBorderColor), sizeof(OLE_COLOR), NULL);
RETURN_ON_FAILURE(hr);
hr = pStm->Write(&(pThis->m_clrBackColor), sizeof(OLE_COLOR), NULL);
RETURN_ON_FAILURE(hr);
hr = pStm->Write(&(pThis->m_clrForeColor), sizeof(OLE_COLOR), NULL);
RETURN_ON_FAILURE(hr);
hr = pStm->Write(&(pThis->m_clrTBarColor), sizeof(OLE_COLOR), NULL);
RETURN_ON_FAILURE(hr);
hr = pStm->Write(&(pThis->m_clrTBarTextColor), sizeof(OLE_COLOR), NULL);
RETURN_ON_FAILURE(hr);
dwT = (DWORD)MAKELONG(
MAKEWORD((BYTE)(pThis->m_fBorderStyle), (BYTE)(pThis->m_fShowMenuBar)),
MAKEWORD((BYTE)(pThis->m_fShowToolbars), (BYTE)(pThis->m_fShowTitlebar)));
hr = pStm->Write(&dwT, sizeof(DWORD), NULL);
RETURN_ON_FAILURE(hr);
dwT = 0;
if (pThis->m_bstrCustomCaption)
dwT = SysStringByteLen(pThis->m_bstrCustomCaption);
hr = pStm->Write(&dwT, sizeof(DWORD), NULL);
RETURN_ON_FAILURE(hr);
if (dwT)
{
hr = pStm->Write(pThis->m_bstrCustomCaption, dwT, NULL);
RETURN_ON_FAILURE(hr);
}
// Version 1.3 added properties...
dwT = (DWORD)MAKELONG((WORD)(pThis->m_lActivationPolicy), (WORD)(pThis->m_lHookPolicy));
hr = pStm->Write(&dwT, sizeof(DWORD), NULL);
RETURN_ON_FAILURE(hr);
dwT = (DWORD)MAKELONG(MAKEWORD((BYTE)(pThis->m_fDisableMenuAccel), 0), 0);
hr = pStm->Write(&dwT, sizeof(DWORD), NULL);
RETURN_ON_FAILURE(hr);
// clear out dirty flag and notify that we're done with save.
if (fClearDirty)
pThis->m_fDirty = FALSE;
if (pThis->m_pOleAdviseHolder)
pThis->m_pOleAdviseHolder->SendOnSave();
return S_OK;
}
STDMETHODIMP CDsoFramerControl::XPersistStreamInit::GetSizeMax(ULARGE_INTEGER *pcbSize)
{
ODS("CDsoFramerControl::XPersistStreamInit::GetSizeMax\n");
return E_NOTIMPL;
}
STDMETHODIMP CDsoFramerControl::XPersistStreamInit::InitNew(void)
{
METHOD_PROLOGUE(CDsoFramerControl, PersistStreamInit);
ODS("CDsoFramerControl::XPersistStreamInit::InitNew\n");
// If we are new control, we are dirty by default...
pThis->m_fDirty = TRUE;
return S_OK;
}
////////////////////////////////////////////////////////////////////////
//
// CDsoFramerControl::XPersistPropertyBag -- IPersistPropertyBag Implementation
//
// STDMETHODIMP GetClassID(CLSID *pClassID);
// STDMETHODIMP InitNew();
// STDMETHODIMP Load(IPropertyBag* pPropBag, IErrorLog* pErrorLog);
// STDMETHODIMP Save(IPropertyBag* pPropBag, BOOL fClearDirty, BOOL fSaveAllProperties);
//
IMPLEMENT_INTERFACE_UNKNOWN(CDsoFramerControl, PersistPropertyBag)
STDMETHODIMP CDsoFramerControl::XPersistPropertyBag::GetClassID(CLSID *pClassID)
{
ODS("CDsoFramerControl::XPersistPropertyBag::GetClassID\n");
if (pClassID) *pClassID = CLSID_FramerControl;
return S_OK;
}
STDMETHODIMP CDsoFramerControl::XPersistPropertyBag::InitNew()
{
METHOD_PROLOGUE(CDsoFramerControl, PersistPropertyBag);
ODS("CDsoFramerControl::XPersistPropertyBag::InitNew\n");
return pThis->m_xPersistStreamInit.InitNew();
}
STDMETHODIMP CDsoFramerControl::XPersistPropertyBag::Load(IPropertyBag* pPropBag, IErrorLog* pErrorLog)
{
VARIANT v;
HRESULT hr;
SIZEL sl = {5000, 3000};
METHOD_PROLOGUE(CDsoFramerControl, PersistPropertyBag);
ODS("CDsoFramerControl::XPersistPropertyBag::Load\n");
v.vt = VT_I4;
v.lVal = 0;
hr = pPropBag->Read(L"_ExtentX", &v, pErrorLog);
if (SUCCEEDED(hr)){sl.cx = v.lVal;}
v.lVal = 0;
hr = pPropBag->Read(L"_ExtentY", &v, pErrorLog);
if (SUCCEEDED(hr)){sl.cy = v.lVal;}
DsoHimetricToPixels(&(sl.cx), &(sl.cy));
pThis->m_Size = sl;
hr = pPropBag->Read(L"Titlebar", &v, pErrorLog);
if (SUCCEEDED(hr)){pThis->m_fShowTitlebar = v.boolVal;}
hr = pPropBag->Read(L"Toolbars", &v, pErrorLog);
if (SUCCEEDED(hr)){pThis->m_fShowToolbars = v.boolVal;}
hr = pPropBag->Read(L"BorderStyle", &v, pErrorLog);
if (SUCCEEDED(hr)){pThis->m_fBorderStyle = v.lVal;}
hr = pPropBag->Read(L"BorderColor", &v, pErrorLog);
if (SUCCEEDED(hr)){pThis->m_clrBorderColor = v.lVal;}
hr = pPropBag->Read(L"BackColor", &v, pErrorLog);
if (SUCCEEDED(hr)){pThis->m_clrBackColor = v.lVal;}
hr = pPropBag->Read(L"ForeColor", &v, pErrorLog);
if (SUCCEEDED(hr)){pThis->m_clrForeColor = v.lVal;}
hr = pPropBag->Read(L"TitlebarColor", &v, pErrorLog);
if (SUCCEEDED(hr)){pThis->m_clrTBarColor = v.lVal;}
hr = pPropBag->Read(L"TitlebarTextColor", &v, pErrorLog);
if (SUCCEEDED(hr)){pThis->m_clrTBarTextColor = v.lVal;}
hr = pPropBag->Read(L"Caption", &v, pErrorLog);
if (SUCCEEDED(hr))
{
LPWSTR pwsz = LPWSTR_FROM_VARIANT(v);
if (pwsz) pThis->m_bstrCustomCaption = SysAllocString(pwsz);
VariantClear(&v);
}
pThis->m_fShowMenuBar = FALSE;
hr = pPropBag->Read(L"Menubar", &v, pErrorLog);
if (SUCCEEDED(hr)){pThis->m_fShowMenuBar = BOOL_FROM_VARIANT(v, FALSE);}
hr = pPropBag->Read(L"ActivationPolicy", &v, pErrorLog);
if (SUCCEEDED(hr)){pThis->m_lActivationPolicy = LONG_FROM_VARIANT(v, 0);}
hr = pPropBag->Read(L"FrameHookPolicy", &v, pErrorLog);
if (SUCCEEDED(hr)){pThis->m_lHookPolicy = LONG_FROM_VARIANT(v, 0);}
hr = pPropBag->Read(L"MenuAccelerators", &v, pErrorLog);
if (SUCCEEDED(hr)){pThis->m_fDisableMenuAccel = !BOOL_FROM_VARIANT(v, TRUE);}
return S_OK;
}
STDMETHODIMP CDsoFramerControl::XPersistPropertyBag::Save(IPropertyBag* pPropBag, BOOL fClearDirty, BOOL fSaveAllProperties)
{
HRESULT hr;
VARIANT v;
SIZEL sl;
METHOD_PROLOGUE(CDsoFramerControl, PersistPropertyBag);
ODS("CDsoFramerControl::XPersistPropertyBag::Save\n");
sl = pThis->m_Size;
DsoPixelsToHimetric(&(sl.cx), &(sl.cy));
v.vt = VT_I4; v.lVal = sl.cx;
hr = pPropBag->Write(L"_ExtentX", &v);
RETURN_ON_FAILURE(hr);
v.lVal = sl.cy;
hr = pPropBag->Write(L"_ExtentY", &v);
RETURN_ON_FAILURE(hr);
v.lVal = pThis->m_clrBorderColor;
hr = pPropBag->Write(L"BorderColor", &v);
RETURN_ON_FAILURE(hr);
v.lVal = pThis->m_clrBackColor;
hr = pPropBag->Write(L"BackColor", &v);
RETURN_ON_FAILURE(hr);
v.lVal = pThis->m_clrForeColor;
hr = pPropBag->Write(L"ForeColor", &v);
RETURN_ON_FAILURE(hr);
v.lVal = pThis->m_clrTBarColor;
hr = pPropBag->Write(L"TitlebarColor", &v);
RETURN_ON_FAILURE(hr);
v.lVal = pThis->m_clrTBarTextColor;
hr = pPropBag->Write(L"TitlebarTextColor", &v);
RETURN_ON_FAILURE(hr);
v.lVal = pThis->m_fBorderStyle;
hr = pPropBag->Write(L"BorderStyle", &v);
RETURN_ON_FAILURE(hr);
v.vt = VT_BOOL; v.boolVal = pThis->m_fShowTitlebar;
hr = pPropBag->Write(L"Titlebar", &v);
RETURN_ON_FAILURE(hr);
v.boolVal = pThis->m_fShowToolbars;
hr = pPropBag->Write(L"Toolbars", &v);
RETURN_ON_FAILURE(hr);
if (pThis->m_bstrCustomCaption)
{
v.vt = VT_BSTR; v.bstrVal = pThis->m_bstrCustomCaption;
hr = pPropBag->Write(L"Caption", &v);
RETURN_ON_FAILURE(hr);
}
v.vt = VT_BOOL; v.boolVal = pThis->m_fShowMenuBar;
hr = pPropBag->Write(L"Menubar", &v);
RETURN_ON_FAILURE(hr);
v.vt = VT_I4; v.lVal = pThis->m_lActivationPolicy;
hr = pPropBag->Write(L"ActivationPolicy", &v);
RETURN_ON_FAILURE(hr);
v.vt = VT_I4; v.lVal = pThis->m_lHookPolicy;
hr = pPropBag->Write(L"FrameHookPolicy", &v);
RETURN_ON_FAILURE(hr);
v.vt = VT_BOOL; v.boolVal = !(pThis->m_fDisableMenuAccel);
hr = pPropBag->Write(L"MenuAccelerators", &v);
RETURN_ON_FAILURE(hr);
// now clear the dirty flag and send out notification
// that we're done.
if (fClearDirty)
pThis->m_fDirty = FALSE;
if (pThis->m_pOleAdviseHolder)
pThis->m_pOleAdviseHolder->SendOnSave();
return S_OK;
}
////////////////////////////////////////////////////////////////////////
//
// CDsoFramerControl::XPersistStorage -- IPersistStorage Implementation
//
// STDMETHODIMP GetClassID(CLSID *pClassID);
// STDMETHODIMP IsDirty(void);
// STDMETHODIMP InitNew(LPSTORAGE pStg);
// STDMETHODIMP Load(LPSTORAGE pStg);
// STDMETHODIMP Save(LPSTORAGE pStg, BOOL fSameAsLoad);
// STDMETHODIMP SaveCompleted(LPSTORAGE pStg);
// STDMETHODIMP HandsOffStorage(void);
//
IMPLEMENT_INTERFACE_UNKNOWN(CDsoFramerControl, PersistStorage)
STDMETHODIMP CDsoFramerControl::XPersistStorage::GetClassID(CLSID *pClassID)
{
ODS("CDsoFramerControl::XPersistStorage::GetClassID\n");
if (pClassID) *pClassID = CLSID_FramerControl;
return S_OK;
}
STDMETHODIMP CDsoFramerControl::XPersistStorage::IsDirty(void)
{
METHOD_PROLOGUE(CDsoFramerControl, PersistStorage);
ODS("CDsoFramerControl::XPersistStorage::IsDirty\n");
return (pThis->m_fDirty) ? S_OK : S_FALSE;
}
STDMETHODIMP CDsoFramerControl::XPersistStorage::InitNew(LPSTORAGE pStg)
{
HRESULT hr;
METHOD_PROLOGUE(CDsoFramerControl, PersistStorage);
ODS("CDsoFramerControl::XPersistStorage::InitNew\n");
CHECK_NULL_RETURN(pStg, E_POINTER);
SAFE_RELEASE_INTERFACE(pThis->m_pOleStorage);
hr = pThis->m_xPersistStreamInit.InitNew();
if (SUCCEEDED(hr))
{ SAFE_SET_INTERFACE(pThis->m_pOleStorage, pStg); };
return hr;
}
STDMETHODIMP CDsoFramerControl::XPersistStorage::Load(LPSTORAGE pStg)
{
HRESULT hr;
IStream* pstm;
DWORD dwStmMode = (STGM_DIRECT | STGM_READWRITE | STGM_SHARE_EXCLUSIVE);
METHOD_PROLOGUE(CDsoFramerControl, PersistStorage);
ODS("CDsoFramerControl::XPersistStorage::Load\n");
CHECK_NULL_RETURN(pStg, E_POINTER);
SAFE_RELEASE_INTERFACE(pThis->m_pOleStorage);
hr = pStg->OpenStream(L"DsoFrameCtlContents", 0, dwStmMode, 0, &pstm);
if (SUCCEEDED(hr) && (pstm))
{
hr = pThis->m_xPersistStreamInit.Load(pstm);
if (SUCCEEDED(hr))
{ SAFE_SET_INTERFACE(pThis->m_pOleStorage, pStg); };
pstm->Release();
}
return hr;
}
STDMETHODIMP CDsoFramerControl::XPersistStorage::Save(LPSTORAGE pStg, BOOL fSameAsLoad)
{
HRESULT hr;
IStream* pstm;
DWORD dwStmMode = (STGM_DIRECT | STGM_READWRITE | STGM_SHARE_EXCLUSIVE);
METHOD_PROLOGUE(CDsoFramerControl, PersistStorage);
ODS("CDsoFramerControl::XPersistStorage::Save\n");
if (fSameAsLoad)
{
if ((pThis->m_pOleStorage == NULL) ||
((pStg) && (pStg != pThis->m_pOleStorage)))
{
SAFE_RELEASE_INTERFACE(pThis->m_pOleStorage);
SAFE_SET_INTERFACE(pThis->m_pOleStorage, pStg);
}
CHECK_NULL_RETURN(pThis->m_pOleStorage, E_POINTER);
pStg = pThis->m_pOleStorage;
}
CHECK_NULL_RETURN(pStg, E_POINTER);
hr = pStg->OpenStream(L"DsoFrameCtlContents", 0, dwStmMode, 0, &pstm);
if (hr == STG_E_FILENOTFOUND)
hr = pStg->CreateStream(L"DsoFrameCtlContents", dwStmMode, 0, 0, &pstm);
if (SUCCEEDED(hr) && (pstm))
{
hr = pThis->m_xPersistStreamInit.Save(pstm, FALSE);
pstm->Release();
}
return hr;
}
STDMETHODIMP CDsoFramerControl::XPersistStorage::SaveCompleted(LPSTORAGE pStg)
{
METHOD_PROLOGUE(CDsoFramerControl, PersistStorage);
ODS("CDsoFramerControl::XPersistStorage::SaveCompleted\n");
pThis->m_fDirty = FALSE;
return S_OK;
}
STDMETHODIMP CDsoFramerControl::XPersistStorage::HandsOffStorage(void)
{
METHOD_PROLOGUE(CDsoFramerControl, PersistStorage);
ODS("CDsoFramerControl::XPersistStorage::HandsOffStorage\n");
SAFE_RELEASE_INTERFACE(pThis->m_pOleStorage);
return S_OK;
}
////////////////////////////////////////////////////////////////////////
//
// CDsoFramerControl::XOleObject -- IOleObject Implementation
//
// STDMETHODIMP SetClientSite(IOleClientSite *pClientSite);
// STDMETHODIMP GetClientSite(IOleClientSite **ppClientSite);
// STDMETHODIMP SetHostNames(LPCOLESTR szContainerApp, LPCOLESTR szContainerObj);
// STDMETHODIMP Close(DWORD dwSaveOption);
// STDMETHODIMP SetMoniker(DWORD dwWhichMoniker, IMoniker *pmk);
// STDMETHODIMP GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, IMoniker **ppmk);
// STDMETHODIMP InitFromData(IDataObject *pDataObject, BOOL fCreation, DWORD dwReserved);
// STDMETHODIMP GetClipboardData(DWORD dwReserved, IDataObject **ppDataObject);
// STDMETHODIMP DoVerb(LONG iVerb, LPMSG lpmsg, IOleClientSite *pActiveSite, LONG lindex, HWND hwndParent, LPCRECT lprcPosRect);
// STDMETHODIMP EnumVerbs(IEnumOleVerb **ppEnumOleVerb);
// STDMETHODIMP Update();
// STDMETHODIMP IsUpToDate();
// STDMETHODIMP GetUserClassID(CLSID *pClsid);
// STDMETHODIMP GetUserType(DWORD dwFormOfType, LPOLESTR *pszUserType);
// STDMETHODIMP SetExtent(DWORD dwDrawAspect, SIZEL *psizel);
// STDMETHODIMP GetExtent(DWORD dwDrawAspect, SIZEL *psizel);
// STDMETHODIMP Advise(IAdviseSink *pAdvSink, DWORD *pdwConnection);
// STDMETHODIMP Unadvise(DWORD dwConnection);
// STDMETHODIMP EnumAdvise(IEnumSTATDATA **ppenumAdvise);
// STDMETHODIMP GetMiscStatus(DWORD dwAspect, DWORD *pdwStatus);
// STDMETHODIMP SetColorScheme(LOGPALETTE *pLogpal);
//
IMPLEMENT_INTERFACE_UNKNOWN(CDsoFramerControl, OleObject)
STDMETHODIMP CDsoFramerControl::XOleObject::SetClientSite(IOleClientSite *pClientSite)
{
METHOD_PROLOGUE(CDsoFramerControl, OleObject);
ODS("CDsoFramerControl::XOleObject::SetClientSite\n");
SAFE_RELEASE_INTERFACE(pThis->m_pClientSite);
SAFE_RELEASE_INTERFACE(pThis->m_pControlSite);
// store away the new client site
pThis->m_pClientSite = pClientSite;
// if we've actually got one, then get some other interfaces we want to keep
// around, and keep a handle on it
if (pClientSite)
{
pClientSite->AddRef();
pClientSite->QueryInterface(IID_IOleControlSite, (void **)&(pThis->m_pControlSite));
}
return S_OK;
}
STDMETHODIMP CDsoFramerControl::XOleObject::GetClientSite(IOleClientSite **ppClientSite)
{
METHOD_PROLOGUE(CDsoFramerControl, OleObject);
ODS("CDsoFramerControl::XOleObject::GetClientSite\n");
if (ppClientSite) { SAFE_SET_INTERFACE(*ppClientSite, pThis->m_pClientSite); }
return S_OK;
}
STDMETHODIMP CDsoFramerControl::XOleObject::SetHostNames(LPCOLESTR /*szContainerApp*/, LPCOLESTR /*szContainerObj*/)
{
ODS("CDsoFramerControl::XOleObject::SetHostNames\n");
return S_OK;
}
STDMETHODIMP CDsoFramerControl::XOleObject::Close(DWORD dwSaveOption)
{
HRESULT hr;
METHOD_PROLOGUE(CDsoFramerControl, OleObject);
ODS("CDsoFramerControl::XOleObject::Close\n");
if (pThis->m_fInPlaceActive)
{
hr = pThis->m_xOleInplaceObject.InPlaceDeactivate();
RETURN_ON_FAILURE(hr);
}
// handle the save flag.
if ((pThis->m_fDirty) && (pThis->m_pClientSite) &&
(dwSaveOption == OLECLOSE_SAVEIFDIRTY ||
dwSaveOption == OLECLOSE_PROMPTSAVE))
{
pThis->m_pClientSite->SaveObject();
}
if (pThis->m_pOleAdviseHolder)
pThis->m_pOleAdviseHolder->SendOnClose();
return S_OK;
}
STDMETHODIMP CDsoFramerControl::XOleObject::SetMoniker(DWORD dwWhichMoniker, IMoniker *pmk)
{
ODS("CDsoFramerControl::XOleObject::SetMoniker\n");
return E_NOTIMPL;
}
STDMETHODIMP CDsoFramerControl::XOleObject::GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, IMoniker **ppmk)
{
ODS("CDsoFramerControl::XOleObject::GetMoniker\n");
if (ppmk) *ppmk = NULL;
return E_NOTIMPL;
}
STDMETHODIMP CDsoFramerControl::XOleObject::InitFromData(IDataObject *pDataObject, BOOL fCreation, DWORD dwReserved)
{
ODS("CDsoFramerControl::XOleObject::InitFromData\n");
return E_NOTIMPL;
}
STDMETHODIMP CDsoFramerControl::XOleObject::GetClipboardData(DWORD /*dwReserved*/, IDataObject **ppDataObject)
{
ODS("CDsoFramerControl::XOleObject::GetClipboardData\n");
if (ppDataObject) *ppDataObject = NULL;
return E_NOTIMPL;
}
STDMETHODIMP CDsoFramerControl::XOleObject::DoVerb(LONG iVerb, LPMSG lpmsg, IOleClientSite *pActiveSite, LONG lindex, HWND hwndParent, LPCRECT lprcPosRect)
{
METHOD_PROLOGUE(CDsoFramerControl, OleObject);
ODS("CDsoFramerControl::XOleObject::DoVerb\n");
switch (iVerb)
{
case OLEIVERB_PRIMARY:
case OLEIVERB_SHOW:
case OLEIVERB_INPLACEACTIVATE:
case OLEIVERB_UIACTIVATE:
return pThis->InPlaceActivate(iVerb);
case OLEIVERB_HIDE:
pThis->m_xOleInplaceObject.UIDeactivate();
if (pThis->m_fInPlaceVisible)
pThis->SetInPlaceVisible(FALSE);
return S_OK;
}
return OLEOBJ_S_INVALIDVERB;
}
STDMETHODIMP CDsoFramerControl::XOleObject::EnumVerbs(IEnumOLEVERB **ppEnumOleVerb)
{
ODS("CDsoFramerControl::XOleObject::EnumVerbs\n");
return OleRegEnumVerbs(CLSID_FramerControl, ppEnumOleVerb);
}
STDMETHODIMP CDsoFramerControl::XOleObject::Update()
{
ODS("CDsoFramerControl::XOleObject::Update\n");
return S_OK;
}
STDMETHODIMP CDsoFramerControl::XOleObject::IsUpToDate()
{
ODS("CDsoFramerControl::XOleObject::IsUpToDate\n");
return S_OK;
}
STDMETHODIMP CDsoFramerControl::XOleObject::GetUserClassID(CLSID *pClsid)
{
ODS("CDsoFramerControl::XOleObject::GetUserClassID\n");
if (pClsid) *pClsid = CLSID_FramerControl;
return S_OK;
}
STDMETHODIMP CDsoFramerControl::XOleObject::GetUserType(DWORD dwFormOfType, LPOLESTR *pszUserType)
{
ODS("CDsoFramerControl::XOleObject::GetUserType\n");
return OleRegGetUserType(CLSID_FramerControl, dwFormOfType, pszUserType);
}
STDMETHODIMP CDsoFramerControl::XOleObject::SetExtent(DWORD dwDrawAspect, SIZEL *psizel)
{
SIZEL sl;
METHOD_PROLOGUE(CDsoFramerControl, OleObject);
ODS("CDsoFramerControl::XOleObject::SetExtent\n");
CHECK_NULL_RETURN(psizel, E_POINTER);
sl = *psizel;
// we don't support any other aspects.
if (!(dwDrawAspect & DVASPECT_CONTENT))
return DV_E_DVASPECT;
// change the units to pixels, and resize the control.
DsoHimetricToPixels(&(sl.cx), &(sl.cy));
// if the size already matches the extents, then don't do anything
// and don't mark the control dirty.
if (sl.cx != pThis->m_Size.cx || sl.cy != pThis->m_Size.cy)
{
pThis->m_Size = sl;
pThis->m_fDirty = TRUE; // changing size should dirty
if (pThis->m_fInPlaceActive)
{
RECT rect;
// Use OnPosRectChange for older OCX containters and Access
// who just refuses to get with the times (like me <g>)...
GetWindowRect(pThis->m_hwnd, &rect);
MapWindowPoints(NULL, pThis->m_hwndParent, (LPPOINT)&rect, 2);
rect.right = rect.left + sl.cx;
rect.bottom = rect.top + sl.cy;
pThis->m_pInPlaceSite->OnPosRectChange(&rect);
// Resize the window based on the new size...
SetWindowPos(pThis->m_hwnd, NULL, 0, 0, sl.cx, sl.cy,
SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
}
else pThis->ViewChanged();
}
return S_OK;
}
STDMETHODIMP CDsoFramerControl::XOleObject::GetExtent(DWORD dwDrawAspect, SIZEL *psizel)
{
METHOD_PROLOGUE(CDsoFramerControl, OleObject);
ODS("CDsoFramerControl::XOleObject::GetExtent\n");
CHECK_NULL_RETURN(psizel, E_POINTER);
if (!(dwDrawAspect & DVASPECT_CONTENT))
return DV_E_DVASPECT;
*psizel = pThis->m_Size;
DsoPixelsToHimetric(&(psizel->cx), &(psizel->cy));
return S_OK;
}
STDMETHODIMP CDsoFramerControl::XOleObject::Advise(IAdviseSink *pAdvSink, DWORD *pdwConnection)
{
METHOD_PROLOGUE(CDsoFramerControl, OleObject);
ODS("CDsoFramerControl::XOleObject::Advise\n");
if (NULL == pThis->m_pOleAdviseHolder)
{
if (FAILED(CreateOleAdviseHolder(&(pThis->m_pOleAdviseHolder))))
return E_FAIL;
}
return pThis->m_pOleAdviseHolder->Advise(pAdvSink, pdwConnection);
}
STDMETHODIMP CDsoFramerControl::XOleObject::Unadvise(DWORD dwConnection)
{
METHOD_PROLOGUE(CDsoFramerControl, OleObject);
ODS("CDsoFramerControl::XOleObject::Unadvise\n");
CHECK_NULL_RETURN(pThis->m_pOleAdviseHolder, CONNECT_E_NOCONNECTION);
return pThis->m_pOleAdviseHolder->Unadvise(dwConnection);
}
STDMETHODIMP CDsoFramerControl::XOleObject::EnumAdvise(IEnumSTATDATA **ppenumAdvise)
{
METHOD_PROLOGUE(CDsoFramerControl, OleObject);
ODS("CDsoFramerControl::XOleObject::EnumAdvise\n");
CHECK_NULL_RETURN(ppenumAdvise, E_POINTER);
*ppenumAdvise = NULL;
CHECK_NULL_RETURN(pThis->m_pOleAdviseHolder, E_FAIL);
return pThis->m_pOleAdviseHolder->EnumAdvise(ppenumAdvise);
}
STDMETHODIMP CDsoFramerControl::XOleObject::GetMiscStatus(DWORD dwAspect, DWORD *pdwStatus)
{
ODS("CDsoFramerControl::XOleObject::GetMiscStatus\n");
if (dwAspect != DVASPECT_CONTENT)
return DV_E_DVASPECT;
if (pdwStatus)
*pdwStatus = OLEMISC_SETCLIENTSITEFIRST |
OLEMISC_ACTIVATEWHENVISIBLE |
OLEMISC_RECOMPOSEONRESIZE |
OLEMISC_CANTLINKINSIDE |
OLEMISC_INSIDEOUT;
return S_OK;
}
STDMETHODIMP CDsoFramerControl::XOleObject::SetColorScheme(LOGPALETTE *pLogpal)
{
ODS("CDsoFramerControl::XOleObject::SetColorScheme\n");
return S_OK;
}
////////////////////////////////////////////////////////////////////////
//
// CDsoFramerControl::XOleControl -- IOleControl Implementation
//
// STDMETHODIMP GetControlInfo(CONTROLINFO* pCI);
// STDMETHODIMP OnMnemonic(LPMSG pMsg);
// STDMETHODIMP OnAmbientPropertyChange(DISPID dispID);
// STDMETHODIMP FreezeEvents(BOOL bFreeze);
//
IMPLEMENT_INTERFACE_UNKNOWN(CDsoFramerControl, OleControl)
STDMETHODIMP CDsoFramerControl::XOleControl::GetControlInfo(CONTROLINFO* pCI)
{
ODS("CDsoFramerControl::XOleControl::GetControlInfo\n");
CHECK_NULL_RETURN(pCI, E_POINTER);
pCI->hAccel = NULL; pCI->cAccel = 0; pCI->dwFlags = 0;
return S_OK;
}
STDMETHODIMP CDsoFramerControl::XOleControl::OnMnemonic(LPMSG pMsg)
{
METHOD_PROLOGUE(CDsoFramerControl, OleControl);
ODS("CDsoFramerControl::XOleControl::OnMnemonic\n");
return pThis->InPlaceActivate(OLEIVERB_UIACTIVATE);
}
STDMETHODIMP CDsoFramerControl::XOleControl::OnAmbientPropertyChange(DISPID dispID)
{
METHOD_PROLOGUE(CDsoFramerControl, OleControl);
ODS("CDsoFramerControl::XOleControl::OnAmbientPropertyChange\n");
// We keep track of state changes in design/run modes...
if (dispID == DISPID_AMBIENT_USERMODE || dispID == DISPID_UNKNOWN)
pThis->m_fModeFlagValid = FALSE;
return S_OK;
}
STDMETHODIMP CDsoFramerControl::XOleControl::FreezeEvents(BOOL bFreeze)
{
METHOD_PROLOGUE(CDsoFramerControl, OleControl);
TRACE1("CDsoFramerControl::XOleControl::FreezeEvents = %s\n", (bFreeze ? "TRUE" : "FALSE"));
pThis->m_fFreezeEvents = bFreeze;
return S_OK;
}
////////////////////////////////////////////////////////////////////////
//
// CDsoFramerControl::XOleInplaceObject -- IOleInplaceObject Implementation
//
// STDMETHODIMP GetWindow(HWND *phwnd);
// STDMETHODIMP ContextSensitiveHelp(BOOL fEnterMode);
// STDMETHODIMP InPlaceDeactivate();
// STDMETHODIMP UIDeactivate();
// STDMETHODIMP SetObjectRects(LPCRECT lprcPosRect, LPCRECT lprcClipRect);
// STDMETHODIMP ReactivateAndUndo();
//
IMPLEMENT_INTERFACE_UNKNOWN(CDsoFramerControl, OleInplaceObject)
STDMETHODIMP CDsoFramerControl::XOleInplaceObject::GetWindow(HWND *phwnd)
{
METHOD_PROLOGUE(CDsoFramerControl, OleInplaceObject);
ODS("CDsoFramerControl::XOleInplaceObject::GetWindow\n");
if (!(pThis->m_fInPlaceActive)) return E_FAIL;
if (phwnd) *phwnd = pThis->m_hwnd;
return S_OK;
}
STDMETHODIMP CDsoFramerControl::XOleInplaceObject::ContextSensitiveHelp(BOOL /*fEnterMode*/)
{
ODS("CDsoFramerControl::XOleInplaceObject::ContextSensitiveHelp\n");
return E_NOTIMPL;
}
STDMETHODIMP CDsoFramerControl::XOleInplaceObject::InPlaceDeactivate()
{
METHOD_PROLOGUE(CDsoFramerControl, OleInplaceObject);
ODS("CDsoFramerControl::XOleInplaceObject::InPlaceDeactivate\n");
// if we're not in-place active yet, then this is easy.
if (!(pThis->m_fInPlaceActive))
return S_OK;
// transition from UIActive back to active
if (pThis->m_fUIActive)
UIDeactivate();
// tell the host we're going away
pThis->m_pInPlaceSite->OnInPlaceDeactivate();
pThis->m_fInPlaceActive = FALSE;
pThis->m_fInPlaceVisible = FALSE;
// if we have a window, tell it to go away.
if (pThis->m_hwnd)
{DestroyWindow(pThis->m_hwnd); pThis->m_hwnd = NULL;}
SAFE_RELEASE_INTERFACE(pThis->m_pInPlaceFrame);
SAFE_RELEASE_INTERFACE(pThis->m_pInPlaceUIWindow);
return S_OK;
}
STDMETHODIMP CDsoFramerControl::XOleInplaceObject::UIDeactivate()
{
METHOD_PROLOGUE(CDsoFramerControl, OleInplaceObject);
ODS("CDsoFramerControl::XOleInplaceObject::UIDeactivate\n");
// if we're not UIActive, not much to do.
if (!(pThis->m_fUIActive))
return S_OK;
pThis->m_fUIActive = FALSE;
// notify frame windows, if appropriate, that we're no longer ui-active.
if (pThis->m_pInPlaceUIWindow)
pThis->m_pInPlaceUIWindow->SetActiveObject(NULL, NULL);
if (pThis->m_pInPlaceFrame)
pThis->m_pInPlaceFrame->SetActiveObject(NULL, NULL);
pThis->OnUIFocusChange(FALSE);
// we don't need to explicitly release the focus here since somebody
// else grabbing the focus is what is likely to cause us to get lose it
pThis->m_pInPlaceSite->OnUIDeactivate(FALSE);
return S_OK;
}
STDMETHODIMP CDsoFramerControl::XOleInplaceObject::SetObjectRects(LPCRECT lprcPosRect, LPCRECT lprcClipRect)
{
RECT rcIXect;
METHOD_PROLOGUE(CDsoFramerControl, OleInplaceObject);
ODS("CDsoFramerControl::XOleInplaceObject::SetObjectRects\n");
// move our window to the new location and handle clipping.
if (pThis->m_hwnd)
{
// if asked to clip the window, we'll use a clip region...
if ((lprcClipRect) && (IntersectRect(&rcIXect, lprcPosRect, lprcClipRect)) &&
(!EqualRect(&rcIXect, lprcPosRect)))
{
OffsetRect(&rcIXect, -(lprcPosRect->left), -(lprcPosRect->top));
SetWindowRgn(pThis->m_hwnd, CreateRectRgnIndirect(&rcIXect), TRUE);
pThis->m_fUsingWindowRgn = TRUE;
}
else if (pThis->m_fUsingWindowRgn)
{
SetWindowRgn(pThis->m_hwnd, NULL, TRUE);
pThis->m_fUsingWindowRgn = FALSE;
}
// set our control's location, but don't change it's size at all
// [people for whom zooming is important should set that up here]
SetWindowPos(pThis->m_hwnd, NULL, lprcPosRect->left, lprcPosRect->top, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
}
// save out our current location.
pThis->m_rcLocation = *lprcPosRect;
return S_OK;
}
STDMETHODIMP CDsoFramerControl::XOleInplaceObject::ReactivateAndUndo()
{
ODS("CDsoFramerControl::XOleInplaceObject::ReactivateAndUndo\n");
return E_NOTIMPL;
}
////////////////////////////////////////////////////////////////////////
//
// CDsoFramerControl::XOleInplaceActiveObject -- IOleInplaceActiveObject Implementation
//
// STDMETHODIMP GetWindow(HWND *phwnd);
// STDMETHODIMP ContextSensitiveHelp(BOOL fEnterMode);
// STDMETHODIMP TranslateAccelerator(LPMSG lpmsg);
// STDMETHODIMP OnFrameWindowActivate(BOOL fActivate);
// STDMETHODIMP OnDocWindowActivate(BOOL fActivate);
// STDMETHODIMP ResizeBorder(LPCRECT prcBorder, IOleInPlaceUIWindow *pUIWindow, BOOL fFrameWindow);
// STDMETHODIMP EnableModeless(BOOL fEnable);
//
IMPLEMENT_INTERFACE_UNKNOWN(CDsoFramerControl, OleInplaceActiveObject)
STDMETHODIMP CDsoFramerControl::XOleInplaceActiveObject::GetWindow(HWND *phwnd)
{
METHOD_PROLOGUE(CDsoFramerControl, OleInplaceActiveObject);
ODS("CDsoFramerControl::XOleInplaceActiveObject::GetWindow\n");
if (phwnd) *phwnd = pThis->m_hwnd;
return S_OK;
}
STDMETHODIMP CDsoFramerControl::XOleInplaceActiveObject::ContextSensitiveHelp(BOOL /*fEnterMode*/)
{
ODS("CDsoFramerControl::XOleInplaceActiveObject::ContextSensitiveHelp\n");
return E_NOTIMPL;
}
////////////////////////////////////////////////////////////////////////
// CDsoFramerControl::XOleInplaceActiveObject::TranslateAccelerator
//
// We handle certain keys as accelerators, but only if host does not
// implement it itself, and only when no document is open. The reason
// why is due to two factors:
//
// (1) When an out-of-proc AxDoc server is embedded and has focus,
// its thread (not ours) gets the accel keys. Word/PPT will treat
// these for us and contact us through IOleCommandTarget, so
// we don't want to handle them if AxDoc is handling them for us.
//
// (2) We cannot know if a given host uses the same accel keys for
// other tasks, and we don't want to impose ours on a host. By
// explicitly asking host to handle it first, we should be able
// to avoid any conflicts, and give developer a change to override
// our handler as needed.
//
static short _SpecialKeyState()
{
BOOL bShift = (GetKeyState(VK_SHIFT) < 0);
BOOL bCtrl = (GetKeyState(VK_CONTROL) < 0);
BOOL bAlt = (GetKeyState(VK_MENU) < 0);
return (short)(bShift + (bCtrl << 1) + (bAlt << 2));
}
STDMETHODIMP CDsoFramerControl::XOleInplaceActiveObject::TranslateAccelerator(LPMSG lpmsg)
{
HRESULT hr = S_FALSE;
METHOD_PROLOGUE(CDsoFramerControl, OleInplaceActiveObject);
CHECK_NULL_RETURN(lpmsg, E_POINTER);
TRACE2("CDsoFramerControl::XOleInplaceActiveObject::TranslateAccelerator(msg=%d, wparam=%d)\n", lpmsg->message, lpmsg->wParam);
// Forward it back to the site for processing on its side...
if (pThis->m_pControlSite)
{
hr = pThis->m_pControlSite->TranslateAccelerator(lpmsg, _SpecialKeyState());
if (hr == S_OK) return S_OK; // If site handled it, nothing else we need to do..
}
if ((GetKeyState(VK_CONTROL) < 0) && (!(pThis->m_fModalState)) &&
(lpmsg->message == WM_KEYUP) && (!(pThis->m_pDocObjFrame)))
{
TRACE1(" Handle Accelerator? (%d)\n", lpmsg->wParam);
switch (lpmsg->wParam) // Looking for Ctrl+N and Ctrl+O keys...
{
case 0x4E: PostMessage(pThis->m_hwnd, DSO_WM_ASYNCH_OLECOMMAND, OLECMDID_NEW, 0); hr = S_OK; break;
case 0x4F: PostMessage(pThis->m_hwnd, DSO_WM_ASYNCH_OLECOMMAND, OLECMDID_OPEN, 0); hr = S_OK; break;
case 0x53: PostMessage(pThis->m_hwnd, DSO_WM_ASYNCH_OLECOMMAND, OLECMDID_SAVE, 0); hr = S_OK; break;
}
}
// we didn't want it.
return hr;
}
STDMETHODIMP CDsoFramerControl::XOleInplaceActiveObject::OnFrameWindowActivate(BOOL fActivate)
{
TRACE1("CDsoFramerControl::XOleInplaceActiveObject::OnFrameWindowActivate - %d\n", fActivate);
return S_OK;
}
STDMETHODIMP CDsoFramerControl::XOleInplaceActiveObject::OnDocWindowActivate(BOOL fActivate)
{
METHOD_PROLOGUE(CDsoFramerControl, OleInplaceActiveObject);
TRACE1("CDsoFramerControl::XOleInplaceActiveObject::OnDocWindowActivate - %d\n", fActivate);
if (pThis->m_fUIActive && fActivate && pThis->m_pInPlaceFrame)
pThis->m_pInPlaceFrame->SetBorderSpace(NULL);
return S_OK;
}
STDMETHODIMP CDsoFramerControl::XOleInplaceActiveObject::ResizeBorder(LPCRECT prcBorder, IOleInPlaceUIWindow *pUIWindow, BOOL fFrameWindow)
{
ODS("CDsoFramerControl::XOleInplaceActiveObject::ResizeBorder\n");
return S_OK;
}
STDMETHODIMP CDsoFramerControl::XOleInplaceActiveObject::EnableModeless(BOOL fEnable)
{
TRACE1("CDsoFramerControl::XOleInplaceActiveObject::EnableModeless(%d)\n", fEnable);
return S_OK;
}
////////////////////////////////////////////////////////////////////////
//
// CDsoFramerControl::XViewObjectEx -- IViewObjectEx Implementation
//
// STDMETHODIMP Draw(DWORD dwAspect, LONG lindex, void *pvAspect, DVTARGETDEVICE * ptd, HDC hicTargetDev, HDC hdcDraw, const LPRECTL lprcBounds, const LPRECTL lprcWBounds, BOOL(*)(DWORD)pfnContinue, DWORD dwContinue);
// STDMETHODIMP GetColorSet(DWORD dwAspect, LONG lindex, void* pvAspect, DVTARGETDEVICE *ptd, HDC hicTargetDev, LOGPALETTE** ppColorSet);
// STDMETHODIMP Freeze(DWORD dwAspect, LONG lindex, void* pvAspect, DWORD* pdwFreeze);
// STDMETHODIMP Unfreeze(DWORD dwFreeze);
// STDMETHODIMP SetAdvise(DWORD dwAspect, DWORD advf, IAdviseSink* pAdvSink);
// STDMETHODIMP GetAdvise(DWORD* pdwAspect, DWORD* padvf, IAdviseSink** ppAdvSink);
// STDMETHODIMP GetExtent(DWORD dwAspect, DWORD lindex, DVTARGETDEVICE ptd, LPSIZEL lpsizel);
// STDMETHODIMP GetRect(DWORD dwAspect, LPRECTL pRect);
// STDMETHODIMP GetViewStatus(DWORD* pdwStatus);
// STDMETHODIMP QueryHitPoint(DWORD dwAspect, LPCRECT pRectBounds, POINT ptlLoc, LONG lCloseHint, DWORD *pHitResult);
// STDMETHODIMP QueryHitRect(DWORD dwAspect, LPCRECT pRectBounds, LPCRECT pRectLoc, LONG lCloseHint, DWORD *pHitResult);
// STDMETHODIMP GetNaturalExtent(DWORD dwAspect, LONG lindex, DVTARGETDEVICE *ptd, HDC hicTargetDev, DVEXTENTINFO *pExtentInfo, LPSIZEL pSizel);
//
IMPLEMENT_INTERFACE_UNKNOWN(CDsoFramerControl, ViewObjectEx)
STDMETHODIMP CDsoFramerControl::XViewObjectEx::Draw(DWORD dwDrawAspect, LONG lIndex, void *pvAspect, DVTARGETDEVICE *ptd, HDC hicTargetDevice, HDC hdcDraw, LPCRECTL prcBounds, LPCRECTL prcWBounds, BOOL (__stdcall *pfnContinue)(DWORD dwContinue), DWORD dwContinue)
{
RECT rc;
int iMode = 0;
POINT pVp = {0,0};
POINT pW = {0,0};
BOOL fOptimize = FALSE;
BOOL fMetafile = FALSE;
METHOD_PROLOGUE(CDsoFramerControl, ViewObjectEx);
ODS("CDsoFramerControl::XViewObjectEx::Draw\n");
if (!((dwDrawAspect == DVASPECT_CONTENT) ||
(dwDrawAspect == DVASPECT_OPAQUE)))
return DV_E_DVASPECT;
SaveDC(hdcDraw);
// first, have to do a little bit to support printing.
if (GetDeviceCaps(hdcDraw, TECHNOLOGY) == DT_METAFILE)
{
// We are dealing with a metafile.
fMetafile = TRUE;
}
/*
// check to see if we have any flags passed in the pvAspect parameter.
if (pvAspect && ((DVASPECTINFO *)pvAspect)->cb == sizeof(DVASPECTINFO))
fOptimize = (((DVASPECTINFO *)pvAspect)->dwFlags & DVASPECTINFOFLAG_CANOPTIMIZE) ? TRUE : FALSE;
*/
// Get the draw rect, if they didn't give us one, just copy over ours
memcpy(&rc, ((prcBounds) ? (RECT*)prcBounds : &(pThis->m_rcLocation)), sizeof(RECT));
if (!fMetafile)
{
LPtoDP(hdcDraw, (POINT*)&rc, 2);
SetViewportOrgEx(hdcDraw, 0, 0, &pVp);
SetWindowOrgEx(hdcDraw, 0, 0, &pW);
iMode = SetMapMode(hdcDraw, MM_TEXT);
}
// prcWBounds is NULL and not used if we are not dealing with a metafile.
// For metafiles, we pass on rc as *prcBounds, we should also include prcWBounds
pThis->OnDraw(dwDrawAspect, hdcDraw, &rc, (RECT*)prcWBounds, hicTargetDevice, fOptimize);
// clean up the DC when we're done with it, if appropriate.
if (!fMetafile)
{
SetViewportOrgEx(hdcDraw, pVp.x, pVp.y, NULL);
SetWindowOrgEx(hdcDraw, pW.x, pW.y, NULL);
SetMapMode(hdcDraw, iMode);
}
RestoreDC(hdcDraw, -1);
return S_OK;
}
STDMETHODIMP CDsoFramerControl::XViewObjectEx::GetColorSet(DWORD dwAspect, LONG lindex, void* pvAspect, DVTARGETDEVICE *ptd, HDC hicTargetDev, LOGPALETTE** ppColorSet)
{
ODS("CDsoFramerControl::XViewObjectEx::GetColorSet\n");
return E_NOTIMPL;
}
STDMETHODIMP CDsoFramerControl::XViewObjectEx::Freeze(DWORD dwAspect, LONG lindex, void* pvAspect, DWORD* pdwFreeze)
{
ODS("CDsoFramerControl::XViewObjectEx::Freeze\n");
return E_NOTIMPL;
}
STDMETHODIMP CDsoFramerControl::XViewObjectEx::Unfreeze(DWORD dwFreeze)
{
ODS("CDsoFramerControl::XViewObjectEx::Unfreeze\n");
return E_NOTIMPL;
}
STDMETHODIMP CDsoFramerControl::XViewObjectEx::SetAdvise(DWORD dwAspect, DWORD advf, IAdviseSink* pAdviseSink)
{
METHOD_PROLOGUE(CDsoFramerControl, ViewObjectEx);
ODS("CDsoFramerControl::XViewObjectEx::SetAdvise\n");
// if it's not a content aspect, we don't support it.
if (!(dwAspect & DVASPECT_CONTENT))
return DV_E_DVASPECT;
// set up some flags [we gotta stash for GetAdvise ...]
pThis->m_fViewAdvisePrimeFirst = (advf & ADVF_PRIMEFIRST) ? TRUE : FALSE;
pThis->m_fViewAdviseOnlyOnce = (advf & ADVF_ONLYONCE) ? TRUE : FALSE;
SAFE_RELEASE_INTERFACE(pThis->m_pViewAdviseSink);
SAFE_SET_INTERFACE(pThis->m_pViewAdviseSink, pAdviseSink);
// prime them if they want it [we need to store this so they can get flags later]
if (pThis->m_fViewAdvisePrimeFirst)
pThis->ViewChanged();
return S_OK;
}
STDMETHODIMP CDsoFramerControl::XViewObjectEx::GetAdvise(DWORD* pdwAspect, DWORD* padvf, IAdviseSink** ppAdviseSink)
{
METHOD_PROLOGUE(CDsoFramerControl, ViewObjectEx);
ODS("CDsoFramerControl::XViewObjectEx::GetAdvise\n");
if (pdwAspect)
*pdwAspect = DVASPECT_CONTENT;
if (padvf)
{
*padvf = 0;
if (pThis->m_fViewAdviseOnlyOnce) *padvf |= ADVF_ONLYONCE;
if (pThis->m_fViewAdvisePrimeFirst) *padvf |= ADVF_PRIMEFIRST;
}
if (ppAdviseSink)
{ SAFE_SET_INTERFACE(*ppAdviseSink, pThis->m_pViewAdviseSink); }
return S_OK;
}
STDMETHODIMP CDsoFramerControl::XViewObjectEx::GetExtent(DWORD dwDrawAspect, LONG lindex, DVTARGETDEVICE *ptd, LPSIZEL psizel)
{
METHOD_PROLOGUE(CDsoFramerControl, ViewObjectEx);
ODS("CDsoFramerControl::XViewObjectEx::GetExtent\n");
return pThis->m_xOleObject.GetExtent(dwDrawAspect, psizel);
}
STDMETHODIMP CDsoFramerControl::XViewObjectEx::GetRect(DWORD dwAspect, LPRECTL pRect)
{
METHOD_PROLOGUE(CDsoFramerControl, ViewObjectEx);
ODS("CDsoFramerControl::XViewObjectEx::GetRect\n");
if (dwAspect != DVASPECT_CONTENT)
return DV_E_DVASPECT;
if (pRect)
{
CopyRect((LPRECT)pRect, &(pThis->m_rcLocation));
// Convert to himetric (according to docs, this is required)
DsoPixelsToHimetric(&(pRect->left), &(pRect->top));
DsoPixelsToHimetric(&(pRect->right), &(pRect->bottom));
}
return S_OK;
}
STDMETHODIMP CDsoFramerControl::XViewObjectEx::GetViewStatus(DWORD* pdwStatus)
{
ODS("CDsoFramerControl::XViewObjectEx::GetViewStatus\n");
if (pdwStatus) *pdwStatus = VIEWSTATUS_OPAQUE;
return S_OK;
}
STDMETHODIMP CDsoFramerControl::XViewObjectEx::QueryHitPoint(DWORD dwAspect, LPCRECT pRectBounds, POINT ptlLoc, LONG lCloseHint, DWORD *pHitResult)
{
// ODS("CDsoFramerControl::XViewObjectEx::QueryHitPoint\n");
if (dwAspect != DVASPECT_CONTENT) return DV_E_DVASPECT;
CHECK_NULL_RETURN(pHitResult, E_POINTER);
*pHitResult = PtInRect(pRectBounds, ptlLoc) ? HITRESULT_HIT : HITRESULT_OUTSIDE;
return S_OK;
}
STDMETHODIMP CDsoFramerControl::XViewObjectEx::QueryHitRect(DWORD dwAspect, LPCRECT pRectBounds, LPCRECT pRectLoc, LONG lCloseHint, DWORD *pHitResult)
{
RECT rc;
//ODS("CDsoFramerControl::XViewObjectEx::QueryHitRect\n");
if (dwAspect != DVASPECT_CONTENT) return DV_E_DVASPECT;
*pHitResult = IntersectRect(&rc, pRectBounds, pRectLoc) ? HITRESULT_HIT : HITRESULT_OUTSIDE;
return S_OK;
}
STDMETHODIMP CDsoFramerControl::XViewObjectEx::GetNaturalExtent(DWORD dwAspect, LONG lindex, DVTARGETDEVICE *ptd, HDC hicTargetDev, DVEXTENTINFO *pExtentInfo, LPSIZEL pSizel)
{
ODS("CDsoFramerControl::XViewObjectEx::GetNaturalExtent\n");
return E_NOTIMPL;
}
////////////////////////////////////////////////////////////////////////
//
// CDsoFramerControl::XDataObject -- IDataObject Implementation
//
// STDMETHODIMP Draw(DWORD dwAspect, LONG lindex, void *pvAspect, DVTARGETDEVICE * ptd, HDC hicTargetDev, HDC hdcDraw, const LPRECTL lprcBounds, const LPRECTL lprcWBounds, BOOL(*)(DWORD)pfnContinue, DWORD dwContinue);
// STDMETHODIMP GetData(FORMATETC *pfmtc, STGMEDIUM *pstgm);
// STDMETHODIMP GetDataHere(FORMATETC *pfmtc, STGMEDIUM *pstgm);
// STDMETHODIMP QueryGetData(FORMATETC *pfmtc);
// STDMETHODIMP GetCanonicalFormatEtc(FORMATETC *pfmtcIn, FORMATETC *pfmtcOut);
// STDMETHODIMP SetData(FORMATETC *pfmtc, STGMEDIUM *pstgm, BOOL fRelease);
// STDMETHODIMP EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC **ppenum);
// STDMETHODIMP DAdvise(FORMATETC *pfmtc, DWORD advf, IAdviseSink *psink, DWORD *pdwConnection);
// STDMETHODIMP DUnadvise(DWORD dwConnection);
// STDMETHODIMP EnumDAdvise(IEnumSTATDATA **ppenum);
//
IMPLEMENT_INTERFACE_UNKNOWN(CDsoFramerControl, DataObject)
STDMETHODIMP CDsoFramerControl::XDataObject::GetData(FORMATETC *pfmtc, STGMEDIUM *pstgm)
{
HRESULT hr;
HMETAFILE hwmf;
LPMETAFILEPICT pwmf;
HGLOBAL hmem;
SIZE sizeMetric;
RECT rc;
HDC hdc;
METHOD_PROLOGUE(CDsoFramerControl, DataObject);
TRACE2("CDsoFramerControl::XDataObject::GetData(%d,%d)\n", pfmtc->cfFormat, pfmtc->tymed);
CHECK_NULL_RETURN(pfmtc, E_POINTER); CHECK_NULL_RETURN(pstgm, E_POINTER);
// Confirm data requested is a supportted type...
if (FAILED(hr = QueryGetData(pfmtc)))
return hr;
// If caller wants a metafile of the current object, draw it...
hdc = CreateMetaFileW(NULL);
sizeMetric.cx = pThis->m_Size.cx;
sizeMetric.cy = pThis->m_Size.cy;
SetRect(&rc, 0, 0, sizeMetric.cx, sizeMetric.cy);
DsoPixelsToHimetric(&(sizeMetric.cx), &(sizeMetric.cy));
sizeMetric.cy = -(sizeMetric.cy);
SetMapMode(hdc, MM_ANISOTROPIC);
SetWindowOrgEx(hdc, 0, 0, NULL);
SetWindowExtEx(hdc, rc.right, rc.bottom, NULL);
// Delegate to same IViewObject::Draw used by most containers for metafile...
hr = pThis->m_xViewObjectEx.Draw(DVASPECT_CONTENT, -1, NULL, NULL, NULL, hdc, (RECTL*)&rc, NULL, NULL, 0);
ASSERT(SUCCEEDED(hr));
if ((hwmf = CloseMetaFile(hdc)) == NULL)
return E_UNEXPECTED;
// Now allocate the transfer medium and set the metafile...
hmem = GlobalAlloc((GMEM_SHARE|GMEM_MOVEABLE), sizeof(METAFILEPICT));
if (hmem == NULL) { DeleteMetaFile(hwmf); return STG_E_MEDIUMFULL; }
pwmf = (LPMETAFILEPICT)GlobalLock(hmem);
if (pwmf)
{
pwmf->hMF = hwmf;
pwmf->mm = MM_ANISOTROPIC;
pwmf->xExt = sizeMetric.cx;
pwmf->yExt = sizeMetric.cy;
GlobalUnlock(hmem);
}
pstgm->tymed = TYMED_MFPICT;
pstgm->hGlobal = hmem;
pstgm->pUnkForRelease = NULL;
return S_OK;
}
STDMETHODIMP CDsoFramerControl::XDataObject::GetDataHere(FORMATETC *pfmtc, STGMEDIUM *pstgm)
{
ODS("CDsoFramerControl::XDataObject::GetDataHere\n");
return DV_E_FORMATETC;
}
STDMETHODIMP CDsoFramerControl::XDataObject::QueryGetData(FORMATETC *pfmtc)
{
TRACE2("CDsoFramerControl::XDataObject::QueryGetData(%d,%d)\n", pfmtc->cfFormat, pfmtc->tymed);
CHECK_NULL_RETURN(pfmtc, E_POINTER);
if (pfmtc->cfFormat != CF_METAFILEPICT)
return DV_E_FORMATETC; // We only support WMF for IDataObj presentation.
if (pfmtc->tymed != TYMED_MFPICT)
return DV_E_TYMED; // It better be in in right format...
if (pfmtc->dwAspect != DVASPECT_CONTENT)
return DV_E_DVASPECT; // We only do content (not thumbnail or partial)...
return S_OK; // If here, it looks fine to us...
}
STDMETHODIMP CDsoFramerControl::XDataObject::GetCanonicalFormatEtc(FORMATETC *pfmtcIn, FORMATETC *pfmtcOut)
{
ODS("CDsoFramerControl::XDataObject::GetCanonicalFormatEtc\n");
return E_NOTIMPL;
}
STDMETHODIMP CDsoFramerControl::XDataObject::SetData(FORMATETC *pfmtc, STGMEDIUM *pstgm, BOOL fRelease)
{
ODS("CDsoFramerControl::XDataObject::SetData\n");
return E_NOTIMPL;
}
STDMETHODIMP CDsoFramerControl::XDataObject::EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC **ppenum)
{
ODS("CDsoFramerControl::XDataObject::EnumFormatEtc\n");
return OleRegEnumFormatEtc(CLSID_FramerControl, dwDirection, ppenum);
}
STDMETHODIMP CDsoFramerControl::XDataObject::DAdvise(FORMATETC *pfmtc, DWORD advf, IAdviseSink *psink, DWORD *pdwConnection)
{
METHOD_PROLOGUE(CDsoFramerControl, DataObject);
ODS("CDsoFramerControl::XDataObject::DAdvise\n");
// Create OLE Data advise holder to keep sink for us...
if ((NULL == pThis->m_pDataAdviseHolder) &&
FAILED(CreateDataAdviseHolder(&(pThis->m_pDataAdviseHolder))))
return E_FAIL;
// Add this advise sink for the given format to the collection...
return pThis->m_pDataAdviseHolder->Advise((IDataObject*)&(pThis->m_xDataObject), pfmtc, advf, psink, pdwConnection);
}
STDMETHODIMP CDsoFramerControl::XDataObject::DUnadvise(DWORD dwConnection)
{
METHOD_PROLOGUE(CDsoFramerControl, DataObject);
ODS("CDsoFramerControl::XDataObject::DUnadvise\n");
CHECK_NULL_RETURN(pThis->m_pDataAdviseHolder, CONNECT_E_NOCONNECTION);
return pThis->m_pDataAdviseHolder->Unadvise(dwConnection);
}
STDMETHODIMP CDsoFramerControl::XDataObject::EnumDAdvise(IEnumSTATDATA **ppenum)
{
METHOD_PROLOGUE(CDsoFramerControl, DataObject);
ODS("CDsoFramerControl::XDataObject::EnumDAdvise\n");
CHECK_NULL_RETURN(pThis->m_pDataAdviseHolder, CONNECT_E_NOCONNECTION);
return pThis->m_pDataAdviseHolder->EnumAdvise(ppenum);
}
////////////////////////////////////////////////////////////////////////
//
// CDsoFramerControl::XProvideClassInfo -- IProvideClassInfo Implementation
//
// STDMETHODIMP GetClassInfo(ITypeInfo** ppTI);
//
IMPLEMENT_INTERFACE_UNKNOWN(CDsoFramerControl, ProvideClassInfo)
STDMETHODIMP CDsoFramerControl::XProvideClassInfo::GetClassInfo(ITypeInfo** ppTI)
{
ODS("CDsoFramerControl::XProvideClassInfo::GetClassInfo\n");
return DsoGetTypeInfoEx(LIBID_DSOFramer, 0,
DSOFRAMERCTL_VERSION_MAJOR, DSOFRAMERCTL_VERSION_MINOR, v_hModule, CLSID_FramerControl, ppTI);
}
////////////////////////////////////////////////////////////////////////
//
// CDsoFramerControl::XConnectionPointContainer -- IConnectionPointContainer Implementation
//
// STDMETHODIMP EnumConnectionPoints(IEnumConnectionPoints **ppEnum);
// STDMETHODIMP FindConnectionPoint(REFIID riid, IConnectionPoint **ppCP);
//
IMPLEMENT_INTERFACE_UNKNOWN(CDsoFramerControl, ConnectionPointContainer)
STDMETHODIMP CDsoFramerControl::XConnectionPointContainer::EnumConnectionPoints(IEnumConnectionPoints **ppEnum)
{
METHOD_PROLOGUE(CDsoFramerControl, ConnectionPointContainer);
ODS("CDsoFramerControl::XConnectionPointContainer::EnumConnectionPoints\n");
if (ppEnum) { SAFE_SET_INTERFACE(*ppEnum, &(pThis->m_xEnumConnectionPoints)); };
return S_OK;
}
STDMETHODIMP CDsoFramerControl::XConnectionPointContainer::FindConnectionPoint(REFIID riid, IConnectionPoint **ppCP)
{
METHOD_PROLOGUE(CDsoFramerControl, ConnectionPointContainer);
ODS("CDsoFramerControl::XConnectionPointContainer::FindConnectionPoint\n");
if (riid != DIID__DFramerCtlEvents) return CONNECT_E_NOCONNECTION;
if (ppCP) { SAFE_SET_INTERFACE(*ppCP, &(pThis->m_xConnectionPoint)); };
return S_OK;
}
////////////////////////////////////////////////////////////////////////
//
// CDsoFramerControl::XEnumConnectionPoints -- IEnumConnectionPoints Implementation
//
// STDMETHODIMP Next(ULONG cConnections, IConnectionPoint **rgpcn, ULONG *pcFetched);
// STDMETHODIMP Skip(ULONG cConnections);
// STDMETHODIMP Reset(void);
// STDMETHODIMP Clone(IEnumConnectionPoints **ppEnum);
//
IMPLEMENT_INTERFACE_UNKNOWN(CDsoFramerControl, EnumConnectionPoints)
STDMETHODIMP CDsoFramerControl::XEnumConnectionPoints::Next(ULONG cConnections, IConnectionPoint **rgpcn, ULONG *pcFetched)
{
HRESULT hr = S_FALSE;
METHOD_PROLOGUE(CDsoFramerControl, EnumConnectionPoints);
ODS("CDsoFramerControl::XEnumConnectionPoints::Next\n");
CHECK_NULL_RETURN(rgpcn, E_POINTER);
*rgpcn = NULL;
CHECK_NULL_RETURN(pcFetched, E_POINTER);
*pcFetched = 0;
if (pThis->m_fConCntDone)
pThis->m_fConCntDone = FALSE;
else
{
SAFE_SET_INTERFACE(*rgpcn, &(pThis->m_xConnectionPoint));
*pcFetched = 1;
pThis->m_fConCntDone = TRUE; hr = S_OK;
}
return hr;
}
STDMETHODIMP CDsoFramerControl::XEnumConnectionPoints::Skip(ULONG cConnections)
{return S_OK;}
STDMETHODIMP CDsoFramerControl::XEnumConnectionPoints::Reset(void)
{return S_OK;}
STDMETHODIMP CDsoFramerControl::XEnumConnectionPoints::Clone(IEnumConnectionPoints **ppEnum)
{if (ppEnum) *ppEnum = this; return S_OK;}
////////////////////////////////////////////////////////////////////////
//
// CDsoFramerControl::XConnectionPoint -- IConnectionPoint Implementation
//
// STDMETHODIMP GetConnectionInterface(IID *pIID);
// STDMETHODIMP GetConnectionPointContainer(IConnectionPointContainer **ppCPC);
// STDMETHODIMP Advise(IUnknown *pUnk, DWORD *pdwCookie);
// STDMETHODIMP Unadvise(DWORD dwCookie);
// STDMETHODIMP EnumConnections(IEnumConnections **ppEnum);
//
IMPLEMENT_INTERFACE_UNKNOWN(CDsoFramerControl, ConnectionPoint)
STDMETHODIMP CDsoFramerControl::XConnectionPoint::GetConnectionInterface(IID *pIID)
{
ODS("CDsoFramerControl::XConnectionPoint::GetConnectionInterface\n");
if (pIID) *pIID = DIID__DFramerCtlEvents;
return S_OK;
}
STDMETHODIMP CDsoFramerControl::XConnectionPoint::GetConnectionPointContainer(IConnectionPointContainer **ppCPC)
{
METHOD_PROLOGUE(CDsoFramerControl, ConnectionPoint);
ODS("CDsoFramerControl::XConnectionPoint::GetConnectionPointContainer\n");
if (ppCPC) { SAFE_SET_INTERFACE(*ppCPC, &(pThis->m_xConnectionPointContainer)); };
return S_OK;
}
STDMETHODIMP CDsoFramerControl::XConnectionPoint::Advise(IUnknown *pUnk, DWORD *pdwCookie)
{
METHOD_PROLOGUE(CDsoFramerControl, ConnectionPoint);
ODS("CDsoFramerControl::XConnectionPoint::Advise\n");
CHECK_NULL_RETURN(pUnk, E_POINTER);
CHECK_NULL_RETURN(pdwCookie, E_POINTER);
SAFE_RELEASE_INTERFACE(pThis->m_dispEvents);
// FIX: The COM Interop layer in .NET CLR returns a different RCW for IDispatch than for a specific
// dispinterface GUID, so for events to work in .NET WinForm applications, we should explicitly use
// the RCW for that dispinterface. Other event source clients may fail QI for this GUID, so if it
// does return an error, we will QI again for IDispatch. The event issue is change in behavior from
// how VB6 implemented event sinks, and how VB7/C# does them...
HRESULT hr = pUnk->QueryInterface(DIID__DFramerCtlEvents, (void**)&(pThis->m_dispEvents));
if (FAILED(hr)) hr = pUnk->QueryInterface(IID_IDispatch, (void**)&(pThis->m_dispEvents));
if (SUCCEEDED(hr)) *pdwCookie = (DWORD)(pThis);
return hr;
}
STDMETHODIMP CDsoFramerControl::XConnectionPoint::Unadvise(DWORD dwCookie)
{
METHOD_PROLOGUE(CDsoFramerControl, ConnectionPoint);
ODS("CDsoFramerControl::XConnectionPoint::Unadvise\n");
if (dwCookie == (DWORD)(pThis))
{
SAFE_RELEASE_INTERFACE(pThis->m_dispEvents);
}
return (pThis->m_dispEvents == NULL) ? S_OK : CONNECT_E_NOCONNECTION;
}
STDMETHODIMP CDsoFramerControl::XConnectionPoint::EnumConnections(IEnumConnections **ppEnum)
{if (ppEnum) *ppEnum = NULL; return E_NOTIMPL;}
////////////////////////////////////////////////////////////////////////
//
// CDsoFramerControl::XOleCommandTarget -- IOleCommandTarget Implementation
//
// STDMETHODIMP QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText);
// STDMETHODIMP Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG *pvaIn, VARIANTARG *pvaOut);
//
IMPLEMENT_INTERFACE_UNKNOWN(CDsoFramerControl, OleCommandTarget)
STDMETHODIMP CDsoFramerControl::XOleCommandTarget::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText)
{
METHOD_PROLOGUE(CDsoFramerControl, OleCommandTarget);
//ODS("CDsoFramerControl::XOleCommandTarget::QueryStatus\n");
if (pguidCmdGroup != NULL)
return OLECMDERR_E_UNKNOWNGROUP;
if (prgCmds == NULL)
return E_INVALIDARG;
for (int i = 0; i < (int)cCmds; i++)
{
switch (prgCmds[i].cmdID)
{
case OLECMDID_NEW: prgCmds[i].cmdf = (((pThis->m_wFileMenuFlags & 1) ? OLECMDF_ENABLED : 0) | OLECMDF_SUPPORTED); break;
case OLECMDID_OPEN: prgCmds[i].cmdf = (((pThis->m_wFileMenuFlags & 2) ? OLECMDF_ENABLED : 0) | OLECMDF_SUPPORTED); break;
case OLECMDID_SAVE: prgCmds[i].cmdf = (((pThis->m_wFileMenuFlags & 8) ? OLECMDF_ENABLED : 0) | OLECMDF_SUPPORTED); break;
case OLECMDID_SAVEAS: prgCmds[i].cmdf = (((pThis->m_wFileMenuFlags & 16) ? OLECMDF_ENABLED : 0) | OLECMDF_SUPPORTED); break;
case OLECMDID_PRINT: prgCmds[i].cmdf = (((pThis->m_wFileMenuFlags & 32) ? OLECMDF_ENABLED : 0) | OLECMDF_SUPPORTED); break;
case OLECMDID_PAGESETUP: prgCmds[i].cmdf = (((pThis->m_wFileMenuFlags & 64) ? OLECMDF_ENABLED : 0) | OLECMDF_SUPPORTED); break;
case OLECMDID_PROPERTIES: prgCmds[i].cmdf = (((pThis->m_wFileMenuFlags & 128) ? OLECMDF_ENABLED : 0) | OLECMDF_SUPPORTED); break;
case OLECMDID_PRINTPREVIEW: prgCmds[i].cmdf = (((pThis->m_wFileMenuFlags & 256) ? OLECMDF_ENABLED : 0) | OLECMDF_SUPPORTED); break;
default: prgCmds[i].cmdf = 0;
}
}
if (pCmdText)
{
pCmdText->cmdtextf = MSOCMDTEXTF_NONE;
pCmdText->cwActual = 0;
}
return S_OK;
}
STDMETHODIMP CDsoFramerControl::XOleCommandTarget::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG *pvaIn, VARIANTARG *pvaOut)
{
METHOD_PROLOGUE(CDsoFramerControl, OleCommandTarget);
ODS("CDsoFramerControl::XOleCommandTarget::Exec\n");
if ((pguidCmdGroup != NULL) && (*pguidCmdGroup != GUID_NULL))
return OLECMDERR_E_UNKNOWNGROUP;
if (nCmdexecopt == MSOCMDEXECOPT_SHOWHELP)
return OLECMDERR_E_NOHELP;
switch (nCmdID)
{
case OLECMDID_NEW:
case OLECMDID_OPEN:
case OLECMDID_SAVE:
case OLECMDID_SAVEAS:
case OLECMDID_PRINT:
case OLECMDID_PAGESETUP:
case OLECMDID_PROPERTIES:
case OLECMDID_PRINTPREVIEW:
PostMessage(pThis->m_hwnd, DSO_WM_ASYNCH_OLECOMMAND, nCmdID, nCmdexecopt);
return S_OK;
}
return OLECMDERR_E_NOTSUPPORTED;
}
////////////////////////////////////////////////////////////////////////
//
// CDsoFramerControl::XSupportErrorInfo -- ISupportErrorInfo Implementation
//
// STDMETHODIMP InterfaceSupportsErrorInfo(REFIID riid);
//
IMPLEMENT_INTERFACE_UNKNOWN(CDsoFramerControl, SupportErrorInfo)
STDMETHODIMP CDsoFramerControl::XSupportErrorInfo::InterfaceSupportsErrorInfo(REFIID riid)
{
ODS("CDsoFramerControl::XSupportErrorInfo::InterfaceSupportsErrorInfo\n");
return ((riid == IID__FramerControl) ? S_OK : E_FAIL);
}
////////////////////////////////////////////////////////////////////////
//
// CDsoFramerControl::XObjectSafety -- IObjectSafety Implementation
//
// STDMETHODIMP GetInterfaceSafetyOptions(REFIID riid, DWORD *pdwSupportedOptions,DWORD *pdwEnabledOptions);
// STDMETHODIMP SetInterfaceSafetyOptions(REFIID riid, DWORD dwOptionSetMask, DWORD dwEnabledOptions);
//
IMPLEMENT_INTERFACE_UNKNOWN(CDsoFramerControl, ObjectSafety)
STDMETHODIMP CDsoFramerControl::XObjectSafety::GetInterfaceSafetyOptions(REFIID riid, DWORD *pdwSupportedOptions,DWORD *pdwEnabledOptions)
{
ODS("CDsoFramerControl::XObjectSafety::GetInterfaceSafetyOptions\n");
CHECK_NULL_RETURN(pdwEnabledOptions, E_POINTER);
if (pdwSupportedOptions)
*pdwSupportedOptions = (INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACESAFE_FOR_UNTRUSTED_CALLER);
// We are safe for initialization, but not necessarily for scripting. Since script
// can open documents with macros, and get access to Office OM via ActiveDocument,
// we cannot be "safe" for malicious script. But this allows the control to load
// without prompt (just not scripted without prompt)...
*pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA;
return S_OK;
}
STDMETHODIMP CDsoFramerControl::XObjectSafety::SetInterfaceSafetyOptions(REFIID riid, DWORD dwOptionSetMask, DWORD dwEnabledOptions)
{
ODS("CDsoFramerControl::XObjectSafety::SetInterfaceSafetyOptions\n");
return ((((riid == IID_IPersist) || (riid == IID_IPersistPropertyBag)) &&
(dwEnabledOptions == INTERFACESAFE_FOR_UNTRUSTED_DATA)) ? S_OK : E_FAIL);
}
////////////////////////////////////////////////////////////////////////
//
// CDsoFramerControl::XDsoDocObjectSite -- IDsoDocObjectSite Implementation
//
// STDMETHODIMP GetWindow(HWND* phWnd);
// STDMETHODIMP GetBorder(LPRECT prcBorder);
// STDMETHODIMP SetStatusText(LPCOLESTR pszText);
// STDMETHODIMP GetHostName(LPWSTR *ppwszHostName);
//
IMPLEMENT_INTERFACE_UNKNOWN(CDsoFramerControl, DsoDocObjectSite)
STDMETHODIMP CDsoFramerControl::XDsoDocObjectSite::QueryService(REFGUID guidService, REFIID riid, void **ppv)
{
HRESULT hr = E_NOINTERFACE;
ODS("CDsoFramerControl::XDsoDocObjectSite::QueryService\n");
METHOD_PROLOGUE(CDsoFramerControl, DsoDocObjectSite);
CHECK_NULL_RETURN(ppv, E_POINTER);
// We will return control IDispatch for cross container automation...
if (guidService == SID_SContainerDispatch)
{
ODS(" -- Container Dispatch Given --\n");
hr = pThis->QueryInterface(riid, ppv);
}
// TODO: Support IHlinkFrame services for cross hyperlinking inside control??
// If we don't handle the call, and our host has a provider, pass the call along to see
// if the top-level host offers the service requested (like hyperlinking to new web page)...
if (FAILED(hr) && (pThis->m_pClientSite))
{
IServiceProvider *pprov = NULL;
if (SUCCEEDED(pThis->m_pClientSite->QueryInterface(IID_IServiceProvider, (void**)&pprov)) && (pprov))
{
if (SUCCEEDED(hr = pprov->QueryService(guidService, riid, ppv)))
{ ODS(" -- Service provided by top-level host --\n"); }
pprov->Release();
}
}
return hr;
}
STDMETHODIMP CDsoFramerControl::XDsoDocObjectSite::GetWindow(HWND* phWnd)
{
METHOD_PROLOGUE(CDsoFramerControl, DsoDocObjectSite);
ODS("CDsoFramerControl::XDsoDocObjectSite::GetWindow\n");
if (phWnd) *phWnd = pThis->m_hwnd;
return S_OK;
}
STDMETHODIMP CDsoFramerControl::XDsoDocObjectSite::GetBorder(LPRECT prcBorder)
{
METHOD_PROLOGUE(CDsoFramerControl, DsoDocObjectSite);
ODS("CDsoFramerControl::XDsoDocObjectSite::GetBorder\n");
pThis->GetSizeRectForDocument(NULL, prcBorder);
return S_OK;
}
STDMETHODIMP CDsoFramerControl::XDsoDocObjectSite::GetHostName(LPWSTR *ppwszHostName)
{
METHOD_PROLOGUE(CDsoFramerControl, DsoDocObjectSite);
ODS("CDsoFramerControl::XDsoDocObjectSite::GetHostName\n");
if (ppwszHostName) *ppwszHostName = DsoCopyString(pThis->m_pwszHostName);
return S_OK;
}
STDMETHODIMP CDsoFramerControl::XDsoDocObjectSite::SysMenuCommand(UINT uiCharCode)
{
METHOD_PROLOGUE(CDsoFramerControl, DsoDocObjectSite);
TRACE1("CDsoFramerControl::XDsoDocObjectSite::SysMenuCommand(%x)\n", uiCharCode);
// If we are processing a sys menu command, see if it is a menu accel for our
// displayed menu, and if so we handle this with a fake click of the menu button...
if ((uiCharCode) && (pThis->m_fShowMenuBar) && !(pThis->m_fDisableMenuAccel))
{
UINT i;
CHAR *pch;
// Loop all the menu items and check against their accelerators...
for (i = 0; i < DSO_MAX_MENUITEMS; i++)
{
pch = &(pThis->m_rgchMenuAccel[0]);
if (*pch)
{
if ((*pch != 0xFF) && ((UINT)(*pch) == ASCII_LOWERCASE(uiCharCode)))
{
// Found one that match, so fake mouse move and button down/up to run click code...
ODS("-- Trigger Menu Accelerator --\n");
PostMessage(pThis->m_hwnd, WM_MOUSEMOVE, (WPARAM)0,
MAKELPARAM(pThis->m_rgrcMenuItems[i].left + 1, pThis->m_rgrcMenuItems[i].top + 1));
PostMessage(pThis->m_hwnd, WM_LBUTTONDOWN, (WPARAM)MK_LBUTTON,
MAKELPARAM(pThis->m_rgrcMenuItems[i].left + 1, pThis->m_rgrcMenuItems[i].top + 1));
PostMessage(pThis->m_hwnd, WM_LBUTTONUP, (WPARAM)0,
MAKELPARAM(pThis->m_rgrcMenuItems[i].left + 1, pThis->m_rgrcMenuItems[i].top + 1));
// Return OK to caller to know to eat this message.
return S_OK;
}
}
else break;
}
}
return S_FALSE;
}
STDMETHODIMP CDsoFramerControl::XDsoDocObjectSite::SetStatusText(LPCOLESTR pszText)
{
METHOD_PROLOGUE(CDsoFramerControl, DsoDocObjectSite);
// If m_fActivateOnStatus flag is set, see if we are not UI active. If not, try to activate...
if ((pThis->m_fActivateOnStatus) && (pThis->m_fComponentActive) && (pThis->m_fAppActive) &&
!(pThis->m_fUIActive) && !(pThis->m_fModalState))
{
ODS(" -- ForceUIActiveFromSetStatusText --\n");
pThis->m_fActivateOnStatus = FALSE;
pThis->Activate();
}
return S_OK;
}
////////////////////////////////////////////////////////////////////////
// CDsoFrameHookManager
//
CDsoFrameHookManager* vgGlobalManager = NULL;
////////////////////////////////////////////////////////////////////////
// CDsoFrameHookManager::RegisterFramerControl
//
// Creates a frame hook and registers it with the active manager. If
// this is the first time called, the global manager will be created
// now. The manager can handle up to DSOF_MAX_CONTROLS controls (10).
//
STDMETHODIMP_(CDsoFrameHookManager*) CDsoFrameHookManager::RegisterFramerControl(HWND hwndParent, HWND hwndControl)
{
CDsoFrameHookManager* pManager = NULL;
ODS("CDsoFrameHookManager::RegisterFramerControl\n");
CHECK_NULL_RETURN(hwndControl, NULL);
EnterCriticalSection(&v_csecThreadSynch);
pManager = vgGlobalManager;
if (pManager == NULL)
pManager = (vgGlobalManager = new CDsoFrameHookManager());
LeaveCriticalSection(&v_csecThreadSynch);
if (pManager)
{
if (hwndParent == NULL)
hwndParent = hwndControl;
if (FAILED(pManager->AddComponent(hwndParent, hwndControl)))
return NULL;
}
return pManager;
}
////////////////////////////////////////////////////////////////////////
// CDsoFrameHookManager::AddComponent
//
// Register the component and create the actual frame hook (if needed).
//
STDMETHODIMP CDsoFrameHookManager::AddComponent(HWND hwndParent, HWND hwndControl)
{
DWORD dwHostProcessID;
CDsoFrameWindowHook* phook;
HRESULT hr = E_OUTOFMEMORY;
HWND hwndNext, hwndHost = hwndParent;
ODS("CDsoFrameHookManager::AddComponent\n");
// Find the top-level window this control is sited on...
while (hwndNext = GetParent(hwndHost))
hwndHost = hwndNext;
// We have to get valid window that is in-thread for a subclass to work...
if (!IsWindow(hwndHost) ||
(GetWindowThreadProcessId(hwndHost, &dwHostProcessID),
dwHostProcessID != GetCurrentProcessId()))
return E_ACCESSDENIED;
// Next if we have room in the array, add the component to the list and
// hook its parent window so we get messages for it.
EnterCriticalSection(&v_csecThreadSynch);
if ((vgGlobalManager) && (m_cComponents < DSOF_MAX_CONTROLS))
{
// Hook the host window for this control...
phook = CDsoFrameWindowHook::AttachToFrameWindow(hwndHost);
if (phook)
{// Add the component to the list if hooked...
m_pComponents[m_cComponents].hwndControl = hwndControl;
m_pComponents[m_cComponents].phookFrame = phook;
m_cComponents++; hr = S_OK;
}
}
LeaveCriticalSection(&v_csecThreadSynch);
if (SUCCEEDED(hr)) // Make sure item is the new active component
hr = SetActiveComponent(hwndControl);
return hr;
}
STDMETHODIMP CDsoFrameHookManager::DetachComponent(HWND hwndControl)
{
DWORD dwIndex;
CHECK_NULL_RETURN(m_cComponents, E_FAIL);
// Find this control in the list...
for (dwIndex = 0; dwIndex < m_cComponents; dwIndex++)
if (m_pComponents[dwIndex].hwndControl == hwndControl) break;
if (dwIndex > m_cComponents)
return E_INVALIDARG;
// If we found the index, remove the item and shift remaining
// items down the list. Change active index as needed...
EnterCriticalSection(&v_csecThreadSynch);
m_pComponents[dwIndex].hwndControl = NULL;
m_pComponents[dwIndex].phookFrame->Detach();
// Compact the list...
while (++dwIndex < m_cComponents)
{
m_pComponents[dwIndex-1].hwndControl = m_pComponents[dwIndex].hwndControl;
m_pComponents[dwIndex-1].phookFrame = m_pComponents[dwIndex].phookFrame;
m_pComponents[dwIndex].hwndControl = NULL;
}
// Decrement the count. If count still exists, forward activation
// to next component in the list...
if (--m_cComponents)
{
while (m_idxActive >= m_cComponents)
--m_idxActive;
HWND hwndActive = GetActiveComponentWindow();
if (hwndActive)
SendNotifyMessage(hwndActive, DSO_WM_HOOK_NOTIFY_COMPACTIVE, (WPARAM)TRUE, (LPARAM)(m_fAppActive));
}
else
{
vgGlobalManager = NULL;
// If this is the last control, we can remove the manger!
delete this;
}
LeaveCriticalSection(&v_csecThreadSynch);
return S_OK;
}
STDMETHODIMP CDsoFrameHookManager::SetActiveComponent(HWND hwndControl)
{
ODS(" -- CDsoFrameHookManager::SetActiveComponent -- \n");
CHECK_NULL_RETURN(m_cComponents, E_FAIL);
DWORD dwIndex;
// Find the index of the control...
for (dwIndex = 0; dwIndex < m_cComponents; dwIndex++)
if (m_pComponents[dwIndex].hwndControl == hwndControl) break;
if (dwIndex > m_cComponents)
return E_INVALIDARG;
// If it is not already the active item, notify old component it is
// losing activation, and notify new component that it is gaining...
EnterCriticalSection(&v_csecThreadSynch);
if (dwIndex != m_idxActive)
{
HWND hwndActive = GetActiveComponentWindow();
if (hwndActive)
SendNotifyMessage(hwndActive, DSO_WM_HOOK_NOTIFY_COMPACTIVE, (WPARAM)FALSE, (LPARAM)0);
m_idxActive = dwIndex;
hwndActive = GetActiveComponentWindow();
if (hwndActive)
SendNotifyMessage(hwndActive, DSO_WM_HOOK_NOTIFY_COMPACTIVE, (WPARAM)TRUE, (LPARAM)(m_fAppActive));
}
LeaveCriticalSection(&v_csecThreadSynch);
return S_OK;
}
STDMETHODIMP CDsoFrameHookManager::OnComponentNotify(DWORD msg, WPARAM wParam, LPARAM lParam)
{
TRACE3("CDsoFrameHookManager::OnComponentNotify(%d, %d, %d)\n", msg, wParam, lParam);
HWND hwndActiveComp = GetActiveComponentWindow();
// The manager needs to keep track of AppActive state...
if (msg == DSO_WM_HOOK_NOTIFY_APPACTIVATE)
{
EnterCriticalSection(&v_csecThreadSynch);
m_fAppActive = (BOOL)wParam;
LeaveCriticalSection(&v_csecThreadSynch);
}
// Send the message to the active component
SendNotifyMessage(hwndActiveComp, msg, wParam, lParam);
return S_OK;
}
STDMETHODIMP_(BOOL) CDsoFrameHookManager::SendNotifyMessage(HWND hwnd, DWORD msg, WPARAM wParam, LPARAM lParam)
{
BOOL fResult;
// Check if the caller is on the same thread as the active component. If so we can
// forward the message directly for processing. If not, we have to post and wait for
// that thread to process message at a later time...
if (GetWindowThreadProcessId(hwnd, NULL) == GetCurrentThreadId())
{ // Notify now...
fResult = (BOOL)SendMessage(hwnd, msg, wParam, lParam);
}
else
{ // Notify later...
fResult = PostMessage(hwnd, msg, wParam, lParam);
}
return fResult;
}
////////////////////////////////////////////////////////////////////////
// CDsoFrameWindowHook
//
////////////////////////////////////////////////////////////////////////
// CDsoFrameWindowHook::AttachToFrameWindow
//
// Creates the frame hook for the host window.
//
STDMETHODIMP_(CDsoFrameWindowHook*) CDsoFrameWindowHook::AttachToFrameWindow(HWND hwndParent)
{
CDsoFrameWindowHook* phook = NULL;
BOOL fHookSuccess = FALSE;
// We have to get valid window ...
if (!IsWindow(hwndParent))
return NULL;
EnterCriticalSection(&v_csecThreadSynch);
phook = CDsoFrameWindowHook::GetHookFromWindow(hwndParent);
if (phook)
{ // Already have this window hooked, so just addref the count.
phook->AddRef();
}
else
{ // Need to create a new hook object for this window...
if ((phook = new CDsoFrameWindowHook()))
{
phook->m_hwndTopLevelHost = hwndParent;
phook->m_fHostUnicodeWindow = (v_fUnicodeAPI && IsWindowUnicode(hwndParent));
// Setup the subclass using Unicode or Ansi methods depending on window
// create state. Note if either property assoc or window subclass fail...
if (phook->m_fHostUnicodeWindow)
{
fHookSuccess = SetPropW(hwndParent, L"DSOFramerWndHook", (HANDLE)phook);
if (fHookSuccess)
{
phook->m_pfnOrigWndProc = (WNDPROC)SetWindowLongW(hwndParent, GWL_WNDPROC, (LONG)(WNDPROC)HostWindowProcHook);
fHookSuccess = (phook->m_pfnOrigWndProc != NULL);
}
}
else
{
fHookSuccess = SetPropA(hwndParent, "DSOFramerWndHook", (HANDLE)phook);
if (fHookSuccess)
{
phook->m_pfnOrigWndProc = (WNDPROC)SetWindowLongA(hwndParent, GWL_WNDPROC, (LONG)(WNDPROC)HostWindowProcHook);
fHookSuccess = (phook->m_pfnOrigWndProc != NULL);
}
}
// If we failed the subclass, kill this object and return error...
if (!fHookSuccess)
{
delete phook;
phook = NULL;
}
else phook->m_cHookCount++;
}
}
LeaveCriticalSection(&v_csecThreadSynch);
return phook;
}
////////////////////////////////////////////////////////////////////////
// CDsoFrameWindowHook::Detach
//
// Removes the hook from the frame window if this is the last control
// to reference the hook.
//
STDMETHODIMP CDsoFrameWindowHook::Detach()
{
// Only need to call this if item is attached.
EnterCriticalSection(&v_csecThreadSynch);
if (m_cHookCount)
{
if (--m_cHookCount == 0)
{ // We can remove the hook!
if (m_fHostUnicodeWindow)
{
SetWindowLongW(m_hwndTopLevelHost, GWL_WNDPROC, (LONG)(m_pfnOrigWndProc));
RemovePropW(m_hwndTopLevelHost, L"DSOFramerWndHook");
}
else
{
SetWindowLongA(m_hwndTopLevelHost, GWL_WNDPROC, (LONG)(m_pfnOrigWndProc));
RemovePropA(m_hwndTopLevelHost, "DSOFramerWndHook");
}
m_hwndTopLevelHost = NULL;
// we can kill this object now...
delete this;
}
}
LeaveCriticalSection(&v_csecThreadSynch);
return S_OK;
}
////////////////////////////////////////////////////////////////////////
// CDsoFrameWindowHook::GetHookFromWindow
//
// Returns the hook control associated with this object.
//
STDMETHODIMP_(CDsoFrameWindowHook*) CDsoFrameWindowHook::GetHookFromWindow(HWND hwnd)
{
CDsoFrameWindowHook* phook = (CDsoFrameWindowHook*)GetPropW(hwnd, L"DSOFramerWndHook");
if (phook == NULL) phook = (CDsoFrameWindowHook*)GetPropA(hwnd, "DSOFramerWndHook");
return phook;
}
////////////////////////////////////////////////////////////////////////
// CDsoFrameWindowHook::HostWindowProcHook
//
// The window proc for the subclassed host window.
//
STDMETHODIMP_(LRESULT) CDsoFrameWindowHook::HostWindowProcHook(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
CDsoFrameWindowHook* phook = CDsoFrameWindowHook::GetHookFromWindow(hwnd);
if (phook) // We better get our prop for this window!
{
// We handle the important ActiveDocument frame-level events like task
// window activation/deactivation, palette change notfication, and key/mouse
// focus notification on host app focus...
switch (msg)
{
case WM_ACTIVATEAPP:
if (vgGlobalManager)
vgGlobalManager->OnComponentNotify(DSO_WM_HOOK_NOTIFY_APPACTIVATE, wParam, lParam);
break;
case WM_PALETTECHANGED:
if (vgGlobalManager)
vgGlobalManager->OnComponentNotify(DSO_WM_HOOK_NOTIFY_PALETTECHANGE, wParam, lParam);
break;
case WM_SYNCPAINT:
if (vgGlobalManager)
vgGlobalManager->OnComponentNotify(DSO_WM_HOOK_NOTIFY_SYNCPAINT, wParam, lParam);
break;
}
// After processing, allow calls to fall through to host app. We need to call
// the appropriate handler for Unicode or non-Unicode windows...
if (phook->m_fHostUnicodeWindow)
return CallWindowProcW(phook->m_pfnOrigWndProc, hwnd, msg, wParam, lParam);
else
return CallWindowProcA(phook->m_pfnOrigWndProc, hwnd, msg, wParam, lParam);
}
// Should not be reached, but just in case call default proc...
return (IsWindowUnicode(hwnd) ?
DefWindowProcW(hwnd, msg, wParam, lParam) :
DefWindowProcA(hwnd, msg, wParam, lParam));
}