📄 maphelper.cpp
字号:
{
VARIANT v;
v.vt = VT_R8;
v.dblVal = value;
SetValue(fields, name, v);
}
void SetValue(CMoFields& fields, LPCTSTR name, const COleDateTime& value)
{
VARIANT v;
v.vt = VT_DATE;
v.date = value.m_dt;
SetValue(fields, name, v);
}
void SetValue(CMoFields& fields, LPCTSTR name, const LPCTSTR value)
{
SetValue(fields, name, COleVariant(value));
}
void SetValue(CMoFields& fields, LPCTSTR name, const BOOL value)
{
VARIANT v;
v.vt = VT_BOOL;
v.bVal = value;
SetValue(fields, name, v);
}
void SetValue(CMoFields& fields, LPCTSTR name, const LPDISPATCH value)
{
VARIANT v;
v.vt = VT_DISPATCH;
v.pdispVal = value;
SetValue(fields, name, v);
}
///////////////////////////////////////////////////////////////////////////
// Printing and Export
//
static void S_AdjustWidthToRatio(CRect& r, const double ratio, const UINT align = DT_CENTER)
{
int newWidth = (int)MULT(r.Height(), ratio);
int offset;
if (align & DT_CENTER)
offset = (int)DIV((double)r.Width() - newWidth, 2);
else if (align & DT_RIGHT)
offset = r.Width() - newWidth;
else
offset = 0;
r.left += offset;
r.right = r.left + newWidth;
}
static void S_AdjustHeightToRatio(CRect& r, const double ratio, const UINT align = DT_VCENTER)
{
int newHeight = (int)DIV(r.Width(), ratio);
int offset;
if (align & DT_VCENTER)
offset = (int)DIV((double)r.Height() - newHeight, 2);
else if (align & DT_BOTTOM)
offset = r.Height() - newHeight;
else
offset = 0;
r.top += offset;
r.bottom = r.top + newHeight;
}
//
// Adjust the rectangle to match the aspect ratio specified
// Use the following values or'd together for alignment:
//
// DT_TOP, DT_VCENTER, DT_BOTTOM
// DT_LEFT, DT_CENTER, DT_RIGHT
//
CRect AdjustToRatio(const CRect& r, const double ratio, const UINT align)
{
CRect newRect = r;
// First try simple adjustment
if (ratio < 1.0)
S_AdjustWidthToRatio(newRect, ratio, align);
else
S_AdjustHeightToRatio(newRect, ratio, align);
// Didn't fit. Adjust again.
if (r.Width() < newRect.Width())
{
newRect.left = r.left;
newRect.right = r.right;
S_AdjustHeightToRatio(newRect, ratio, align);
}
if (r.Height() < newRect.Height())
{
newRect.top = r.top;
newRect.bottom = r.bottom;
S_AdjustWidthToRatio(newRect, ratio, align);
}
return newRect;
}
//
// Calculate the size of the output device in pixels
//
CRect GetDeviceRect(CDC* pDC)
{
CRect devRect;
// HDC hDC = pDC->m_hAttribDC;
HDC hDC = pDC->GetSafeHdc();
int type = ::GetObjectType(hDC);
switch (type)
{
case OBJ_DC: // Printer or screen
//
// If there's a window associated with
// the DC, use the client area. Otherwise
// use the device width.
//
HWND hWnd;
if (hWnd = ::WindowFromDC(hDC))
::GetClientRect(hWnd, &devRect);
else
devRect.SetRect(0, 0, pDC->GetDeviceCaps(HORZRES), pDC->GetDeviceCaps(VERTRES));
break;
case OBJ_MEMDC: // Memory bitmap
//
// Use the bitmap size
//
HBITMAP hBitmap;
hBitmap = (HBITMAP)::GetCurrentObject(pDC->GetSafeHdc(), OBJ_BITMAP);
if (!hBitmap)
throw "error with memory DC";
BITMAP bm;
VERIFY(::GetObject(hBitmap, sizeof(BITMAP), &bm));
if (bm.bmWidth == 0 || bm.bmHeight == 0)
throw "error with memory DC";;
devRect.SetRect(0, 0, bm.bmWidth, bm.bmHeight);
break;
default:
devRect.SetRect(0, 0, pDC->GetDeviceCaps(HORZRES), pDC->GetDeviceCaps(VERTRES));
if (devRect.right == 0)
{
CClientDC dc(0);
devRect.SetRect(0, 0, dc.GetDeviceCaps(HORZRES), dc.GetDeviceCaps(VERTRES));
}
break;
}
return devRect;
}
//
// Work-around that allows you to draw maps on an old style windows
// metafile.
//
void OutputMap(CMap1& map, CMetaFileDC* pDC)
{
map.ExportMap(moExportClipboardEMF, TEXT("TRUE"), 1.0); // system generates old-style metafile
if (::OpenClipboard(::GetFocus()))
{
HANDLE hMFP = ::GetClipboardData(CF_METAFILEPICT);
METAFILEPICT* pMFP = (METAFILEPICT*)::GlobalLock(hMFP);
if (pMFP)
{
VERIFY(::PlayMetaFile(pDC->GetSafeHdc(), pMFP->hMF));
::GlobalUnlock(hMFP);
}
VERIFY(::CloseClipboard());
}
}
//
// Draw the map, scaling it to a frame on the surface of the
// device referenced by the DC. If the frame doesn't match the
// aspect ratio of the map, the map is position as specified
// by hAlign and vAlign within the frame. Use the following
// values or'd together for alignment:
//
// DT_TOP, DT_VCENTER, DT_BOTTOM
// DT_LEFT, DT_CENTER, DT_RIGHT
//
void FrameMap(CMap1& map, CDC* pDC, const CRect& dstRect, const UINT align)
{
//
// Create a frame of the same aspect ratio as the map and
// center or left justify it in dstRect.
//
double aspectRatio = GetAspectRatio(map);
CRect frame = AdjustToRatio(dstRect, aspectRatio, align);
//
// Use GDI to position map on page
//
CRect devRect = AdjustToRatio(GetDeviceRect(pDC), aspectRatio);
int saveID = pDC->SaveDC();
pDC->SetMapMode(MM_ISOTROPIC);
pDC->SetWindowOrg(devRect.left, devRect.top);
pDC->SetWindowExt(devRect.Width(), devRect.Height());
pDC->SetViewportOrg(frame.left, frame.top);
pDC->SetViewportExt(frame.Width(), frame.Height());
map.OutputMap((OLE_HANDLE)pDC->GetSafeHdc());
pDC->RestoreDC(saveID);
#if 0
// Rectangles for testing
HBRUSH hBrush = (HBRUSH)::GetStockObject(NULL_BRUSH);
HBRUSH hOldBrush = (HBRUSH)::SelectObject(pDC->GetSafeHdc(), hBrush);
pDC->Rectangle(dstRect);
HPEN hPen = (HPEN)::CreatePen(PS_SOLID, 0, RGB(255, 0, 0));
HPEN hOldPen = (HPEN)::SelectObject(pDC->GetSafeHdc(), hPen);
pDC->Rectangle(frame);
::SelectObject(pDC->GetSafeHdc(), hOldPen);
::SelectObject(pDC->GetSafeHdc(), hOldBrush);
#endif
}
///////////////////////////////////////////////////////////////////////////
// OLE Fonts
//
CMoFont::CMoFont()
: CFontHolder(0),
m_pFontDisp(0),
m_pDispatch(0)
{
CFontDesc fontDesc;
InitializeFont(&fontDesc, 0);
}
CMoFont::CMoFont(LPFONTDISP pFontDisp)
: CFontHolder(0)
{
InitializeFont(0, pFontDisp);
// similar to COleDispatchDriver::CreateDispatch()
}
CMoFont::~CMoFont()
{
ReleaseDispatch();
}
void CMoFont::AttachDispatch(LPFONTDISP pFontDisp)
{
ReleaseDispatch();
InitializeFont(0, pFontDisp);
}
void CMoFont::ReleaseDispatch()
{
if (m_pFontDisp)
{
m_pFontDisp->Release();
m_pFontDisp = 0;
}
if (m_pDispatch)
{
m_pDispatch->Release();
m_pDispatch = 0;
}
}
CMoFont::operator LPFONTDISP()
{
if (m_pFontDisp == 0)
m_pFontDisp = GetFontDispatch(); // must release;
return m_pFontDisp;
}
CMoFont::operator LPDISPATCH()
{
if (m_pDispatch == 0)
{
LPFONTDISP pFontDisp = this->operator LPFONTDISP();
pFontDisp->QueryInterface(IID_IDispatch, (void**)&m_pDispatch); // must release;
}
return m_pDispatch;
}
LPCTSTR CMoFont::GetName()
{
USES_CONVERSION;
ASSERT(m_pFont);
BSTR pName;
m_pFont->get_Name(&pName);
return OLE2T(pName);
}
void CMoFont::SetName(LPCTSTR name)
{
USES_CONVERSION;
ASSERT(m_pFont);
m_pFont->put_Name(T2OLE(name));
}
long CMoFont::GetSize()
{
ASSERT(m_pFont);
CY size;
m_pFont->get_Size(&size);
return (long)DIV(size.int64, 10000);
}
void CMoFont::SetSize(long size)
{
ASSERT(m_pFont);
CY _size = { size * 10000, 0 };
m_pFont->put_Size(_size);
}
short CMoFont::GetWeight()
{
ASSERT(m_pFont);
short weight;
m_pFont->get_Weight(&weight);
return weight;
}
void CMoFont::SetWeight(short weight)
{
ASSERT(m_pFont);
m_pFont->put_Weight(weight);
}
short CMoFont::GetCharSet()
{
ASSERT(m_pFont);
short charSet;
m_pFont->get_Charset(&charSet);
return charSet;
}
void CMoFont::SetCharSet(short charset)
{
ASSERT(m_pFont);
m_pFont->put_Charset(charset);
}
BOOL CMoFont::GetItalic()
{
ASSERT(m_pFont);
BOOL flag;
m_pFont->get_Italic(&flag);
return flag;
}
void CMoFont::SetItalic(BOOL italic)
{
ASSERT(m_pFont);
m_pFont->put_Italic(italic);
}
BOOL CMoFont::GetUnderline()
{
ASSERT(m_pFont);
BOOL flag;
m_pFont->get_Underline(&flag);
return flag;
}
void CMoFont::SetUnderline(BOOL underline)
{
ASSERT(m_pFont);
m_pFont->put_Underline(underline);
}
BOOL CMoFont::GetStrikeThrough()
{
ASSERT(m_pFont);
BOOL flag;
m_pFont->get_Strikethrough(&flag);
return flag;
}
void CMoFont::SetStrikeThrough(BOOL strikeThrough)
{
ASSERT(m_pFont);
m_pFont->put_Strikethrough(strikeThrough);
}
///////////////////////////////////////////////////////////////////////////
// Collection Iterator
//
CMoIterator::CMoIterator(COleDispatchDriver& collection)
: m_pEnumVariant(0)
{
//
// Find out if collection is really a collection
// by querying for the _NewEnum property and
// assigning the m_pEnumVariant pointer to it.
//
USES_CONVERSION;
LPCOLESTR pName = T2COLE(TEXT("_NewEnum"));
DISPID dispID = -1;
if (!SUCCEEDED(LPDISPATCH(collection)->GetIDsOfNames(IID_NULL, (OLECHAR**)&pName, 1, 0, &dispID)))
throw "invalid collection object";
LPUNKNOWN pUnknown = 0;
collection.GetProperty(dispID, VT_UNKNOWN, &pUnknown);
if (pUnknown == 0)
throw "unable to get IUnknown for collection object";
pUnknown->QueryInterface(IID_IEnumVARIANT, (void**)&m_pEnumVariant);
pUnknown->Release();
if (m_pEnumVariant == 0)
throw "unable to get IEnumVARIANT for collection object";
Reset(); // might not need this.
// success, collection has _NewEnum property!
}
//
// Sets item to next element of collection
//
BOOL CMoIterator::Next(COleDispatchDriver& item)
{
HRESULT result = S_FALSE;
ASSERT(m_pEnumVariant);
if (m_pEnumVariant)
{
ULONG c;
VARIANT v;
result = m_pEnumVariant->Next(1, &v, &c);
if (result == S_OK && c == 1)
{
// v.pdispVal->AddRef(); // You shouldn't need to AddRef anything
item.AttachDispatch(v.pdispVal);
}
}
return (result == S_OK);
}
void CMoIterator::Reset()
{
ASSERT(m_pEnumVariant);
if (m_pEnumVariant)
m_pEnumVariant->Reset();
}
void CMoIterator::Skip(unsigned long index)
{
ASSERT(m_pEnumVariant);
if (m_pEnumVariant)
m_pEnumVariant->Skip(index);
}
CMoIterator::~CMoIterator()
{
if (m_pEnumVariant)
m_pEnumVariant->Release();
}
IUnknown* CreateCOMObject(const GUID& clsid, IUnknown* pOuter)
{
USES_CONVERSION;
IUnknown* pUnknown = 0;
IClassFactory* pFactory = 0;
HRESULT hr = CoGetClassObject(clsid, CLSCTX_ALL, 0, IID_IClassFactory, (void**)&pFactory);
if (SUCCEEDED(hr))
{
hr = pFactory->CreateInstance(pOuter, IID_IUnknown, (void**)&pUnknown);
pFactory->Release();
}
return pUnknown;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -