1
votes

I want to add the text in a listbox control to the child of my main window. The child is essentially an edit control, but is not a dialog. I have tried a few different functions already with no success, I believe my problem is that I need to somehow switch focus from the dialog window to the child window before adding the text. I would prefer not to get an answer with specific code, but if I could be pointed to a helpful function or concept, that would be great!

EDIT: The listbox is part of a larger dialog window that allows the user to enter text and then add it to the list. These functions are working very well. What I'd like to do is get the text that is added to the list moved into the child window when the user clicks a button on the dialog, preferably without the user having to select the items before clicking the button.

There's a lot of code, but I think these pieces are relevant:

Child window:

case WM_CREATE:
        {
        hEdit = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "", 
            WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL | ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL,
            0, 0, 100, 100, w, (HMENU) IDC_EDIT, NULL, NULL);

        if (hEdit == NULL){
            MessageBox(NULL, "Could not create child window :(", "ERROR", MB_ICONEXCLAMATION | MB_OK);
            return 0;
        }
    }
        break;

    case WM_SIZE:
        {
            RECT wSize;

            GetClientRect(w, &wSize);
            SetWindowPos(hEdit, NULL, 0, 0, wSize.right, wSize.bottom, NULL);
        }

Function to add text to child window by clicking a button on the dialog (HWND hEdit, the child window, is defined globally):

case ID_ADDMAIN:
            {
            HWND hList = GetDlgItem(w, IDC_LIST1);
            int count = SendMessage(hList, LB_GETCOUNT, NULL, NULL);

            if (count > 0){

                DWORD textLength = GetWindowTextLength(hList);

                LPSTR alloc;

                alloc = (LPSTR) GlobalAlloc(GPTR, textLength + 1);
                if(GetWindowText(hList, alloc, textLength + 1)){

                    SendMessage(hEdit, WM_SETTEXT, NULL, (LPARAM) alloc);
                }

                GlobalFree(alloc);
            }
            else{
                MessageBox(NULL, "There's nothing to add!", "???", MB_ICONINFORMATION | MB_OK);
            }
        }
            break;

Besides the SendMessage function, I also tried SetWindowText and I tried getting each string in the listbox separately using a for loop rather than GetWindowText. Thank you in advance for your help.

2
Where is hEdit declared?Jonathan Potter
It's a global variable, so it's outside of all of my functions.user2924162

2 Answers

1
votes

You misunderstand the list box. The LB_GETCOUNT message is used to get the number of items (rows) in the list box. (Not the number of characters.)

GetWindowText is not appropriate for a list box: It gets the titlebar text, but a list box has no titlebar. What you can do with a list box is find out which row is selected (LB_GETCURSEL) and then get the text from that row (LB_GETTEXT).

1
votes

Here is a list of functions I wrote for my WINAPI class library..

    int ListBox::GetItemCount() const
    {
        return SendMessage(Control::GetHandle(), LB_GETCOUNT, 0, 0);
    }

    int ListBox::GetSelectedIndex() const
    {
        return SendMessage(Control::GetHandle(), LB_GETCURSEL, 0, 0);
    }

    void ListBox::SetSelectedIndex(int Index)
    {
        SendMessage(Control::GetHandle(), LB_SETCURSEL, Index, 0);
    }

    void ListBox::AddItem(const tstring &Item, int Index)
    {
        SendMessage(Control::GetHandle(), Index == 0 ? LB_ADDSTRING : LB_INSERTSTRING, Index, reinterpret_cast<LPARAM>(Item.c_str()));
    }

    void ListBox::RemoveItem(int Index)
    {
        SendMessage(Control::GetHandle(), LB_DELETESTRING, Index, 0);
    }

    void ListBox::Clear()
    {
        SendMessage(Control::GetHandle(), LB_RESETCONTENT, 0, 0);
    }

    int ListBox::GetIndexOf(const tstring &Item)
    {
        return SendMessage(Control::GetHandle(), LB_FINDSTRINGEXACT, -1, reinterpret_cast<LPARAM>(Item.c_str()));
    }

    int ListBox::GetIndexPartial(const tstring &Item)
    {
        return SendMessage(Control::GetHandle(), LB_FINDSTRING, -1, reinterpret_cast<LPARAM>(Item.c_str()));
    }

    void ListBox::SetColumnWidth(int Width)
    {
        SendMessage(Control::GetHandle(), LB_SETCOLUMNWIDTH, Width, 0);
    }

    tstring ListBox::GetItem(int Index) const
    {
        std::vector<char> Buffer(SendMessage(Control::GetHandle(), LB_GETTEXTLEN, Index, 0) + 1);
        SendMessage(Control::GetHandle(), LB_GETTEXT, Index, reinterpret_cast<LPARAM>(Buffer.data()));
        return tstring(Buffer.begin(), Buffer.end());
    }

You'll need:

ListBox::GetItem(ListBox::GetSelectedIndex());

to get the text of the current item in the list box..

For the Edit control, I have:

void TextBox::SetReadOnly(bool ReadOnly)
{
    SendMessage(Control::GetHandle(), EM_SETREADONLY, ReadOnly, 0);
}

void TextBox::SetPassword(bool Enabled, char PasswordChar)
{
    SendMessage(Control::GetHandle(), EM_SETPASSWORDCHAR, Enabled ? PasswordChar : 0, 0);
}

std::uint32_t TextBox::GetTextLength() const
{
    return GetWindowTextLength(Control::GetHandle());
}

void TextBox::ShowScrollBar(bool Show, int wBar)
{
    ::ShowScrollBar(Control::GetHandle(), wBar, true);
}

void TextBox::AppendText(const tstring &Text) const
{
    SendMessage(Control::GetHandle(), EM_SETSEL, -1, -1);
    SendMessage(Control::GetHandle(), EM_REPLACESEL, 0, reinterpret_cast<LPARAM>(Text.c_str()));
}

tstring TextBox::GetText() const
{
    std::vector<TCHAR> Buffer(GetWindowTextLength(Control::GetHandle()) + 1);
    GetWindowText(Control::GetHandle(), Buffer.data(), Buffer.size());
    return tstring(Buffer.begin(), Buffer.end());
}

void TextBox::SetText(const tstring &Text)
{
    this->Title = Text;
    SetWindowText(Handle, Text.c_str());
}

You can get the text from the edit box easily with these.. I hope these aid you greatly..