//----------------------------------------------------------------------------
// ObjectWindows
// Copyright (c) 1998 by Bidus Yura, All Rights Reserved
//
/// \file
/// Implementation of the TComboBoxEx class
//----------------------------------------------------------------------------
#include <owl/pch.h>
#include <owl/combobex.h>
#include <owl/imagelst.h>
#include <tchar.h>
using namespace std;
namespace owl {
OWL_DIAGINFO;
DIAG_DECLARE_GROUP(OwlCommCtrl); // CommonCtrl Diagnostic group
DEFINE_RESPONSE_TABLE1(TComboBoxEx, TComboBox)
EV_WM_COMPAREITEM,
EV_WM_DELETEITEM,
EV_WM_DRAWITEM,
EV_WM_MEASUREITEM,
END_RESPONSE_TABLE;
//
//
//
TComboBoxEx::TComboBoxEx(TWindow* parent, int id, int x, int y, int w, int h,
uint32 style, uint textLimit, TModule* module)
:
TComboBox(parent, id, x, y, w, h,style, textLimit, module),
ImageList(0),
ShouldDelete(false)
{
InitializeCommonControls(ICC_USEREX_CLASSES);
ModifyExStyle(WS_EX_CLIENTEDGE, 0); // Creates 3d sunken inside edge
}
//
//
TComboBoxEx::TComboBoxEx(TWindow* parent, int resourceId, uint textLen,
TModule* module)
:
TComboBox(parent, resourceId, textLen, module),
ImageList(0),
ShouldDelete(false)
{
InitializeCommonControls(ICC_USEREX_CLASSES);
}
//
/// Constructs an extended combo box object to encapsulate (alias) an existing control.
//
TComboBoxEx::TComboBoxEx(THandle hWnd, TModule* module)
:
TComboBox(hWnd, module),
ImageList(0),
ShouldDelete(false)
{
InitializeCommonControls(ICC_USEREX_CLASSES);
}
//
//
//
TComboBoxEx::~TComboBoxEx()
{
if(ShouldDelete)
delete ImageList;
}
//
/// Return the proper class name.
/// Windows class: WC_COMBOBOXEX is defined in commctrl.h
auto TComboBoxEx::GetWindowClassName() -> TWindowClassName
{
return TWindowClassName{WC_COMBOBOXEX};
}
//
//
//
void
TComboBoxEx::SetupWindow()
{
TComboBox::SetupWindow();
if(ImageList)
SendMessage(CBEM_SETIMAGELIST, 0, (LPARAM)(HIMAGELIST)*ImageList);
}
//
//
//
bool
TComboBoxEx::GetItem(TComboBoxExItem& item, INT_PTR index)
{
PRECONDITION(GetHandle());
((tstring&)item.Text()).reserve(MAX_PATH);
COMBOBOXEXITEM exitem;
item.InitItem(exitem, MAX_PATH);
if (index != -1)
exitem.iItem = index; // Use provided index.
if(SendMessage(CBEM_GETITEM, 0, TParam2(&exitem)) != 0){
item.ReFillItem(exitem);
return true;
}
return false;
}
//
/// Functional style overload
//
TComboBoxExItem
TComboBoxEx::GetItem(INT_PTR index)
{
TComboBoxExItem item;
GetItem(item, index);
return item;
}
//
//
//
int
TComboBoxEx::InsertItem(const TComboBoxExItem& item)
{
PRECONDITION(GetHandle());
COMBOBOXEXITEM exitem;
item.InitItem(exitem);
return (int)SendMessage(CBEM_INSERTITEM, 0, TParam2(&exitem));
}
//
//
//
bool
TComboBoxEx::SetItem(const TComboBoxExItem& item, INT_PTR index)
{
PRECONDITION(GetHandle());
COMBOBOXEXITEM exitem;
item.InitItem(exitem);
if (index != -1)
exitem.iItem = index; // Use provided index.
return SendMessage(CBEM_SETITEM, 0, TParam2(&exitem)) != 0;
}
//
//
//
void
TComboBoxEx::SetImageList(TImageList* list, TAutoDelete del)
{
if(GetHandle())
SendMessage(CBEM_SETIMAGELIST, 0, (LPARAM)(HIMAGELIST)*list);
if(ShouldDelete)
delete ImageList;
ShouldDelete = del == AutoDelete;
ImageList = list;
}
//
/// Transfers the items and selection of the combo box to or from a transfer buffer
/// if tdSetData or tdGetData, respectively, is passed as the direction. buffer is
/// expected to point to a TComboBoxExData structure.
///
/// Transfer returns the size of the TComboBoxExData structure. To retrieve the size
/// without transferring data, your application must pass tdSizeData as the
/// direction.
//
uint
TComboBoxEx::Transfer(void* buffer, TTransferDirection direction)
{
if (!buffer && direction != tdSizeData) return 0;
TComboBoxExData& data = *static_cast<TComboBoxExData*>(buffer);
if (direction == tdGetData)
{
// Clear out data and fill with contents of list box part.
//
data.Clear();
const int count = GetCount();
for(int i = 0; i != count; ++i)
data.AddItem(GetItem(i));
// Get the selected string from the list by index, or if no selection,
// get the selection string from the edit box.
//
int selIndex = GetSelIndex();
if (selIndex >= 0)
data.Select(selIndex);
else
data.SelectString(GetText());
}
else if (direction == tdSetData)
{
// Fill the list box part.
//
ClearList();
const int count = static_cast<int>(data.Size());
for (int i = 0; i != count; ++i)
InsertItem(data.GetItem(i));
// Set the selected item, if any, otherwise set the edit part.
//
if (data.GetSelIndex() >= 0)
SetSelIndex(data.GetSelIndex());
else
SetText(data.GetSelection());
}
return sizeof(TComboBoxExData);
}
////////////////////////////////////////////////////////////////////////////////
//
//
//
TComboBoxExItem::TComboBoxExItem()
{
Init();
}
//
//
//
TComboBoxExItem::TComboBoxExItem(const tstring& str, INT_PTR item, int image)
{
Init();
Item = item;
Text = str;
Image = image;
Selected = image; // By default use same image for both selected and unselected items
}
TComboBoxExItem::TComboBoxExItem(const tstring& str, INT_PTR item, int image, int selectedImage, int overlayImage, int indent, LPARAM param)
{
Init();
Item = item;
Text = str;
Image = image;
Selected = selectedImage;
Overlay = overlayImage;
Indent = indent;
Param = param;
}
//
/// Copies the property data, not the properties themselves.
//
TComboBoxExItem::TComboBoxExItem(const TComboBoxExItem& item)
{
operator =(item);
}
//
/// Assigns the property data, not the properties themselves.
//
TComboBoxExItem&
TComboBoxExItem::operator =(const TComboBoxExItem& item)
{
Mask = item.Mask();
Item = item.Item();
Text = item.Text();
Image = item.Image();
Selected = item.Selected();
Overlay = item.Overlay();
Indent = item.Indent();
Param = item.Param();
return *this;
}
//
//
//
void
TComboBoxExItem::InitItem(COMBOBOXEXITEM& item, uint tsize) const
{
memset(&item,0,sizeof(item));
item.mask = Mask();
item.iItem = Item();
if(Image() != -1){
item.mask |= CBEIF_IMAGE;
item.iImage |= Image();
}
if(Indent() != -1){
item.mask |= CBEIF_INDENT;
item.iIndent = Indent();
}
if(Param() != 0){
item.mask |= CBEIF_LPARAM;
item.lParam = Param();
}
if(Overlay() != -1){
item.mask |= CBEIF_OVERLAY;
item.iOverlay = Overlay();
}
if(Selected() != -1){
item.mask |= CBEIF_SELECTEDIMAGE;
item.iSelectedImage = Selected();
}
if(Text().length() || tsize){
item.mask |= CBEIF_TEXT;
item.pszText = (LPTSTR)Text().c_str();
item.cchTextMax = static_cast<int>(Text().length() > tsize ? Text().length() : tsize);
}
}
//
//
//
void
TComboBoxExItem::ReFillItem(const COMBOBOXEXITEM& item)
{
Mask = item.mask;
Item = item.iItem;
if(item.mask & CBEIF_IMAGE)
Image = item.iImage;
else
Image = -1;
if(item.mask & CBEIF_INDENT)
Indent = item.iIndent;
else
Indent = -1;
if(item.mask & CBEIF_LPARAM)
Param = item.lParam;
else
Param = 0;
if(item.mask & CBEIF_OVERLAY)
Overlay = item.iOverlay;
else
Overlay = -1;
if(item.mask & CBEIF_SELECTEDIMAGE)
Selected = item.iSelectedImage;
else
Selected = -1;
if(item.mask & CBEIF_TEXT)
Text = tstring(item.pszText);
else
Text = tstring(_T(""));
}
//
//
//
void
TComboBoxExItem::Init()
{
Mask = 0; //
Item = -1; //
Text = tstring(_T(""));
Image = -1;
Selected = -1;
Overlay = -1;
Indent = -1;
Param = 0;
}
// class TComboBoxExData
// ----- ---------------
//
TComboBoxExData::TComboBoxExData()
:
Selection(_T("")),
SelIndex(CB_ERR)
{
Items = new TComboBoxExItemArray;
}
//
//
//
TComboBoxExData::~TComboBoxExData()
{
delete Items;
}
//
//
//
int
TComboBoxExData::DeleteItem(int index)
{
return Items->Destroy(index);
}
//
//
//
int
TComboBoxExData::AddItem(const TComboBoxExItem& item)
{
return Items->Add(item);
}
//
//
//
TComboBoxExItem&
TComboBoxExData::GetItem(int index)
{
PRECONDITION(Items->Size() > (uint)index);
return (*Items)[index];
}
//
//
//
void
TComboBoxExData::Clear()
{
Items->Flush();
}
//
//
//
uint
TComboBoxExData::Size()
{
return Items->Size();
}
//
/// Copies the selected string into Buffer. BufferSize includes the terminating 0
//
void
TComboBoxExData::GetSelString(LPTSTR buffer, int bufferSize) const
{
_tcsncpy(buffer, Selection.c_str(), bufferSize);
}
//
/// Selects "str", marking the matching String entry (if any) as selected
//
void TComboBoxExData::SelectString(LPCTSTR str)
{
int numStrings = Items->Size();
SelIndex = CB_ERR;
for (int i = 0; i < numStrings; i++)
if (_tcscmp((*Items)[i].Text().c_str(), str) == 0)
{
SelIndex = i;
break;
}
if (Selection != str)
Selection = str;
}
} // OWL namespace
/* ========================================================================== */
↑ V522 There might be dereferencing of a potential null pointer.
↑ V818 It is more efficient to use an initialization list 'Item(item), Text(str), Image(image), Selected(image)' rather than an assignment operator.
↑ V818 It is more efficient to use an initialization list 'Item(item), Text(str), Image(image), Selected(selectedImage), Overlay(overlayImage), ...' rather than an assignment operator.