// DDLabel.cpp : Implementation of CDDLabel
//
// Author : David Shepherd
// Copyright (c) 2003, DaeDoe-Software
//
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include ".\DDLabel.h"
/////////////////////////////////////////////////////////////////////////////
// CDDLabel
CDDLabel::CDDLabel()
{
// initialise everything
m_bWindowOnly=TRUE;
m_Reserved0=0;
m_Reserved1=0;
m_BackColor=MAKE_OLE_COLOR(COLOR_BTNFACE);
m_ForeColor=MAKE_OLE_COLOR(COLOR_BTNTEXT);
m_TextAlign=ddcpTextAlignLeft;
m_CenterVertically=VARIANT_FALSE;
m_BorderStyle=ddcpBorderStyleNone;
}
HRESULT CDDLabel::FinalConstruct()
{
IMP_BEGIN
// create the default font
m_spFontDisp=CreateDefaultFont();
IMP_END
return RetVal;
}
void CDDLabel::FinalRelease()
{
}
const TCHAR* CDDLabel::GetObjectFriendlyName()
{
// return the object friendly name
return _T("DDLabel");
}
HRESULT CDDLabel::OnTextAlignChanging(ddcpTextAlign newVal)
{
IMP_BEGIN
// check the new value is valid
if(newVal < ddcpTextAlign_First or newVal > ddcpTextAlign_Last)
{
throw CHResult(E_INVALIDARG);
}
IMP_END
return RetVal;
}
HRESULT CDDLabel::OnBorderStyleChanging(ddcpBorderStyle newVal)
{
IMP_BEGIN
// check the new value is valid
if(newVal < ddcpBorderStyle_First or newVal > ddcpBorderStyle_Last)
{
throw CHResult(E_INVALIDARG);
}
IMP_END
return RetVal;
}
void CDDLabel::DrawBorder(CDCHandle hDC,CRect Rect)
{
// save the device context state
CAutoDCState AutoDCState(hDC);
// get the draw edge type
UINT DrawEdgeType=0;
switch(m_BorderStyle)
{
// none
case ddcpBorderStyleNone:
break;
// sunken
case ddcpBorderStyleSunken:
DrawEdgeType=EDGE_SUNKEN;
break;
// raised
case ddcpBorderStyleRaised:
DrawEdgeType=EDGE_RAISED;
break;
// etched
case ddcpBorderStyleEtched:
DrawEdgeType=EDGE_ETCHED;
break;
// bump
case ddcpBorderStyleBump:
DrawEdgeType=EDGE_BUMP;
break;
// unknown
default:
ATLASSERT(FALSE);
break;
}
// draw the border
if(DrawEdgeType)
{
if(hDC.DrawEdge(Rect,DrawEdgeType,BF_RECT)==FALSE)
{
throw std::exception();
}
}
}
void CDDLabel::DrawText(CDCHandle hDC,CRect Rect)
{
USES_CONVERSION;
// save the device context state
CAutoDCState AutoDCState(hDC);
// set the background color
COLORREF BackColor=RGB(0,0,0);
if(!SUCCEEDED(OleTranslateColor(m_BackColor,NULL,&BackColor)))
{
throw std::exception();
}
if(hDC.SetBkColor(BackColor)==CLR_INVALID)
{
throw std::exception();
}
// set the foreground color
COLORREF ForeColor=RGB(0,0,0);
if(!SUCCEEDED(OleTranslateColor(m_ForeColor,NULL,&ForeColor)))
{
throw std::exception();
}
if(hDC.SetTextColor(ForeColor)==CLR_INVALID)
{
throw std::exception();
}
// set the font
CComQIPtr<IFont> spFont(m_spFontDisp);
if(spFont==NULL)
{
throw std::exception();
}
CFontHandle hFont;
if(!SUCCEEDED(spFont->get_hFont(&hFont.m_hFont)))
{
throw std::exception();
}
if(hDC.SelectFont(hFont)==NULL)
{
throw std::exception();
}
// fill in the background
hDC.FillSolidRect(Rect,BackColor);
// get the draw text flags
UINT DrawTextFlags=DT_NOPREFIX|DT_WORDBREAK;
switch(m_TextAlign) // text align
{
// left
case ddcpTextAlignLeft:
DrawTextFlags |= DT_LEFT;
break;
// center
case ddcpTextAlignCenter:
DrawTextFlags |= DT_CENTER;
break;
// right
case ddcpTextAlignRight:
DrawTextFlags |= DT_RIGHT;
break;
// unknown
default:
ATLASSERT(FALSE);
break;
}
if(m_CenterVertically) // center vertically
{
DrawTextFlags |= DT_VCENTER|DT_SINGLELINE;
// todo : remove DT_WORDBREAK if required
}
// draw the text
if(hDC.DrawText(W2CT(BSTR2W(m_Text)),-1,Rect,DrawTextFlags)==0)
{
throw std::exception();
}
}
HRESULT CDDLabel::OnDraw(ATL_DRAWINFO& di)
{
IMP_BEGIN
// device context wrapper
CDCHandle hDC(di.hdcDraw);
// bounding rectangle
CRect Rect=*(RECT*)di.prcBounds;
// create GDI object wrappers
// this must be done before the memory device context state is saved
CBitmap Bitmap;
// create the memory device context
CDC dcMem;
if(dcMem.CreateCompatibleDC(hDC)==NULL)
{
throw CHResult(E_FAIL);
}
// save the memory device context state
CAutoDCState AutoDCState(dcMem);
// create the bitmap and select it into the memory device context
if(Bitmap.CreateCompatibleBitmap(hDC,Rect.Width(),Rect.Height())==NULL)
{
throw CHResult(E_FAIL);
}
if(dcMem.SelectBitmap(Bitmap)==NULL)
{
throw CHResult(E_FAIL);
}
// map coordinates to the control
if(dcMem.SetWindowOrg(Rect.left,Rect.top)==FALSE)
{
throw CHResult(E_FAIL);
}
// draw the border
CRect BorderRect=Rect;
DrawBorder(CDCHandle(dcMem),BorderRect);
// get the area in which to draw the text
CRect TextRect=Rect;
if( m_BorderStyle==ddcpBorderStyleSunken or
m_BorderStyle==ddcpBorderStyleRaised or
m_BorderStyle==ddcpBorderStyleEtched or
m_BorderStyle==ddcpBorderStyleBump)
{
if(TextRect.Width() < 4 or TextRect.Height() < 4)
{
TextRect.SetRectEmpty(); // there is no room for the text
}
else
{
TextRect.InflateRect(-2,-2); // there is room for the text
}
}
// draw the text
DrawText(CDCHandle(dcMem),TextRect);
// update the screen
if(hDC.BitBlt(
Rect.left,Rect.top,Rect.Width(),Rect.Height(),
dcMem,Rect.left,Rect.top,SRCCOPY)==FALSE)
{
throw CHResult(E_FAIL);
}
IMP_END
return RetVal;
}
LRESULT CDDLabel::OnEraseBkgnd(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
// to prevent flicker do not erase the background
return TRUE;
}
STDMETHODIMP CDDLabel::SetClientSite(IOleClientSite *pClientSite)
{
IMP_BEGIN
// call the base class
HRESULT hr=IOleObjectImpl<CDDLabel>::SetClientSite(pClientSite);
if(!SUCCEEDED(hr))
{
throw CHResult(hr);
}
// set the background color based on the container ambient properties
OLE_COLOR BackColor=RGB(0,0,0);
if(SUCCEEDED(GetAmbientBackColor(BackColor)))
{
(void)put_BackColor(BackColor);
}
// set the foreground color based on the container ambient properties
OLE_COLOR ForeColor=RGB(0,0,0);
if(SUCCEEDED(GetAmbientForeColor(ForeColor)))
{
(void)put_ForeColor(ForeColor);
}
IMP_END
return RetVal;
}
STDMETHODIMP CDDLabel::get__Default(BSTR* pVal)
{
// delegate to the required default property
return get_Text(pVal);
}
STDMETHODIMP CDDLabel::put__Default(BSTR newVal)
{
// delegate to the required default property
return put_Text(newVal);
}