Click here to Skip to main content
15,860,844 members
Articles / Desktop Programming / WTL

Form Designer

26 Jul 2021CPOL24 min read 349.7K   82.5K   230  
Component for adding scriptable forms capabilities to an application.
// DDButton.cpp : Implementation of CDDButton
//
// Author : David Shepherd
//			Copyright (c) 2003, DaeDoe-Software
//
/////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include ".\DDButton.h"

/////////////////////////////////////////////////////////////////////////////
// CDDButton

#pragma warning(push)
#pragma warning(disable: 4355) // 'this' : used in base member initializer list
CDDButton::CDDButton() : m_ctlButton(_T("DDButton"), this, 1)
#pragma warning(pop)
{
	// initialise everything
	m_bWindowOnly=TRUE;
	m_Reserved0=0;
	m_Reserved1=0;
	m_Enabled=VARIANT_TRUE;
	m_BackColor=MAKE_OLE_COLOR(COLOR_BTNFACE);
	m_ForeColor=MAKE_OLE_COLOR(COLOR_BTNTEXT);
	m_TextAlign=ddcpTextAlignCenter;
}

HRESULT CDDButton::FinalConstruct()
{
IMP_BEGIN
	// create the default font
	m_spFontDisp=CreateDefaultFont();
IMP_END
	return RetVal;
}

void CDDButton::FinalRelease()
{
}

const TCHAR* CDDButton::GetObjectFriendlyName()
{
	// return the object friendly name
	return _T("DDButton");
}

HRESULT CDDButton::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;
}

void CDDButton::OnEnabledChanged()
{
TRY
	// update the button
	// this is done indirectly by enabling the parent window
	if(IsWindow())
	{
		(void)EnableWindow(VB2B(m_Enabled));
	}
CATCH_ALL
}

void CDDButton::DrawButton(
	CDCHandle hDC,CRect Rect,BOOL HasFocus,BOOL IsSelected)
{
	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 edge type
	UINT DrawEdgeType=IsSelected ? EDGE_SUNKEN : EDGE_RAISED;
	// draw the edge
	if(hDC.DrawEdge(Rect,DrawEdgeType,BF_RECT)==FALSE)
	{
		throw std::exception();
	}
	// get the focus rectangle
	if(Rect.Width() < 8 or Rect.Height() < 8)
	{
		Rect.SetRectEmpty();		// there is no room for the focus rectangle
	}
	else
	{
		Rect.InflateRect(-4,-4);	// there is room for the focus rectangle
	}
	// adjust the position based on the selected state
	if(IsSelected)
	{
		Rect.OffsetRect(1,1);
	}
	// draw the focus rectangle
	if(HasFocus)
	{
		CBrush Brush=hDC.GetHalftoneBrush();
		if(Brush==NULL)
		{
			throw std::exception();
		}
		if(hDC.FrameRect(Rect,Brush)==FALSE)
		{
			throw std::exception();
		}
	}
	// get the text rectangle
	if(Rect.Width() < 4 or Rect.Height() < 4)
	{
		Rect.SetRectEmpty();		// there is no room for the text
	}
	else
	{
		Rect.InflateRect(-2,-2);	// there is room for the text
	}
	// get the draw text flags
	UINT DrawTextFlags=DT_SINGLELINE|DT_VCENTER|DT_NOPREFIX;
	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;
	}
	// draw the text
	if(hDC.DrawText(W2CT(BSTR2W(m_Text)),-1,Rect,DrawTextFlags)==0)
	{
		throw std::exception();
	}
}

HRESULT CDDButton::FireViewChange()
{
IMP_BEGIN
	// call the base class
	HRESULT hr=CComControlBase::FireViewChange();
	if(!SUCCEEDED(hr))
	{
		throw CHResult(hr);
	}
	// redraw the button
	if(m_ctlButton.IsWindow())
	{
		(void)m_ctlButton.Invalidate(FALSE);
	}
IMP_END
	return RetVal;
}

LRESULT CDDButton::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
TRY
	// create the button
	if(m_ctlButton.Create(*this,
		CRect(0,0,0,0),_T(""),WS_CHILD|WS_VISIBLE|BS_OWNERDRAW)==NULL)
	{
		throw std::exception();
	}
	// update the button
	if(!SUCCEEDED(put_Enabled(m_Enabled)))
	{
		throw std::exception();
	}
CATCH_ALL
	return Caught ? -1 : 0;
}

LRESULT CDDButton::OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
	// generated by the ATL control wizard
	LRESULT lRes = CComControl<CDDButton>::OnSetFocus(uMsg, wParam, lParam, bHandled);
	if (m_bInPlaceActive)
	{
		if(!IsChild(::GetFocus()))
			m_ctlButton.SetFocus();
	}
	return lRes;
}

LRESULT CDDButton::OnDrawItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
TRY
	// get the draw item struct
	DRAWITEMSTRUCT *pDrawItemStruct=(DRAWITEMSTRUCT *)lParam;
	// wrap the device context
	CDCHandle hDC=pDrawItemStruct->hDC;
	// get the item rectangle
	CRect Rect=pDrawItemStruct->rcItem;
	// determine if the item has the focus
	BOOL HasFocus=(pDrawItemStruct->itemState & ODS_FOCUS) ? TRUE : FALSE;
	// determine if the item is selected
	BOOL IsSelected=(pDrawItemStruct->itemState & ODS_SELECTED) ? TRUE : FALSE;
	// 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 std::exception();
	}
	// 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 std::exception();
	}
	if(dcMem.SelectBitmap(Bitmap)==NULL)
	{
		throw std::exception();
	}
	// map coordinates to the item
	if(dcMem.SetWindowOrg(Rect.left,Rect.top)==FALSE)
	{
		throw std::exception();
	}
	// draw the button
	DrawButton(CDCHandle(dcMem),Rect,HasFocus,IsSelected);
	// update the screen
	if(hDC.BitBlt(
		Rect.left,Rect.top,Rect.Width(),Rect.Height(),
			dcMem,Rect.left,Rect.top,SRCCOPY)==FALSE)
	{
		throw std::exception();
	}
CATCH_ALL
	return TRUE;
}

LRESULT CDDButton::OnBNClicked(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
{
TRY
	// fire the click event
	__raise Click();
CATCH_ALL
	return 0;
}

LRESULT CDDButton::OnButtonEraseBkgnd(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
	// to prevent flicker do not erase the background
	return TRUE;
}

STDMETHODIMP CDDButton::SetClientSite(IOleClientSite *pClientSite)
{
IMP_BEGIN
	// call the base class
	HRESULT hr=IOleObjectImpl<CDDButton>::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 CDDButton::SetObjectRects(LPCRECT prcPos,LPCRECT prcClip)
{
	// generated by the ATL control wizard
	IOleInPlaceObjectWindowlessImpl<CDDButton>::SetObjectRects(prcPos, prcClip);
	int cx, cy;
	cx = prcPos->right - prcPos->left;
	cy = prcPos->bottom - prcPos->top;
	::SetWindowPos(m_ctlButton.m_hWnd, NULL, 0,
		0, cx, cy, SWP_NOZORDER | SWP_NOACTIVATE);
	return S_OK;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
United Kingdom United Kingdom
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions