📄 ctlcore.cpp
字号:
WORD buf[WORDBUFSIZE];
WORD i;
WORD pat;
for (i = 0, pat = 0x0100; i < WORDBUFSIZE; i++, pat += 0x0202)
buf[i] = pat;
}
void COleControl::DoSuperclassPaint(CDC* pDC, const CRect& rcBounds)
{
if (m_hWnd == NULL)
CreateWindowForSubclassedControl();
if (m_hWnd != NULL)
{
CRect rcClient;
GetClientRect(&rcClient);
if (rcClient.Size() != rcBounds.Size())
{
pDC->SetMapMode(MM_ANISOTROPIC);
pDC->SetWindowExt(rcClient.right, rcClient.bottom);
pDC->SetViewportExt(rcBounds.Size());
}
pDC->SetWindowOrg(0, 0);
pDC->SetViewportOrg(rcBounds.left, rcBounds.top);
BOOL bWin4 = afxData.bWin4;
_AfxFillPSOnStack();
::CallWindowProc(
*GetSuperWndProcAddr(),
m_hWnd, (bWin4 ? WM_PRINT : WM_PAINT),
(WPARAM)(pDC->m_hDC),
(LPARAM)(bWin4 ? PRF_CHILDREN | PRF_CLIENT : 0));
}
}
BOOL COleControl::IsSubclassedControl()
{
// This default implementation provides some degree of backward
// compatibility with old controls. New subclassed controls should just
// override IsSubclassedControl and return TRUE.
return m_pfnSuper == NULL &&
GetSuperWndProcAddr() != CWnd::GetSuperWndProcAddr();
}
BOOL COleControl::CreateControlWindow(HWND hWndParent, const CRect& rcPos,
LPCRECT prcClip)
{
if (m_hWnd == NULL)
{
// If window doesn't exist, create it.
// Test if:
// we're not subclassing a Windows control, or
// container reflects messages for us...
DWORD dwStyle = WS_VISIBLE|WS_CHILD|WS_CLIPSIBLINGS|WS_CLIPCHILDREN;
if (m_sBorderStyle)
dwStyle |= WS_BORDER;
if (!m_bEnabled)
dwStyle |= WS_DISABLED;
DWORD dwExStyle = WS_EX_NOPARENTNOTIFY;
if (m_sAppearance)
dwExStyle |= WS_EX_CLIENTEDGE;
// we create normally if:
// (we're not subclassing -or- the container reflects)
// -and- the container autoclips for us
if ((!IsSubclassedControl() || m_bMsgReflect) && m_bAutoClip)
{
// Just create the control's window.
VERIFY(AfxDeferRegisterClass(AFX_WNDOLECONTROL_REG));
CreateEx(dwExStyle, AFX_WNDOLECONTROL, m_strText, dwStyle,
rcPos.left, rcPos.top, rcPos.Width(), rcPos.Height(),
hWndParent, 0);
}
else // ...we're subclassing a Windows control.
{
if (m_pReflect == NULL)
{
// Create a window to reflect notification messages.
m_pReflect = new CReflectorWnd;
if (prcClip == NULL)
prcClip = rcPos;
if (!m_pReflect->Create(prcClip, hWndParent))
{
// If m_pReflect->Create failed, then m_pReflect deleted itself.
m_pReflect = NULL;
}
}
else
{
// Reflector window already exists... just reparent it.
if (m_pReflect->m_hWnd != NULL)
{
::SetParent(m_pReflect->m_hWnd, hWndParent);
::SetWindowPos(m_pReflect->m_hWnd, NULL, 0, 0, 0, 0,
SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|
SWP_SHOWWINDOW);
}
}
if (m_pReflect != NULL && m_pReflect->m_hWnd != NULL)
{
// Create the control's window.
CreateEx(dwExStyle, NULL, m_strText, dwStyle,
m_ptOffset.x, m_ptOffset.y, rcPos.Width(), rcPos.Height(),
m_pReflect->m_hWnd, 0);
if (m_hWnd == NULL)
{
// Window creation failed: cleanup.
m_pReflect->DestroyWindow();
m_pReflect = NULL;
}
}
}
// Set the new window's font.
OnFontChanged();
}
else
{
// If window does exist, reparent it...
CWnd* pWndOuter = GetOuterWindow();
ASSERT(pWndOuter != NULL);
if (::GetParent(pWndOuter->m_hWnd) != hWndParent)
ReparentControlWindow(pWndOuter->m_hWnd, hWndParent);
::SetWindowPos(pWndOuter->m_hWnd, NULL, 0, 0, 0, 0,
SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|
SWP_SHOWWINDOW);
// And then reposition it...
OnSetObjectRects(rcPos, prcClip);
}
ASSERT(m_hWnd != NULL);
return (m_hWnd != NULL);
}
void COleControl::ReparentControlWindow(HWND hWndOuter, HWND hWndParent)
{
// can be overridden by subclass, if necessary
::SetParent(hWndOuter, hWndParent);
}
void COleControl::GetControlSize(int* pcx, int* pcy)
{
ASSERT_POINTER(pcx, int);
ASSERT_POINTER(pcy, int);
SIZEL szlHimetric;
SIZEL szlPixels;
szlHimetric.cx = m_cxExtent;
szlHimetric.cy = m_cyExtent;
_AfxXformSizeInHimetricToPixels(NULL, &szlHimetric, &szlPixels);
*pcx = (int)szlPixels.cx;
*pcy = (int)szlPixels.cy;
}
BOOL COleControl::SetControlSize(int cx, int cy)
{
SIZEL szlPixels;
SIZEL szlHimetric;
szlPixels.cx = cx;
szlPixels.cy = cy;
_AfxXformSizeInPixelsToHimetric(NULL, &szlPixels, &szlHimetric);
return SUCCEEDED(m_xOleObject.SetExtent(DVASPECT_CONTENT, &szlHimetric));
}
BOOL COleControl::SetRectInContainer(LPCRECT lpRect)
{
if ((m_pInPlaceSite != NULL) && m_bInPlaceActive)
{
m_pInPlaceSite->OnPosRectChange(lpRect);
return TRUE;
}
#ifdef _AFXDLL
else if (m_bOpen)
{
ResizeOpenControl(lpRect->right - lpRect->left,
lpRect->bottom - lpRect->top);
return TRUE;
}
#endif
return FALSE;
}
void COleControl::OnResetState()
{
CResetPropExchange px;
DoPropExchange(&px);
InvalidateControl();
}
#ifndef BDR_INNER
#define BDR_INNER 0x000c
#endif
#ifndef BDR_OUTER
#define BDR_OUTER 0x0003
#endif
void AFXAPI _AfxDrawBorders(CDC* pDC, CRect& rc, BOOL bBorder, BOOL bClientEdge)
{
if (bBorder)
::DrawEdge(pDC->m_hDC, &rc, (bClientEdge ? BDR_INNER : BDR_OUTER),
BF_RECT | BF_ADJUST | (bClientEdge ? BF_FLAT : BF_MONO));
if (bClientEdge)
::DrawEdge(pDC->m_hDC, &rc, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
}
void COleControl::DrawContent(CDC* pDC, CRect& rc)
{
// Map into device coordinates.
pDC->LPtoDP(&rc);
int iSaveDC = 0;
if (! m_bOptimizedDraw)
iSaveDC = pDC->SaveDC();
pDC->SetViewportOrg(0, 0);
pDC->SetWindowOrg(0, 0);
pDC->SetMapMode(MM_TEXT);
m_rcBounds = rc;
if (pDC->GetDeviceCaps(TECHNOLOGY) == DT_RASDISPLAY)
_AfxDrawBorders(pDC, rc, (m_sBorderStyle == 1), (m_sAppearance == 1));
OnDraw(pDC, rc, rc);
if (! m_bOptimizedDraw && iSaveDC != 0)
pDC->RestoreDC(iSaveDC);
}
void COleControl::DrawMetafile(CDC* pDC, CRect& rc)
{
int iSaveDC = 0;
if (! m_bOptimizedDraw)
iSaveDC = pDC->SaveDC();
m_rcBounds = rc;
_AfxDrawBorders(pDC, rc, (m_sBorderStyle == 1), (m_sAppearance == 1));
OnDrawMetafile(pDC, rc);
if (! m_bOptimizedDraw && iSaveDC != 0)
pDC->RestoreDC(iSaveDC);
}
void COleControl::OnDraw(CDC*, const CRect&, const CRect&)
{
// To be overridden by subclass.
}
void COleControl::OnDrawMetafile(CDC* pDC, const CRect& rcBounds)
{
// By default, we draw into metafile the same way we would draw to the
// screen. This may be overridden by the subclass.
OnDraw(pDC, rcBounds, rcBounds);
}
BOOL COleControl::GetMetafileData(LPFORMATETC lpFormatEtc,
LPSTGMEDIUM lpStgMedium)
{
ASSERT_VALID(this);
ASSERT(AfxIsValidAddress(lpFormatEtc, sizeof(FORMATETC), FALSE));
ASSERT(AfxIsValidAddress(lpStgMedium, sizeof(STGMEDIUM)));
ASSERT(lpStgMedium->tymed == TYMED_NULL); // GetDataHere not valid
ASSERT(lpStgMedium->pUnkForRelease == NULL);
// medium must be TYMED_MFPICT -- cannot fill in existing HGLOBAL
if (!(lpFormatEtc->tymed & TYMED_MFPICT) || lpStgMedium->hGlobal != NULL)
return FALSE;
// create appropriate memory metafile DC
CMetaFileDC dc;
if (!dc.Create())
return FALSE;
// create attribute DC according to lpFormatEtc->ptd
HDC hAttribDC = ::_AfxOleCreateDC(lpFormatEtc->ptd);
dc.SetAttribDC(hAttribDC);
// Paint directly into the metafile.
int cx;
int cy;
GetControlSize(&cx, &cy);
CRect rc(0, 0, cx, cy);
dc.SetMapMode(MM_ANISOTROPIC);
dc.SetWindowOrg(0, 0);
dc.SetWindowExt(cx, cy);
DrawMetafile(&dc, rc);
// attribute DC is no longer necessary
dc.SetAttribDC(NULL);
::DeleteDC(hAttribDC);
HMETAFILE hMF;
hMF = (HMETAFILE)dc.Close();
if (hMF == NULL)
return FALSE;
HGLOBAL hPict;
if ((hPict = ::GlobalAlloc(GMEM_DDESHARE, sizeof(METAFILEPICT))) == NULL)
{
DeleteMetaFile(hMF);
return FALSE;
}
LPMETAFILEPICT lpPict;
if ((lpPict = (LPMETAFILEPICT)::GlobalLock(hPict)) == NULL)
{
DeleteMetaFile(hMF);
::GlobalFree(hPict);
return FALSE;
}
// set the metafile size
lpPict->mm = MM_ANISOTROPIC;
lpPict->hMF = hMF;
lpPict->xExt = (int)m_cxExtent;
lpPict->yExt = (int)m_cyExtent;
// return the medium with the hGlobal to the METAFILEPICT
::GlobalUnlock(hPict);
lpStgMedium->hGlobal = hPict;
lpStgMedium->tymed = TYMED_MFPICT;
return TRUE;
}
BOOL COleControl::OnCreateAggregates()
{
return TRUE;
}
LPVOID COleControl::QueryDefHandler(REFIID iid)
{
// If we're being aggregated, we want to pass the outer unknown
// to the object we're aggregating (the default handler).
// Otherwise, we pass our own "inner" unknown.
// That's what GetControllingUnknown() does.
LPUNKNOWN pUnk = GetControllingUnknown();
CLSID clsid;
GetClassID(&clsid);
if (m_pDefIUnknown == NULL)
{
// Note: This call will not increment pUnk's reference count.
HRESULT hr = CreateDataCache(pUnk, clsid,
IID_IUnknown, (LPLPVOID)&m_pDefIUnknown);
if (FAILED(hr))
return NULL;
}
LPVOID pNew;
// Note: For the following QueryInterface call, we want to prevent
// pUnk's reference count from being incremented. So, if the
// call succeeds, we immediately force a decrement of the reference count.
if (SUCCEEDED(m_pDefIUnknown->QueryInterface(iid, &pNew)))
{
ASSERT(pNew != NULL);
pUnk->Release();
}
return pNew;
}
void COleControl::InvalidateControl(LPCRECT lpRect, BOOL bErase)
{
if (m_bInPlaceActive && m_bInPlaceSiteWndless)
{
CRect rect;
if (lpRect != NULL)
{
CPoint point(0, 0);
ClientToParent(m_rcPos, &point);
rect.CopyRect(lpRect);
rect.OffsetRect(point);
lpRect = ▭
}
m_pInPlaceSiteWndless->InvalidateRect(lpRect, bErase);
}
#ifdef _AFXDLL
else if (m_bInPlaceActive || m_bOpen)
#else
else if (m_bInPlaceActive)
#endif
{
InvalidateRect(lpRect, bErase);
}
else
{
SendAdvise(OBJECTCODE_VIEWCHANGED);
}
if (m_bModified)
SendAdvise(OBJECTCODE_DATACHANGED);
}
CWnd* COleControl::GetOuterWindow() const
{
return (m_pReflect != NULL ? (CWnd*)m_pReflect : (CWnd*)this);
}
void COleControl::OnReflectorDestroyed()
{
m_pReflect = NULL;
}
HRESULT COleControl::SaveState(IStream* pstm)
{
HRESULT hr = S_OK;
TRY
{
// Delegate to the Serialize method.
COleStreamFile file(pstm);
CArchive ar(&file, CArchive::store);
Serialize(ar);
}
CATCH_ALL(e)
{
hr = E_FAIL;
DELETE_EXCEPTION(e);
}
END_CATCH_ALL
return hr;
}
HRESULT COleControl::LoadState(IStream* pstm)
{
HRESULT hr = S_OK;
TRY
{
// Delegate to the Serialize method.
COleStreamFile file(pstm);
CArchive ar(&file, CArchive::load);
Serialize(ar);
}
CATCH_ALL(e)
{
// The load failed. Delete any partially-initialized state.
OnResetState();
m_bInitialized = TRUE;
hr = E_FAIL;
DELETE_EXCEPTION(e);
}
END_CATCH_ALL
// Clear the modified flag.
m_bModified = FALSE;
// Unless IOleObject::SetClientSite is called after this, we can
// count on ambient properties being available while loading.
m_bCountOnAmbients = TRUE;
// Properties have been initialized
m_bInitialized = TRUE;
// Uncache cached ambient properties
_afxAmbientCache->Cache(NULL);
return hr;
}
void COleControl::SendAdvise(UINT uCode)
{
// Calls the appropriate IOleClientSite or IAdviseSink member function
// for various events such as closure, renaming, saving, etc.
switch (uCode)
{
case OBJECTCODE_SAVED:
if (m_pOleAdviseHolder != NULL)
m_pOleAdviseHolder->SendOnSave();
break;
case OBJECTCODE_CLOSED:
if (m_pOleAdviseHolder != NULL)
m_pOleAdviseHolder->SendOnClose();
break;
case OBJECTCODE_SAVEOBJECT:
if (m_bModified && m_pClientSite != NULL)
m_pClientSite->SaveObject();
break;
case OBJECTCODE_DATACHANGED:
//No flags are necessary here.
if (m_pDataAdviseHolder != NULL)
m_pDataAdviseHolder->SendOnDataChange(&m_xDataObject, 0, 0);
break;
case OBJECTCODE_SHOWWINDOW:
if (m_pClientSite != NULL)
m_pClientSite->OnShowWindow(TRUE);
break;
case OBJECTCODE_HIDEWINDOW:
if (m_pClientSite != NULL)
m_pClientSite->OnShowWindow(FALSE);
break;
case OBJECTCODE_SHOWOBJECT:
if (m_pClientSite != NULL)
m_pClientSite->ShowObject();
break;
case OBJECTCODE_VIEWCHANGED:
{
DWORD aspects;
DWORD advf;
LPADVISESINK pAdvSink;
if (SUCCEEDED(m_xViewObject.GetAdvise(&aspects, &advf, &pAdvSink)) &&
(pAdvSink != NULL))
{
pAdvSink->OnViewChange(DVASPECT_CONTENT, -1);
pAdvSink->Release();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -