2025-11-28 00:35:46 +09:00

334 lines
8.2 KiB
C++

//-----------------------------------------------------------------------------
// File: Listbox.cpp
// Desc: Listbox control class
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#include "wincontrol.h"
#include "listbox.h"
//-----------------------------------------------------------------------------
// ListBox constructor
//-----------------------------------------------------------------------------
ListBox::ListBox()
: m_bMultiSelect(false)
{
}
//-----------------------------------------------------------------------------
// Name: SetWindow
// Desc: Override the base class to check if we are a multi-select list.
//-----------------------------------------------------------------------------
void ListBox::SetWindow(HWND hwnd)
{
Control::SetWindow(hwnd);
LONG style = GetWindowLong(m_hwnd, GWL_STYLE);
m_bMultiSelect = HasStyle(LBS_MULTIPLESEL) || HasStyle(LBS_EXTENDEDSEL);
}
//-----------------------------------------------------------------------------
// Name: Count
// Desc: Returns the number of items in the listbox.
//-----------------------------------------------------------------------------
UINT ListBox::Count()
{
LRESULT res = SendMessage(LB_GETCOUNT, 0, 0);
return (res == LB_ERR ? 0 : (UINT)res);
}
//-----------------------------------------------------------------------------
// Name: AddString
// Desc: Adds an item to the listbox.
//
// Returns TRUE if successful, or FALSE if an error occurred.
//-----------------------------------------------------------------------------
BOOL ListBox::AddString(LPCTSTR sz)
{
if (!sz)
{
return FALSE;
}
LRESULT res = SendMessage(LB_ADDSTRING, 0, (LPARAM)sz);
if (res == LB_ERR || res == LB_ERRSPACE)
{
return FALSE;
}
else
{
return TRUE;
}
}
//-----------------------------------------------------------------------------
// Name: GetString
// Desc: Returns a string at a specified index.
//
// ppStr: Receives a pointer to the string. The method allocates the string.
// The caller must free the string using CoTaskMemFree.
//
// Returns TRUE if successful, or FALSE if an error occurred.
//-----------------------------------------------------------------------------
BOOL ListBox::GetString(UINT index, TCHAR **ppStr)
{
if (!ppStr)
{
return FALSE;
}
*ppStr = NULL;
LRESULT cch = SendMessage(LB_GETTEXTLEN, (WPARAM)index, 0);
if (cch == LB_ERR)
{
return FALSE;
}
TCHAR *str = (TCHAR*)CoTaskMemAlloc(sizeof(TCHAR) * (cch + 1));
if (str == NULL)
{
return FALSE;
}
cch = SendMessage(LB_GETTEXT, (WPARAM)index, (LPARAM)str);
if (cch == LB_ERR)
{
CoTaskMemFree(str);
return FALSE;
}
*ppStr = str;
return TRUE;
}
//-----------------------------------------------------------------------------
// Name: AddItem
// Desc: Adds a string plus user data to a list box.
//
// Returns TRUE if successful, or FALSE if an error occurred.
//-----------------------------------------------------------------------------
BOOL ListBox::AddItem(LPCTSTR szName, void* pItemData)
{
if (!szName)
{
return FALSE;
}
LRESULT result = SendMessage(LB_ADDSTRING, 0, (LPARAM)szName);
if (result == LB_ERR || result == LB_ERRSPACE)
{
return FALSE;
}
if (pItemData)
{
UINT index = (UINT)result;
result = SendMessage(LB_SETITEMDATA, (WPARAM)index, (LPARAM)pItemData);
if (result == LB_ERR)
{
// ??
SendMessage(LB_DELETESTRING, index, 0);
return FALSE;
}
}
return TRUE;
}
//-----------------------------------------------------------------------------
// Name: GetItem
// Desc: Returns the user data associated with a listbox item (or NULL).
//
// index: Index of the listbox item.
//-----------------------------------------------------------------------------
void* ListBox::GetItem(UINT index)
{
LRESULT result = SendMessage(LB_GETITEMDATA, index, 0);
if (result == LB_ERR)
{
return NULL;
}
return (void*)result;
}
//-----------------------------------------------------------------------------
// Name: Select
// Desc: Sets the current selection.
//
// index: Zero-based index.
// Returns TRUE if successful, or FALSE if an error occurred.
//-----------------------------------------------------------------------------
BOOL ListBox::Select(UINT index)
{
LRESULT res;
if (IsMultiSelect())
{
res = SendMessage(LB_SETSEL, (WPARAM)TRUE, (LPARAM)index);
}
else
{
res = SendMessage(LB_SETCURSEL, (WPARAM)index, 0);
}
if (res == LB_ERR)
{
return FALSE;
}
else
{
return TRUE;
}
}
//-----------------------------------------------------------------------------
// Name: GetCurrentSelection
// Desc: Returns the current selection. (Single-select list only)
//
// pindex: Receives the zero-based index of the current selection.
// Returns TRUE if successful, or FALSE if an error occurred.
//-----------------------------------------------------------------------------
BOOL ListBox::GetCurrentSelection(UINT *pindex)
{
if (!pindex)
{
return FALSE;
}
if (IsMultiSelect())
{
return FALSE;
}
LRESULT res = SendMessage(LB_GETCURSEL, 0, 0);
if (res == LB_ERR)
{
return FALSE;
}
else
{
*pindex = (int)res;
return TRUE;
}
}
//-----------------------------------------------------------------------------
// Name: GetMultiSelection
// Desc: Returns an array of selection indices. (Multi-select list only)
//
// ppIndexes: Receives a pointer to the array. The caller must free the
// array, using CoTaskMemFree
// pCount: Receives the size of the array.
//
// Returns TRUE if successful, or FALSE if an error occurred.
//-----------------------------------------------------------------------------
BOOL ListBox::GetMultiSelection(UINT **ppIndexes, UINT *pCount)
{
if (!ppIndexes || !pCount)
{
return FALSE;
}
*ppIndexes = NULL;
*pCount = 0;
if (!IsMultiSelect())
{
return FALSE;
}
UINT selCount = (UINT)SendMessage(LB_GETSELCOUNT, 0, 0);
if (selCount == LB_ERR)
{
return FALSE;
}
UINT *pIndexes = (UINT*)CoTaskMemAlloc(sizeof(UINT) * selCount);
if (pIndexes == NULL)
{
return FALSE;
}
if (LB_ERR == SendMessage(LB_GETSELITEMS, (WPARAM)selCount, (LPARAM)pIndexes))
{
CoTaskMemFree(pIndexes);
return FALSE;
}
*pCount = selCount;
*ppIndexes = pIndexes;
return TRUE;
}
//-----------------------------------------------------------------------------
// Name: ClearSelection
// Desc: Clears the current selection.
//-----------------------------------------------------------------------------
void ListBox::ClearSelection()
{
if (m_bMultiSelect)
{
UINT c = Count();
for (UINT i = 0; i < c; i++)
{
SendMessage(LB_SETSEL, (WPARAM)FALSE, (LPARAM)i);
}
}
else
{
SendMessage(LB_SETCURSEL, -1, 0);
// Per MSDN: In this case, SendMessage returns LB_ERR even though
// no error has occurred. Go figure.
}
}
//-----------------------------------------------------------------------------
// Name: DeleteItem
// Desc: Deletes a listbox item.
//
// Note: Does not release any user data associated with the item.
//-----------------------------------------------------------------------------
BOOL ListBox::DeleteItem(UINT index)
{
LRESULT res = SendMessage(LB_DELETESTRING, index, 0);
return (res == LB_ERR ? FALSE : TRUE);
}
//-----------------------------------------------------------------------------
// Name: ClearItems
// Desc: Removes all items.
//-----------------------------------------------------------------------------
void ListBox::ClearItems()
{
SendMessage(LB_RESETCONTENT, 0, 0);
}