// DDTextBox.cpp : Implementation of CDDTextBox
//
// Author : David Shepherd
// Copyright (c) 2003, DaeDoe-Software
//
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include ".\DDTextBox.h"
/////////////////////////////////////////////////////////////////////////////
// CDDTextBox
#pragma warning(push)
#pragma warning(disable: 4355) // 'this' : used in base member initializer list
CDDTextBox::CDDTextBox() : m_ctlEdit(_T("Edit"), 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_WINDOW);
m_ForeColor=MAKE_OLE_COLOR(COLOR_WINDOWTEXT);
m_hAccel=NULL;
}
HRESULT CDDTextBox::FinalConstruct()
{
IMP_BEGIN
// create the background brush
CreateBackgroundBrush(m_BackColor);
// create the default font
m_spFontDisp=CreateDefaultFont();
IMP_END
return RetVal;
}
void CDDTextBox::FinalRelease()
{
}
const TCHAR* CDDTextBox::GetObjectFriendlyName()
{
// return the object friendly name
return _T("DDTextBox");
}
HRESULT CDDTextBox::OnBackColorChanging(OLE_COLOR newVal)
{
IMP_BEGIN
// create the background brush
// if this fails the background color will remain unchanged
CreateBackgroundBrush(newVal);
IMP_END
return RetVal;
}
void CDDTextBox::OnEnabledChanged()
{
TRY
// update the edit box
// this is done indirectly by enabling the parent window
if(IsWindow())
{
(void)EnableWindow(VB2B(m_Enabled));
}
CATCH_ALL
}
void CDDTextBox::OnBackColorChanged()
{
TRY
// update the edit box
if(m_ctlEdit.IsWindow())
{
(void)m_ctlEdit.Invalidate();
}
CATCH_ALL
}
void CDDTextBox::OnForeColorChanged()
{
TRY
// update the edit box
if(m_ctlEdit.IsWindow())
{
(void)m_ctlEdit.Invalidate();
}
CATCH_ALL
}
void CDDTextBox::CreateBackgroundBrush(OLE_COLOR BackColor)
{
// create the background brush
COLORREF RGBBackColor=RGB(0,0,0);
if(!SUCCEEDED(OleTranslateColor(BackColor,NULL,&RGBBackColor)))
{
throw std::exception();
}
CBrush Brush;
if(Brush.CreateSolidBrush(RGBBackColor)==NULL)
{
throw std::exception();
}
if(m_BackBrush!=NULL)
{
(void)m_BackBrush.DeleteObject();
}
m_BackBrush.Attach(Brush.Detach());
}
BOOL CDDTextBox::PreTranslateAccelerator(LPMSG pMsg, HRESULT& hRet)
{
// this will be set TRUE if the key press was handled
BOOL Handled=FALSE;
TRY
// if the edit box has focus
if(GetFocus()==m_ctlEdit and
// and this is a key down message
pMsg->message==WM_KEYDOWN)
{
// get shift key modifiers
BOOL Ctrl = (GetKeyState(VK_CONTROL) & 0x80000000) ? TRUE : FALSE;
BOOL Shift = (GetKeyState(VK_SHIFT ) & 0x80000000) ? TRUE : FALSE;
BOOL Alt = (GetKeyState(VK_MENU ) & 0x80000000) ? TRUE : FALSE;
// tab key
if(pMsg->wParam==VK_TAB)
{
(void)m_ctlEdit.SendMessage(EM_REPLACESEL,TRUE,(LPARAM)_T("\t"));
Handled=TRUE;
}
// arrow key
if( pMsg->wParam==VK_LEFT or
pMsg->wParam==VK_RIGHT or
pMsg->wParam==VK_UP or
pMsg->wParam==VK_DOWN or
// other navigation
pMsg->wParam==VK_HOME or
pMsg->wParam==VK_END or
pMsg->wParam==VK_PRIOR or
pMsg->wParam==VK_NEXT or
// del
pMsg->wParam==VK_DELETE)
{
(void)m_ctlEdit.SendMessage(pMsg->message,pMsg->wParam,pMsg->lParam);
Handled=TRUE;
}
// cut / copy / paste / undo
if(Handled==FALSE)
{
if(::TranslateAccelerator(*this,m_hAccel,pMsg)!=0)
{
Handled=TRUE;
}
}
}
// if the key press was handled
if(Handled)
{
// signal success
hRet=S_OK;
}
CATCH_ALL
return Handled;
}
LRESULT CDDTextBox::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
TRY
// create the edit box
if(m_ctlEdit.Create(*this,CRect(0,0,0,0),_T(""),
// standard window styles
WS_CHILD|WS_VISIBLE|
// edit box styles
ES_AUTOHSCROLL|ES_AUTOVSCROLL|ES_MULTILINE|ES_WANTRETURN,
// extended styles
WS_EX_CLIENTEDGE,
// id
IDC_EDIT)==NULL)
{
throw std::exception();
}
// update the edit box
if(!SUCCEEDED(put_Enabled(m_Enabled)))
{
throw std::exception();
}
if(!SUCCEEDED(put_Font(m_spFontDisp)))
{
throw std::exception();
}
if(!SUCCEEDED(put_Text(m_Text)))
{
throw std::exception();
}
// load the edit box accelerators
m_hAccel=LoadAccelerators(_pModule->GetResourceInstance(),
MAKEINTRESOURCE(IDA_DDTEXTBOX));
if(m_hAccel==NULL)
{
throw std::exception();
}
CATCH_ALL
return Caught ? -1 : 0;
}
LRESULT CDDTextBox::OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
// generated by the ATL control wizard
LRESULT lRes = CComControl<CDDTextBox>::OnSetFocus(uMsg, wParam, lParam, bHandled);
if (m_bInPlaceActive)
{
if(!IsChild(::GetFocus()))
m_ctlEdit.SetFocus();
}
return lRes;
}
LRESULT CDDTextBox::OnCtlColorEdit(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
TRY
// wrap the device context
CDCHandle hDC=(HDC)wParam;
// set the background color
COLORREF RGBBackColor=RGB(0,0,0);
if(!SUCCEEDED(OleTranslateColor(m_BackColor,NULL,&RGBBackColor)))
{
throw std::exception();
}
if(hDC.SetBkColor(RGBBackColor)==CLR_INVALID)
{
throw std::exception();
}
// set the foreground color
COLORREF RGBForeColor=RGB(0,0,0);
if(!SUCCEEDED(OleTranslateColor(m_ForeColor,NULL,&RGBForeColor)))
{
throw std::exception();
}
if(hDC.SetTextColor(RGBForeColor)==CLR_INVALID)
{
throw std::exception();
}
CATCH_ALL
// return the background brush
// todo : recover correctly if an exception is thrown
return (LRESULT)(HBRUSH)m_BackBrush;
}
LRESULT CDDTextBox::OnEditChanged(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
{
TRY
PROPERTY_CHANGED(DISPID_TEXT);
// fire the change event
__raise Change();
CATCH_ALL
return 0;
}
LRESULT CDDTextBox::OnCut(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
{
TRY
// cut
if(m_ctlEdit.IsWindow())
{
(void)m_ctlEdit.SendMessage(WM_CUT);
}
CATCH_ALL
return 0;
}
LRESULT CDDTextBox::OnCopy(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
{
TRY
// copy
if(m_ctlEdit.IsWindow())
{
(void)m_ctlEdit.SendMessage(WM_COPY);
}
CATCH_ALL
return 0;
}
LRESULT CDDTextBox::OnPaste(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
{
TRY
// paste
if(m_ctlEdit.IsWindow())
{
(void)m_ctlEdit.SendMessage(WM_PASTE);
}
CATCH_ALL
return 0;
}
LRESULT CDDTextBox::OnUndo(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
{
TRY
// undo
if(m_ctlEdit.IsWindow())
{
(void)m_ctlEdit.SendMessage(WM_UNDO);
}
CATCH_ALL
return 0;
}
STDMETHODIMP CDDTextBox::SetObjectRects(LPCRECT prcPos,LPCRECT prcClip)
{
// generated by the ATL control wizard
IOleInPlaceObjectWindowlessImpl<CDDTextBox>::SetObjectRects(prcPos, prcClip);
int cx, cy;
cx = prcPos->right - prcPos->left;
cy = prcPos->bottom - prcPos->top;
::SetWindowPos(m_ctlEdit.m_hWnd, NULL, 0,
0, cx, cy, SWP_NOZORDER | SWP_NOACTIVATE);
return S_OK;
}
STDMETHODIMP CDDTextBox::get_Font(IFontDisp** pVal)
{
IMP_BEGIN
// check parameters
if(pVal==NULL)
{
throw CHResult(E_POINTER);
}
// get the font
*pVal=m_spFontDisp;
if(*pVal!=NULL) // add ref it
{
(void)(*pVal)->AddRef();
}
IMP_END
return RetVal;
}
STDMETHODIMP CDDTextBox::put_Font(IFontDisp* newVal)
{
IMP_BEGIN
REQUEST_EDIT(DISPID_FONT)
// check parameters
if(newVal==NULL)
{
throw CHResult(E_POINTER);
}
// clone the passed font and delegate to putref_Font
if(!SUCCEEDED(putref_Font(CloneFont(newVal))))
{
throw CHResult(E_FAIL);
}
PROPERTY_CHANGED(DISPID_FONT)
IMP_END
return RetVal;
}
STDMETHODIMP CDDTextBox::putref_Font(IFontDisp* newVal)
{
IMP_BEGIN
REQUEST_EDIT(DISPID_FONT)
// check parameters
if(newVal==NULL)
{
throw CHResult(E_POINTER);
}
// set the font
CComQIPtr<IFont> spFont(newVal);
if(spFont==NULL)
{
throw CHResult(E_FAIL);
}
CFontHandle hFont=NULL;
if(!SUCCEEDED(spFont->get_hFont(&hFont.m_hFont)))
{
throw CHResult(E_FAIL);
}
if(m_ctlEdit.IsWindow())
{
m_ctlEdit.SetFont(hFont);
}
m_spFontDisp=newVal;
PROPERTY_CHANGED(DISPID_FONT)
IMP_END
return RetVal;
}
STDMETHODIMP CDDTextBox::get_Text(BSTR* pVal)
{
IMP_BEGIN
// check parameters
if(pVal==NULL)
{
throw CHResult(E_POINTER);
}
// get the text
if(m_ctlEdit.IsWindow())
{
if(m_ctlEdit.GetWindowText(&m_Text)==FALSE)
{
throw CHResult(E_FAIL);
}
}
*pVal=CComBSTR(m_Text).Detach();
IMP_END
return RetVal;
}
STDMETHODIMP CDDTextBox::put_Text(BSTR newVal)
{
IMP_BEGIN
// request edit can not be applied to this property since the
// edit box text can be changed by the user at any time
USES_CONVERSION;
// set the text
if(m_ctlEdit.IsWindow())
{
if(m_ctlEdit.SetWindowText(W2CT(BSTR2W(newVal)))==FALSE)
{
throw CHResult(E_FAIL);
}
}
m_Text=newVal;
PROPERTY_CHANGED(DISPID_TEXT)
IMP_END
return RetVal;
}
STDMETHODIMP CDDTextBox::get__Default(BSTR* pVal)
{
// delegate to the required default property
return get_Text(pVal);
}
STDMETHODIMP CDDTextBox::put__Default(BSTR newVal)
{
// delegate to the required default property
return put_Text(newVal);
}