Random_NPC
Random_NPC

Reputation: 61

Win32 C++: Display contents of a listbox

I am trying to display the contents of a listbox using the SendMessage function. However when I press the button to execute the piece of code below, I get the following segfault in my code when I call

SendMessage(hwndLBox,LB_GETTEXT,k,(LPARAM)lBoxitems);

Segfault (dbgheap.c):

extern "C" _CRTIMP int __cdecl _CrtIsValidHeapPointer(
        const void * pUserData
        )
 {
        if (!pUserData)
            return FALSE;

        if (!_CrtIsValidPointer(pHdr(pUserData), sizeof(_CrtMemBlockHeader), FALSE))
            return FALSE;

        return HeapValidate( _crtheap, 0, pHdr(pUserData) );
}

The Code that causes this segfault:

            else if(LOWORD(wParam)==ID_BUTTON_CALC){

                int getLboxitems = SendMessage(hwndLBox,LB_GETCOUNT,NULL,NULL);

                char * lBoxitems = new char[getLboxitems];

                for(unsigned int k=0; k < getLboxitems; k++){
                        SendMessage(hwndLBox,LB_GETTEXT,k,(LPARAM)lBoxitems);
                        MessageBox(hwnd,lBoxitems,"Listbox says",NULL);
                }

                delete[] lBoxitems;
            }

I am using Visual Studio Beta 2011 to compile my code.

Upvotes: 0

Views: 2447

Answers (2)

Jesse Good
Jesse Good

Reputation: 52365

You need to allocate space for your strings. char * lBoxitems = new char[getLboxitems]; allocates a char array that is the size of how many items you have in the list. The following should work I think:

else if(LOWORD(wParam)==ID_BUTTON_CALC)
{
    int getLboxitems = SendMessage(hwndLBox, LB_GETCOUNT, NULL, NULL);

    char ** lBoxitems = new char*[getLboxitems];

    for(unsigned int k = 0; k < getLboxitems; k++)
    {
        int textlength = SendMessage(control, LB_GETTEXTLEN, (WPARAM)k, NULL);
        lBoxitems[k] = new char[textlength + 1]; // +1 for null terminator
        SendMessage(hwndLBox, LB_GETTEXT, (WPARAM)k, (LPARAM)lBoxitems[k]);
        MessageBox(hwnd, lBoxitems[k], "Listbox says" , NULL);
    }
    for (unsigned int k = 0; k < getLboxitems; k++)
    {
        delete [] lBoxitems[k];
    }
    delete[] lBoxitems;
}

However, using std::vector<std::vector<char>> or std::vector<std::string> would be easier:

else if(LOWORD(wParam)==ID_BUTTON_CALC)
{
    int getLboxitems = SendMessage(hwndLBox, LB_GETCOUNT, NULL, NULL);

    std::vector<std::string> v(getLboxitems);

    for(unsigned int k = 0; k < getLboxitems; k++)
    {
        int textlength = SendMessage(control, LB_GETTEXTLEN, (WPARAM)k, NULL);
        v[k].resize(textlength + 1);
        std::string& buff = v[k];
        SendMessage(hwndLBox, LB_GETTEXT, (WPARAM)k, (LPARAM)&buff[0]);
        MessageBox(hwnd, v[k].c_str(), "Listbox says" , NULL);
    }
}

Upvotes: 1

ApplePie
ApplePie

Reputation: 8942

Two things I see

  1. Have you verified that getLboxitems is a valid value (i.e. neither <= 0) or absurdly large ?

  2. I don't think you are using arrays properly in this case. You create a dynamic-sized array the size of getLboxitems meaning that if you have 5 items in your list box, you will effectively create an array of five char (and not char* or char[] as you assume you are doing). You would need to create your array this way:

    // verify with MSDN that 255 is large enough
    char* lBoxitems[255] = new char[getLboxitems][255];
    for(unsigned int k=0; k < getLboxitems; k++) {
        SendMessage(hwndLBox, LB_GETTEXT, k, (LPARAM)(lBoxitems[k]));
        MessageBox(hwnd, lBoxitems[k], "Listbox says", NULL);
    }
    

Beware, untested code.

Edit: Thanks to Jesse Good for correction.

Also I would like to point out that this method is not very C++-y. You may want to use std::vector<std::string> instead of 2D arrays and only use a temporary array to be used in SendMessage().

Upvotes: 0

Related Questions