home *** CD-ROM | disk | FTP | other *** search
- // ObjectWindows - (C) Copyright 1992 by Borland International
-
- /* --------------------------------------------------------
- LISTBOX.CPP
- Defines type TListBox. This defines the basic behavior
- of all listbox controls.
- -------------------------------------------------------- */
-
- #include "listbox.h"
- #include <stdlib.h>
-
- #define MULTIPLESEL (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)
-
- /* Constructs Strings and SelStrings, and initializes SelCount
- to zero. */
- TListBoxData::TListBoxData()
- {
- SelCount = 0;
- Strings = new Array(10, 0, 10);
- SelStrings = new Array(10, 0, 10);
- }
-
- /* Deletes Strings and SelStrings. */
- TListBoxData::~TListBoxData()
- {
- if ( Strings )
- delete Strings;
- if ( SelStrings )
- delete SelStrings ;
- }
-
- /* Adds the specified string to Strings. If IsSelected is
- TRUE, also adds the string to SelStrings. */
- void TListBoxData::AddString(Pchar AString, BOOL IsSelected)
- {
- Strings->add(*new String(AString));
- if ( IsSelected )
- SelStrings->addAt(*new String(AString), SelCount++);
- }
-
- /* Adds the specified string to SelStrings. */
- void TListBoxData::SelectString(LPSTR AString)
- {
- Pchar TmpString = new char[_fstrlen(AString) + 1];
- _fstrcpy(TmpString, AString);
- SelStrings->addAt(*new String(TmpString), SelCount++);
- delete TmpString;
- }
-
- /* Removes all strings from SelStrings and sets SelCount to 0. */
- void TListBoxData::ResetSelections()
- {
- SelStrings->flush();
- SelCount = 0;
- }
-
- /* Returns the length of the string at the passed index in
- SelStrings excluding the terminating null. */
- int TListBoxData::GetSelStringLength(int Index)
- {
- if (Index >= 0 && Index < SelCount)
- return strlen((PCchar)(RString)(*SelStrings)[Index]);
- else
- return -1;
- }
-
- /* Copies the string at the passed index in SelStrings into
- Buffer. BufferSize includes the terminating null. */
- void TListBoxData::GetSelString(LPSTR Buffer, int BufferSize, int Index)
- {
- if (BufferSize > 0)
- {
- if (Index >= 0 && Index < SelCount)
- {
- _fstrncpy(Buffer, (PCchar)(RString)(*SelStrings)[Index],
- BufferSize-1);
- Buffer[BufferSize - 1] = '\0';
- }
- else
- Buffer[0] = '\0';
- }
- }
-
- /* Constructor for an instance of TListBox. Initializes its data fields
- using parameters passed and default values. By default, an MS-Windows
- listbox associated with the TListBox will: be visible upon creation;
- have a border and a vertical scrollbar; maintain entries in
- alphabetical order; and notify its parent when a selection is made. */
- TListBox::TListBox(PTWindowsObject AParent, int AnId, int X, int Y,
- int W, int H, PTModule AModule)
- : TControl(AParent, AnId, NULL, X, Y, W, H, AModule)
- {
- Attr.Style |= LBS_STANDARD;
- }
-
- static void DoAddForLB(RObject AString, Pvoid AListBox)
- {
- if (AString!=NOOBJECT)
- ((PTListBox)AListBox)->AddString((Pchar)(PCchar)(RString)AString);
- }
-
- /* Transfers state information for a TListBox. The TransferFlag passed
- specifies whether data is to be read from or written to the passed
- buffer, or whether the data element size is simply to be returned.
- The return value is the size (in bytes) of the transfer data. */
- WORD TListBox::Transfer(Pvoid DataPtr, WORD TransferFlag)
- {
- int I, SelIndex;
- long Style;
- int *Selections;
- int MaxStringLen = 0, TmpStringLen = 0;
- Pchar TmpString;
- PTListBoxData ListBoxData = *(PTListBoxData _FAR *)DataPtr;
-
- Style = GetWindowLong(HWindow, GWL_STYLE);
- if ( TransferFlag == TF_GETDATA )
- {
- // first, clear out Strings array and fill with contents of list box
- ListBoxData->Strings->flush();
-
- for (int i=0; i<GetCount(); i++) {
- TmpString = new char[GetStringLen(i)+1];
- GetString(TmpString, i);
- ListBoxData->AddString(TmpString, FALSE);
- delete TmpString;
- }
-
- // then update transfer data with new selected item(s)
- ListBoxData->ResetSelections();
- if ( (Style & MULTIPLESEL) == 0 ) // single selection
- {
- // Get selected item
- SelIndex = (int)SendMessage(HWindow, LB_GETCURSEL, 0, 0);
- if ( SelIndex != LB_ERR )
- {
- // allocate string for selected item and copy string to transfer data
- MaxStringLen = GetStringLen(SelIndex);
- TmpString = new char[MaxStringLen + 1];
- GetString(TmpString, SelIndex);
- ListBoxData->SelectString(TmpString);
- delete TmpString;
- }
- }
- else // multiple selection
- {
- I = GetSelCount();
- if ( I > 0 )
- {
- Selections = new int[I];
- SendMessage(HWindow, LB_GETSELITEMS, I, (long)(Selections));
- // loop through all selections to find longest string
- for (int SelIndex = 0; SelIndex < I; SelIndex++)
- {
- TmpStringLen = GetStringLen(Selections[SelIndex]);
- if ( TmpStringLen > MaxStringLen )
- MaxStringLen = TmpStringLen;
- }
- // allocate temporary string large enough to hold longest selection
- TmpString = new char[MaxStringLen+1];
- for (SelIndex = 0; SelIndex < I; SelIndex++)
- {
- GetString(TmpString, Selections[SelIndex]);
- ListBoxData->SelectString(TmpString);
- }
- delete TmpString;
- delete Selections;
- }
- }
- }
- else if ( TransferFlag == TF_SETDATA )
- {
- ClearList();
- // add each string in ListBoxData to list box
- ListBoxData->Strings->forEach(DoAddForLB, this);
-
- // now update selected item(s) as per ListBoxData
-
- if ( (Style & MULTIPLESEL) == 0 )
- { // single selection list box
- if ( ListBoxData->SelCount )
- {
- SelIndex = FindExactString((LPSTR)(PCchar)(RString)
- (*ListBoxData->SelStrings)[0], -1);
- if ( SelIndex > -1 )
- SetSelIndex(SelIndex);
- }
- }
- else // multiple selection list box
- {
- SendMessage(HWindow, LB_SETSEL, 0, -1); // Unselect all
-
- for (I = 0; I < ListBoxData->SelCount; ++I)
- {
- SelIndex = FindExactString((LPSTR)(PCchar)(RString)
- (*ListBoxData->SelStrings)[I], -1);
- if ( SelIndex > -1 )
- SendMessage(HWindow, LB_SETSEL, 1, SelIndex);
- }
- }
- }
- return sizeof(PTListBoxData);
- }
-
- /* Adds a string to an associated listbox. Returns index of the string
- in the list (the first entry is at index 0). A negative value is
- returned if an error occurs. */
- int TListBox::AddString(LPSTR AString)
- {
- return (int)(SendMessage(HWindow, GetMsgID(MN_ADDSTRING),
- 0, (long)AString));
- }
-
- /* Inserts a string in the associated listbox at the passed index,
- returning the index of the string in the list. A negative value is
- returned if an error occurs. */
- int TListBox::InsertString(LPSTR AString, int Index)
- {
- return (int)SendMessage(HWindow, GetMsgID(MN_INSERTSTRING),
- Index, (long)AString);
- }
-
- /* Deletes the string at the passed index in the associated listbox.
- Returns a count of the entries remaining in the list. A negative
- value is returned if an error occurs. */
- int TListBox::DeleteString(int Index)
- {
- return (int)SendMessage(HWindow, GetMsgID(MN_DELETESTRING), Index, 0);
- }
-
- /* Clears all the entries in the associated listbox. */
- void TListBox::ClearList()
- {
- SendMessage(HWindow, GetMsgID(MN_RESETCONTENT), 0, 0);
- }
-
- /* Returns the number of entries in the associated listbox. A negative
- value is returned if an error occurs. */
- int TListBox::GetCount()
- {
- return (int)SendMessage(HWindow, GetMsgID(MN_GETCOUNT), 0, 0);
- }
-
- /* Returns the index of the first string in the associated listbox
- which begins with the passed string. Searches for a match beginning
- at the passed SearchIndex. If a match is not found after the last
- string has been compared, the search continues from the beginning of
- the list until a match is found or until the list has been completely
- traversed. Searches from beginning of list when -1 is passed as the
- index. Returns the index of the selected string. A negative value
- is returned if an error occurs. For single or multiple-selection
- list boxes. */
- int TListBox::FindString(LPSTR Prefix, int SearchIndex)
- {
- return (int)SendMessage(HWindow, GetMsgID(MN_FINDSTRING),
- SearchIndex, (long)Prefix);
- }
-
- /* Returns the index of the first string in the associated listbox
- which is the same as the passed string. Searches for a match
- beginning at the passed SearchIndex. If a match is not found after
- the last string has been compared, the search continues from the
- beginning of the list until a match is found or until the list has
- been completely traversed. Searches from beginning of list when -1
- is passed as the index. Returns the index of the selected string.
- A negative value is returned if an error occurs. For single or
- multiple-selection list boxes. */
- int TListBox::FindExactString(LPSTR AString, int SearchIndex)
- {
- Pchar TmpString;
- int FirstMatch;
- BOOL Found = FALSE;
-
- FirstMatch = SearchIndex = (int)SendMessage(HWindow,
- GetMsgID(MN_FINDSTRING), SearchIndex, (long)AString);
- do
- {
- if ( SearchIndex > -1 )
- {
- TmpString = new char[GetStringLen(SearchIndex) + 1];
- GetString(TmpString, SearchIndex);
- if ( lstrcmp(TmpString, AString) == 0 )
- Found = TRUE;
- else
- SearchIndex = (int)SendMessage(HWindow,
- GetMsgID(MN_FINDSTRING), SearchIndex, (long)AString);
- delete TmpString;
- }
- } while ( !Found && SearchIndex != FirstMatch );
-
- if ( !Found )
- return -1;
- else
- return SearchIndex;
- }
-
- /* Retrieves the contents of the string at the passed index of the
- associated listbox, returning the length of the string (in bytes
- excluding the terminating null) as the value of the call. A
- negative value is returned if the passed index is not valid.
- The buffer must be large enough for the string and the terminating
- null. */
- int TListBox::GetString(LPSTR AString, int Index)
- {
- return (int)SendMessage(HWindow, GetMsgID(MN_GETTEXT),
- Index, (long)AString);
- }
-
- /* Returns the length of the string at the passed index in the
- associated listbox excluding the terminating null. A negative
- value is returned if an error occurs. */
- int TListBox::GetStringLen(int Index)
- {
- return (int)SendMessage(HWindow, GetMsgID(MN_GETTEXTLEN), Index, 0);
- }
-
- /* Returns the number of selected items in the list box. For single-
- or multiple-selection list boxes (and combo boxes). */
- int TListBox::GetSelCount()
- {
- if ( (GetWindowLong(HWindow, GWL_STYLE) & MULTIPLESEL) == 0)
- //including if it's a combobox.
- return GetSelIndex() < 0 ? 0 : 1;
- else // multiple-selection list box
- return (int)SendMessage(HWindow, LB_GETSELCOUNT, 0, 0);
- }
-
- /* For use with single-selection list boxes (and combo boxes).
- Retrieves the text of the string which is selected in the
- associated listbox. Returns the number of characters copied.
- -1 is returned if no string is selected or if this is a
- multiple-selection list box. Since the Windows function is not
- passed a size parameter, we have to allocate a string to hold
- the largest string (gotten from a query), and copy a part of it. */
- int TListBox::GetSelString(LPSTR AString, int MaxChars)
- {
- int Index, Length;
- Pchar TempString;
-
- if ( (GetWindowLong(HWindow, GWL_STYLE) & MULTIPLESEL) == 0)
- //including if it's a combobox.
- {
- Index = GetSelIndex();
- if ( Index > -1 )
- {
- Length = GetStringLen(Index);
- if ( MaxChars >= Length )
- return GetString(AString,Index);
- else
- {
- TempString = new char[Length+1];
- if ( TempString )
- {
- GetString(TempString, Index);
- _fstrncpy(AString, TempString, MaxChars);
- delete TempString;
- return MaxChars;
- }
- }
- }
- }
- return -1;
- }
-
- /* Retrieves the text of the strings which are selected in the
- associated listbox. Returns the number of items put into Strings. -1 is
- returned if this is not a multiple-selection list box. Since the Windows
- function is not passed a size parameter, we have to allocate a string
- to hold the largest string (gotten from a query), and copy a part of it.
- Only for use with multiple-selection list boxes. */
- int TListBox::GetSelStrings(LPSTR *Strings, int MaxCount, int MaxChars)
- {
- int I, TmpStringLen, *Selections;
- Pchar TmpString;
-
- if ( (GetWindowLong(HWindow, GWL_STYLE) & MULTIPLESEL) == 0)
- //including if it's a combobox.
- return -1;
-
- I = GetSelCount();
- if ( I < MaxCount )
- MaxCount = I;
-
- if ( MaxCount > 0 )
- {
- Selections = new int[MaxCount];
- SendMessage(HWindow, LB_GETSELITEMS, MaxCount, (long)(Selections));
- for (int SelIndex = 0; SelIndex < MaxCount; SelIndex++)
- {
- TmpStringLen = GetStringLen(Selections[SelIndex]);
- if ( MaxChars >= TmpStringLen )
- GetString(Strings[SelIndex], Selections[SelIndex]);
- else
- {
- TmpString = new char [TmpStringLen+1];
- if ( TmpString )
- {
- GetString(TmpString, Selections[SelIndex]);
- _fstrncpy(Strings[SelIndex], TmpString, MaxChars);
- delete TmpString;
- }
- }
- }
- delete Selections;
- }
- return MaxCount;
- }
-
- /* Selects the first string in the associated listbox following the
- passed index which begins with the passed string. Searches for a
- match beginning at the passed Index. If a match is not found after
- the last string has been compared, the search continues from the
- beginning of the list until a match is found or until the list has
- been completely traversed. Searches from beginning of list when
- -1 is passed as the index. Returns the index of the selected
- string. A negative value is returned if an error occurs. Only for
- single-selection list boxes (and combo boxes). */
- int TListBox::SetSelString(LPSTR Prefix, int SearchIndex)
- {
- if ( (GetWindowLong(HWindow, GWL_STYLE) & MULTIPLESEL) == 0 )
- //including if it's a combobox.
- return (int)SendMessage(HWindow, GetMsgID(MN_SELECTSTRING),
- SearchIndex, (long)Prefix);
- else
- return -1;
- }
-
- /* Selects the strings in the associated list box which begin with
- the passed prefixes. For each string the search begins at the
- beginning of the list and continues until a match is found or
- until the list has been completely traversed. If ShouldSet is
- TRUE, the matched strings are selected and highlighted, if
- ShouldSet is FALSE the highlight is removed from the matched
- strings and they are no longer selected. Returns the number of
- strings successfully selected or deselected. If NumSelections
- is less than zero, all strings are selected or deselected, and a
- negative value is returned on failure. Only for multiple-
- selection list boxes. (-1 is returned if this is not a
- multiple-selectionlist box). */
- int TListBox::SetSelStrings(LPSTR *Prefixes, int NumSelections,
- BOOL ShouldSet)
- {
- int SelIndex, Successes = 0;
-
- if ( (GetWindowLong(HWindow, GWL_STYLE) & MULTIPLESEL) == 0)
- //including if it's a combobox.
- return -1;
-
- if ( NumSelections > -1 )
- {
- for ( int I = 0; I < NumSelections; I++ )
- if ((SelIndex = FindString(Prefixes[I], -1)) > -1 )
- if ( (int)SendMessage(HWindow, LB_SETSEL, ShouldSet, SelIndex)
- > -1 )
- Successes++;
- }
- else
- return (int)SendMessage(HWindow, LB_SETSEL, ShouldSet, -1);
- return Successes;
- }
-
- /* Returns the index of the selected string in the associated listbox.
- A negative value is returned if no string is selected or this
- is a multiple-selection list box. Only for single-selection
- flist boxes (and combo boxes). */
- int TListBox::GetSelIndex()
- {
- if ( (GetWindowLong(HWindow, GWL_STYLE) & MULTIPLESEL) == 0)
- //including if it's a combobox.
- return (int)SendMessage(HWindow, GetMsgID(MN_GETCURSEL), 0, 0);
- else
- return -1;
- }
-
- /* Fills Indexes with the indexes of up to Count selected strings.
- Returns number of items put in the array (-1 for single-selection
- list boxes and combo boxes). */
- int TListBox::GetSelIndexes(Pint Indexes, int MaxCount)
- {
- if ( (GetWindowLong(HWindow, GWL_STYLE) & MULTIPLESEL) == 0)
- //including if it's a combobox.
- return -1;
- return (int)SendMessage(HWindow, LB_GETSELITEMS, MaxCount,
- (long)(Indexes));
- }
-
- /* Selects the string at passed index in the associated listbox and
- forces the string into view. Clears selection when -1 is passed
- as the index. A negative value is returned if an error occurs.
- Only for single-selection list boxes (and combo boxes). */
- int TListBox::SetSelIndex(int Index)
- {
- if ( (GetWindowLong(HWindow, GWL_STYLE) & MULTIPLESEL) == 0)
- //including if it's a combobox.
- return (int)SendMessage(HWindow, GetMsgID(MN_SETCURSEL), Index, 0);
- else
- return -1;
- }
-
- /* Selects/deselects the strings in the associated list box at the
- passed indexes. If ShouldSet is TRUE, the indexed strings are
- selected and highlighted, if ShouldSet is FALSE the highlight is
- removed and they are no longer selected. Returns the number of
- strings successfully selected or deselected (-1 if not a
- multiple-selection list box). If NumSelections is less than zero,
- all strings are selected or deselected, and a negative value is
- returned on failure. Only for multiple-selection list boxes. */
- int TListBox::SetSelIndexes(Pint Indexes, int NumSelections,
- BOOL ShouldSet)
- {
- int Successes = 0;
-
- if ( (GetWindowLong(HWindow, GWL_STYLE) & MULTIPLESEL) == 0)
- //including if it's a combobox.
- return -1;
-
- if ( NumSelections > -1 )
- {
- for ( int I = 0; I < NumSelections; I++ )
- if ( (int)SendMessage(HWindow, LB_SETSEL, ShouldSet, Indexes[I])
- > -1 )
- Successes++;
- }
- else
- return (int)SendMessage(HWindow, LB_SETSEL, ShouldSet, -1);
- return Successes;
- }
-
- /* Returns the appropriate MS-Windows message WORD identifier for
- the function identified by the passed MsgName string. Allows
- instances of TComboBox (which redefines GetMsgID) to inherit
- many TListBox methods. */
- WORD TListBox::GetMsgID(WORD AMsg)
- {
- WORD MsgXlat[] = { LB_ADDSTRING, LB_INSERTSTRING, LB_DELETESTRING,
- LB_RESETCONTENT, LB_GETCOUNT, LB_GETTEXT,
- LB_GETTEXTLEN, LB_SELECTSTRING, LB_SETCURSEL,
- LB_GETCURSEL, LB_FINDSTRING };
- return MsgXlat[AMsg];
- }
-
- PTStreamable TListBox::build()
- {
- return new TListBox(streamableInit);
- }
-
- TStreamableClass RegListBox("TListBox", TListBox::build, __DELTA(TListBox));
-