// DDListBox.cpp : Implementation of CDDListBox
//
// Author : David Shepherd
// Copyright (c) 2003, DaeDoe-Software
//
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include ".\DDListBox.h"
/////////////////////////////////////////////////////////////////////////////
// CDDListBox
#pragma warning(push)
#pragma warning(disable: 4355) // 'this' : used in base member initializer list
CDDListBox::CDDListBox() : m_ctlListBox(_T("ListBox"), 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_Sorted=VARIANT_FALSE;
m_Redraw=VARIANT_TRUE;
}
HRESULT CDDListBox::FinalConstruct()
{
IMP_BEGIN
// create the background brush
CreateBackgroundBrush(m_BackColor);
// create the default font
m_spFontDisp=CreateDefaultFont();
IMP_END
return RetVal;
}
void CDDListBox::FinalRelease()
{
}
const TCHAR* CDDListBox::GetObjectFriendlyName()
{
// return the object friendly name
return _T("DDListBox");
}
HRESULT CDDListBox::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 CDDListBox::OnEnabledChanged()
{
TRY
// update the list box
// this is done indirectly by enabling the parent window
if(IsWindow())
{
(void)EnableWindow(VB2B(m_Enabled));
}
CATCH_ALL
}
void CDDListBox::OnBackColorChanged()
{
TRY
// update the list box
if(m_ctlListBox.IsWindow())
{
(void)m_ctlListBox.Invalidate();
}
CATCH_ALL
}
void CDDListBox::OnForeColorChanged()
{
TRY
// update the list box
if(m_ctlListBox.IsWindow())
{
(void)m_ctlListBox.Invalidate();
}
CATCH_ALL
}
void CDDListBox::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 CDDListBox::PreTranslateAccelerator(LPMSG pMsg, HRESULT& hRet)
{
// this will be set TRUE if the key press was handled
BOOL Handled=FALSE;
TRY
// if the list box has focus
if(GetFocus()==m_ctlListBox and
// and this is a key down message
pMsg->message==WM_KEYDOWN)
{
// 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)
{
(void)m_ctlListBox.SendMessage(pMsg->message,pMsg->wParam,pMsg->lParam);
Handled=TRUE;
}
}
// if the key press was handled
if(Handled)
{
// signal success
hRet=S_OK;
}
CATCH_ALL
return Handled;
}
LRESULT CDDListBox::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
TRY
// create the list box
if(m_ctlListBox.Create(*this,CRect(0,0,0,0),_T(""),
// standard window styles
WS_CHILD|WS_VISIBLE|WS_VSCROLL|
// list box styles
LBS_HASSTRINGS|LBS_NOINTEGRALHEIGHT|LBS_NOTIFY|
// list box styles that can only be applied at creation time
(m_Sorted ? LBS_SORT : 0),
// extended styles
WS_EX_CLIENTEDGE,
// id
IDC_LISTBOX)==NULL)
{
throw std::exception();
}
// update the list box
if(!SUCCEEDED(put_Enabled(m_Enabled)))
{
throw std::exception();
}
if(!SUCCEEDED(put_Font(m_spFontDisp)))
{
throw std::exception();
}
CATCH_ALL
return Caught ? -1 : 0;
}
LRESULT CDDListBox::OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
// generated by the ATL control wizard
LRESULT lRes = CComControl<CDDListBox>::OnSetFocus(uMsg, wParam, lParam, bHandled);
if (m_bInPlaceActive)
{
if(!IsChild(::GetFocus()))
m_ctlListBox.SetFocus();
}
return lRes;
}
LRESULT CDDListBox::OnCtlColorListBox(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 CDDListBox::OnListBoxSelChanged(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
{
TRY
PROPERTY_CHANGED(DISPID_SELECTEDITEM)
// fire the change event
__raise Change();
CATCH_ALL
return 0;
}
STDMETHODIMP CDDListBox::SetObjectRects(LPCRECT prcPos,LPCRECT prcClip)
{
// generated by the ATL control wizard
IOleInPlaceObjectWindowlessImpl<CDDListBox>::SetObjectRects(prcPos, prcClip);
int cx, cy;
cx = prcPos->right - prcPos->left;
cy = prcPos->bottom - prcPos->top;
::SetWindowPos(m_ctlListBox.m_hWnd, NULL, 0,
0, cx, cy, SWP_NOZORDER | SWP_NOACTIVATE);
return S_OK;
}
STDMETHODIMP CDDListBox::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 CDDListBox::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 CDDListBox::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_ctlListBox.IsWindow())
{
m_ctlListBox.SetFont(hFont);
}
m_spFontDisp=newVal;
PROPERTY_CHANGED(DISPID_FONT)
IMP_END
return RetVal;
}
STDMETHODIMP CDDListBox::get_Redraw(VARIANT_BOOL* pVal)
{
IMP_BEGIN
// check parameters
if(pVal==NULL)
{
throw CHResult(E_POINTER);
}
// check the list box is created
if(m_ctlListBox.IsWindow()==FALSE)
{
throw CHResult(E_FAIL);
}
// get the redraw state
*pVal=m_Redraw;
IMP_END
return RetVal;
}
STDMETHODIMP CDDListBox::put_Redraw(VARIANT_BOOL newVal)
{
IMP_BEGIN
REQUEST_EDIT(DISPID_REDRAW)
// check parameters
if(newVal!=VARIANT_TRUE and newVal!=VARIANT_FALSE)
{
throw CHResult(E_INVALIDARG);
}
// check the list box is created
if(m_ctlListBox.IsWindow()==FALSE)
{
throw CHResult(E_FAIL);
}
// set the redraw state
m_ctlListBox.SetRedraw(VB2B(newVal));
if(newVal)
{
(void)m_ctlListBox.Invalidate();
}
m_Redraw=newVal;
PROPERTY_CHANGED(DISPID_REDRAW)
IMP_END
return RetVal;
}
STDMETHODIMP CDDListBox::get_SelectedItem(BSTR* pVal)
{
IMP_BEGIN
// check parameters
if(pVal==NULL)
{
throw CHResult(E_POINTER);
}
// check the list box is created
if(m_ctlListBox.IsWindow()==FALSE)
{
throw CHResult(E_FAIL);
}
// wrap the list box
CListBox ListBox(m_ctlListBox);
// get the index of the selected item
LONG Ix=ListBox.GetCurSel();
if(Ix!=LB_ERR)
{
// get the selected item text
if(ListBox.GetTextBSTR(Ix,*pVal)==FALSE)
{
throw CHResult(E_FAIL);
}
}
else // there is no selection
{
*pVal=NULL;
}
// todo : update m_SelectedItem
IMP_END
return RetVal;
}
STDMETHODIMP CDDListBox::put_SelectedItem(BSTR newVal)
{
IMP_BEGIN
// request edit can not be applied to this property since the
// list box selection can be changed by the user at any time
USES_CONVERSION;
// check the list box is created
if(m_ctlListBox.IsWindow()==FALSE)
{
throw CHResult(E_FAIL);
}
// wrap the list box
CListBox ListBox(m_ctlListBox);
// if the selection should be cleared
if(wcslen(BSTR2W(newVal))==0)
{
(void)ListBox.SetCurSel(-1);
}
else // the selection should not be cleared
{
// get the index of the item to select
LONG Ix=ListBox.FindStringExact(-1,W2CT(BSTR2W(newVal)));
if(Ix==LB_ERR)
{
throw CHResult(E_FAIL);
}
// select the item
if(ListBox.SetCurSel(Ix)==LB_ERR)
{
throw CHResult(E_FAIL);
}
}
// todo : update m_SelectedItem
PROPERTY_CHANGED(DISPID_SELECTEDITEM)
IMP_END
return RetVal;
}
STDMETHODIMP CDDListBox::AddItem(BSTR Text)
{
IMP_BEGIN
USES_CONVERSION;
// check parameters
if(wcslen(BSTR2W(Text))==0)
{
throw CHResult(E_INVALIDARG);
}
// check the list box is created
if(m_ctlListBox.IsWindow()==FALSE)
{
throw CHResult(E_FAIL);
}
// wrap the list box
CListBox ListBox(m_ctlListBox);
// ensure the item does not already exist
LONG Ix=ListBox.FindStringExact(-1,W2CT(BSTR2W(Text)));
if(Ix!=LB_ERR)
{
throw CHResult(E_FAIL);
}
// add the item
Ix=ListBox.AddString(W2CT(BSTR2W(Text)));
if(Ix==LB_ERR or Ix==LB_ERRSPACE)
{
throw CHResult(E_FAIL);
}
IMP_END
return RetVal;
}
STDMETHODIMP CDDListBox::RemoveItem(BSTR Text)
{
IMP_BEGIN
USES_CONVERSION;
// check parameters
if(wcslen(BSTR2W(Text))==0)
{
throw CHResult(E_INVALIDARG);
}
// check the list box is created
if(m_ctlListBox.IsWindow()==FALSE)
{
throw CHResult(E_FAIL);
}
// wrap the list box
CListBox ListBox(m_ctlListBox);
// ensure the item exists
LONG Ix=ListBox.FindStringExact(-1,W2CT(BSTR2W(Text)));
if(Ix==LB_ERR)
{
throw CHResult(E_FAIL);
}
// remove the item
if(ListBox.DeleteString(Ix)==LB_ERR)
{
throw CHResult(E_FAIL);
}
IMP_END
return RetVal;
}
STDMETHODIMP CDDListBox::Clear()
{
IMP_BEGIN
// check the list box is created
if(m_ctlListBox.IsWindow()==FALSE)
{
throw CHResult(E_FAIL);
}
// wrap the list box
CListBox ListBox(m_ctlListBox);
// clear the list box
ListBox.ResetContent();
IMP_END
return RetVal;
}
STDMETHODIMP CDDListBox::get__Default(BSTR* pVal)
{
// delegate to the required default property
return get_SelectedItem(pVal);
}
STDMETHODIMP CDDListBox::put__Default(BSTR newVal)
{
// delegate to the required default property
return put_SelectedItem(newVal);
}