📄 coleobj.cpp
字号:
preobj->cp = _cp;
if( _punkobj->QueryInterface(IID_IOleObject, (void **)&poo) == NOERROR )
{
// don't worry about failures here
poo->GetUserClassID(&(preobj->clsid));
}
preobj->dwFlags = _pi.dwFlags;
preobj->dvaspect = _pi.dvaspect;
preobj->dwUser = _pi.dwUser;
preobj->sizel = _sizel;
if( (dwFlags & REO_GETOBJ_POLEOBJ) )
{
preobj->poleobj = poo;
if( poo )
{
poo->AddRef();
}
}
else
{
preobj->poleobj = NULL;
}
if( poo )
poo->Release();
if( IsZombie() )
{
return CO_E_RELEASED;
}
if( (dwFlags & REO_GETOBJ_PSTG) )
{
preobj->pstg = _pstg;
if( _pstg )
{
_pstg->AddRef();
}
}
else
{
preobj->pstg = NULL;
}
if( (dwFlags & REO_GETOBJ_POLESITE) )
{
// COMPATIBILITY HACK!! Note that we don't 'release' any pointer that
// may already be in the stored in the site. RichEdit1.0 always sets
// the value, consequently several apps pass in garbage for the site.
//
// If the site was previously set, we will get a reference counting
// bug, so be sure that doesn't happen!
preobj->polesite = (IOleClientSite *)this;
AddRef();
}
else
{
preobj->polesite = NULL;
}
return NOERROR;
}
/*
* COleObject::IsLink
*
* @mfunc returns TRUE if the object is a link
*
* @rdesc BOOL
*/
BOOL COleObject::IsLink()
{
return !!(_pi.dwFlags & REO_LINK);
}
/*
* COleObject::InitFromREOBJECT
*
* @mfunc initializes this object's state from the given
* REOBJECT data structure
*
* @rdesc HRESULT
*/
HRESULT COleObject::InitFromREOBJECT(
DWORD cp, //@parm the cp for the object
REOBJECT *preobj) //@parm the data to use for initialization
{
IOleLink *plink;
HRESULT hr = E_INVALIDARG;
CRchTxtPtr rtp(_ped, 0);
POINT pt;
TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEINTERN, "COleObject::InitFromREOBJECT");
Assert(_punkobj == NULL);
if( IsZombie() )
{
return CO_E_RELEASED;
}
_cp = cp;
if( preobj->poleobj )
{
hr = preobj->poleobj->QueryInterface(IID_IUnknown, (void **)&_punkobj);
}
else
{
_punkobj = (IOleClientSite *) this;
AddRef();
hr = NOERROR;
}
if( hr != NOERROR )
{
return hr;
}
_pstg = preobj->pstg;
if( _pstg )
{
_pstg->AddRef();
}
_pi.dwFlags = preobj->dwFlags & REO_READWRITEMASK;
_pi.dwUser = preobj->dwUser;
_pi.dvaspect = preobj->dvaspect;
_sizel = preobj->sizel; // COMPATIBILITY ISSUE: the RE1.0 code had some
// stuff to deal with REO_DYNAMICSIZE here. We
// do not currently support that.
if( _punkobj->QueryInterface(IID_IOleLink, (void **)&plink) == NOERROR )
{
_pi.dwFlags |= REO_LINK | REO_LINKAVAILABLE;
plink->Release();
}
if( IsZombie() )
{
return CO_E_RELEASED;
}
if( IsEqualCLSID(preobj->clsid, CLSID_StaticMetafile) ||
IsEqualCLSID(preobj->clsid, CLSID_StaticDib) ||
IsEqualCLSID(preobj->clsid, CLSID_Picture_EnhMetafile) )
{
_pi.dwFlags |= REO_STATIC;
}
else if( IsExcelCLSID(preobj->clsid) )
{
_pi.dwFlags |= REO_GETMETAFILE;
}
else if( IsEqualCLSID(preobj->clsid, CLSID_WordArt ) )
{
_fIsWordArt2 = TRUE;
}
else if(IsEqualCLSID(preobj->clsid, CLSID_PaintbrushPicture) ||
IsEqualCLSID(preobj->clsid, CLSID_BitmapImage))
{
_fIsPaintBrush = TRUE;
// These calls will initialize the flag, _fPBUseLocalSizel, which
// indicates that for this PB object, SetExtent calls are not
// acknowledged by the object, and we are to use our local value
// of _sizel as the object extents.
FetchObjectExtents();
SetExtent(SE_NOTACTIVATING);
}
hr = ConnectObject();
if( IsZombie() )
{
return CO_E_RELEASED;
}
// this is a bit non-intuitive, but we need to figure out
// where the object would be so that it can inplace activate correctly.
if( cp )
{
cp--;
}
rtp.SetCp(cp);
_ped->_pdp->PointFromTp(rtp, NULL, FALSE, pt, NULL, TA_TOP);
_rcPos.top = _rcPos.bottom = pt.y; //bottom will be set below in
// FetchExtents
_rcPos.left = _rcPos.right = pt.x;
if (preobj->sizel.cx || preobj->sizel.cy)
{
_sizel = preobj->sizel;
}
else
{
FetchObjectExtents();
}
ResetPosRect();
if( IsZombie() )
{
return CO_E_RELEASED;
}
// finally, lock down Link objects so they we don't try to refetch their
// extents from the server. After initialization, link object size is
// entirely determined by the container.
if( (_pi.dwFlags & REO_LINK) )
{
// so we don't call GetExtents on remeasuring.
_fSetExtent = TRUE;
}
return NOERROR;
}
/*
* COleObject::MeasureObj(pdp, xWidth, yHeight, yDescent)
*
* @mfunc calculates the size of this object in device units
*
* @rdesc void
*/
void COleObject::MeasureObj(
const CDisplay *pdp, //@parm the device to measure for
LONG &xWidth, //@parm the width of the object
LONG &yHeight,
SHORT yDescent) //@parm the height of the object
{
xWidth = pdp->HimetricXtoDX(_sizel.cx);
yHeight = pdp->HimetricYtoDY(_sizel.cy);
if (!(_pi.dwFlags & REO_BELOWBASELINE))
{
yHeight += yDescent;
}
}
/*
* COleObject::InHandle
*
* @mfunc See if a point is in the rectangle defined by the handle at
* the given coordinates.
*
* @rdesc True if point is in handle.
*
*/
BOOL COleObject::InHandle(
int x, //@parm x pos of upper left corner coordinate of the handle box.
int y, //@parm y pos of upper left corner coordinate of the handle box.
const POINT &pt) //@parm point to check
{
RECT rc;
BOOL fRet;
rc.left = x;
rc.top = y;
//Add one to bottom right because PtInRect does not consider
//points on bottom or right to be in rect.
rc.right = x + dxyHandle + 1;
rc.bottom = y + dxyHandle + 1;
fRet = PtInRect(&rc, pt);
return fRet;
}
/*
* COleObject::CheckForHandleHit
*
* @mfunc Check for a hit on any of the frame handles.
*
* @rdesc NULL if no hit, cursor resource ID if there is a hit.
*
*/
LPTSTR COleObject::CheckForHandleHit(
const POINT &pt) //@parm POINT containing client coord. of the cursor.
{
RECT rc;
// if the object is not resizeable, no chance of hitting a resize
// handle!
if( !(_pi.dwFlags & REO_RESIZABLE) )
{
return NULL;
}
CopyRect(&rc, &_rcPos);
if (!_dxyFrame)
{
_dxyFrame = dxyFrameDefault;
}
//Check to see if point is farther into the interior of the
//object than the handles extent. If it is we can just bail.
InflateRect(&rc, -(_dxyFrame + dxyHandle), -(_dxyFrame + dxyHandle));
if (PtInRect(&rc, pt))
{
return NULL;
}
//Check to see if point is in any of the handles and
//return the proper cursor ID if it is.
InflateRect(&rc, dxyHandle, dxyHandle);
if(InHandle(rc.left, rc.top, pt) ||
InHandle(rc.right-dxyHandle, rc.bottom-dxyHandle, pt))
{
return IDC_SIZENWSE;
}
if(InHandle(rc.left, rc.top+(rc.bottom-rc.top-dxyHandle)/2, pt) ||
InHandle(rc.right-dxyHandle,
rc.top+(rc.bottom-rc.top-dxyHandle)/2, pt))
{
return IDC_SIZEWE;
}
if(InHandle(rc.left, rc.bottom-dxyHandle, pt) ||
InHandle(rc.right-dxyHandle, rc.top, pt))
{
return IDC_SIZENESW;
}
if(InHandle(rc.left+(rc.right-rc.left-dxyHandle)/2, rc.top, pt) ||
InHandle(rc.left+(rc.right-rc.left-dxyHandle)/2,
rc.bottom-dxyHandle, pt))
{
return IDC_SIZENS;
}
return NULL;
}
/*
* COleObject::DrawHandle
*
* @mfunc Draw a handle on the object frame at the specified coordinate
*
* @rdesc void
*
*/
void COleObject::DrawHandle(
HDC hdc, //@parm HDC to be drawn into
int x, //@parm x pos of upper left corner coordinate of the handle box
int y) //@parm y pos upper left corner coordinate of the handle box
{
RECT rc;
//Draw the handle by inverting.
rc.left = x;
rc.top = y;
rc.right = x + dxyHandle;
rc.bottom = y + dxyHandle;
InvertRect(hdc, (LPRECT)&rc);
}
/*
* COleObject::DrawFrame
*
* @mfunc Draw a frame around the object. Invert if required and
* include handles if required.
*
* @rdesc void
*
*/
void COleObject::DrawFrame(
const CDisplay *pdp, //@parm the display to draw to
HDC hdc, //@parm the device context
RECT *prc) //@parm the rect around which to draw
{
RECT rc;
CopyRect(&rc, prc);
if (_pi.dwFlags & REO_INVERTEDSELECT)
{
//Invert entire object
InvertRect(hdc, &rc);
}
else
{
// Just the border, so use a null brush
SaveDC(hdc);
SetROP2(hdc, R2_NOT);
SelectObject(hdc, GetStockObject(NULL_BRUSH));
Rectangle(hdc, rc.left, rc.top, rc.right, rc.bottom);
RestoreDC(hdc, -1);
}
if (_pi.dwFlags & REO_RESIZABLE)
{
int bkmodeOld;
HPEN hpen;
LOGPEN logpen;
bkmodeOld = SetBkMode(hdc, TRANSPARENT);
Assert(bkmodeOld);
//Get the frame width
_dxyFrame = dxyFrameDefault;
hpen = (HPEN)GetCurrentObject(hdc, OBJ_PEN);
if( W32->GetObject(hpen, sizeof(LOGPEN), &logpen) )
{
if( logpen.lopnWidth.x )
{
_dxyFrame = (SHORT)logpen.lopnWidth.x;
}
}
// Draw the handles inside the rectangle boundary
InflateRect(&rc, -_dxyFrame, -_dxyFrame);
DrawHandle(hdc, rc.left, rc.top);
DrawHandle(hdc, rc.left, rc.top + (rc.bottom-rc.top-dxyHandle)/2);
DrawHandle(hdc, rc.left, rc.bottom-dxyHandle);
DrawHandle(hdc, rc.left + (rc.right - rc.left - dxyHandle)/2, rc.top);
DrawHandle(hdc, rc.left+(rc.right-rc.left-dxyHandle)/2,
rc.bottom-dxyHandle);
DrawHandle(hdc, rc.right-dxyHandle, rc.top);
DrawHandle(hdc, rc.right-dxyHandle,
rc.top+(rc.bottom-rc.top-dxyHandle)/2);
DrawHandle(hdc, rc.right-dxyHandle, rc.bottom-dxyHandle);
SetBkMode(hdc, bkmodeOld);
}
}
/*
* COleObject::CreateDib
*
* @mfunc Create DIB for Windows CE display
*
* @rdesc void
*
*/
void COleObject::CreateDib(HDC hdc)
{
BYTE *pbDib;
HGLOBAL hnew = NULL;
BYTE *pbSrcBits;
LPBITMAPINFO pbmi = (LPBITMAPINFO) GlobalLock(_hdata);
int iBitsPerPix, iAdjustedWidth, iNumColors;
DWORD dwColors, dwImage;
iBitsPerPix = pbmi->bmiHeader.biBitCount;
ASSERT(iBitsPerPix == 1 || iBitsPerPix == 4 ||
iBitsPerPix == 8 || iBitsPerPix == 16 || iBitsPerPix == 24 || iBitsPerPix == 32);
iAdjustedWidth = ((pbmi->bmiHeader.biWidth * iBitsPerPix + 31) & ~31) / 8;
iNumColors = pbmi->bmiHeader.biClrUsed;
if ((iNumColors == 0) && (iBitsPerPix <= 8)){
iNumColors = 1 << iBitsPerPix;
}
dwColors = iNumColors * sizeof(RGBQUAD) + (pbmi->bmiHeader.biCompression == BI_BITFIELDS ? 3 * sizeof(DWORD) : 0);
dwImage = pbmi->bmiHeader.biHeight * iAdjustedWidth;
// Bitmap bits location
pbSrcBits = (BYTE*)(pbmi) + sizeof(BITMAPINFOHEADER) + dwColors;
if(16 == iBitsPerPix &&
(pbmi->bmiHeader.biCompression == BI_BITFIELDS))
{
// Sixteen-bit case: fill in the bitfields mask for 565
#define MASK565_0 0x0000F800
#define MASK565_1 0x000007E0
#define MASK565_2 0x0000001F
((DWORD*)(pbmi->bmiColors))[0] = MASK565_0;
((DWORD*)(pbmi->bmiColors))[1] = MASK565_1;
((DWORD*)(pbmi->bmiColors))[2] = MASK565_2;
}
_hdib = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&pbDib, NULL, 0);
if (_hdib == NULL)
{
DWORD dwle = ::GetLastError();
_ped->GetCallMgr()->SetOutOfMemory();
// V-GUYB:
// Do not attempt to repaint this picture until the user starts typing in the
// control. This allows the user to dismiss the oom that will appear and then
// save the document, and then free up some space. If we don't do this here,
// every time the oom msg is dismissed it will appear again. This doesn't allow
// the user to save the document unless they can find some memory to free.
_fDraw = FALSE;
TRACEWARNSZ("Out of memory creating DIB");
return;
}
// Move Bitmap bits
CopyMemory(pbDib, pbSrcBits, dwImage);
GlobalUnlock(pbmi);
GlobalFree(hnew);
}
/*
* COleObject::DrawDib : Auxiliary function
*
* @mfunc draws the dib in the given dc
*
* @rdesc void
*/
void COleObject::DrawDib(
HDC hdc,
RECT *prc
)
{
// HDC hdcMem = CreateCompatibleDC(hdc);
HDC hdcMem; // V-GUYB: Create hdcMem later in case we return early.
LPBITMAPINFO pbmi;
if (!_hdib)
{
CreateDib(hdc);
}
// If _hdib is still NULL, just return. Maybe out of memory.
if (!_hdib)
{
goto leave;
}
// V-GUYB: NOW create the mem dc.
hdcMem = CreateCompatibleDC(hdc);
if(!hdcMem)
{
goto leave;
}
pbmi = (LPBITMAPINFO) LocalLock(_hdata);
SelectObject(hdcMem, _hdib);
StretchBlt(hdc, prc->left, prc->top,
prc->right - prc->left, prc->bottom - prc->top,
hdcMem, 0, 0, pbmi->bmiHeader.biWidth, pbmi->bmiHeader.biHeight, SRCCOPY);
GlobalUnlock(pbmi);
DeleteDC(hdcMem);
leave:
return;
}
/*
* COleObject::DrawObj
*
* @mfunc draws the object
*
* @rdesc void
*/
void COleObject::DrawObj(
const CDisplay *pdp, //@parm the display object for the view
HDC hdc, //@parm the drawing HDC (can be different
//than the display.
BOOL fMetafile, //@parm whether the HDC is a metafile
POINT *ppt, //@parm top left corner of where to draw
RECT *prcRender) //@parm pointer to render rectangle
{
RECT rc, rc1;
IViewObject *pvo;
CDisplayPrinter *pdpPrint;
LONG adjust = 0;
CObjectMgr * pobjmgr = _ped->GetObjectMgr();
if (NULL == pobjmgr)
{
Assert(pobjmgr);
SetLastError(ERROR_OUTOFMEMORY);
return;
}
// if we aren't running in transparent mode,
// Clear the space in the render rectangle
// This includes space for the object
// It also includes any surrounding space
if( !_ped->_fTransparent )
{
rc1.left = prcRender->left;
rc1.top = prcRender->top;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -