Не удается добавить элементы в элемент управления списком Win32

Предыстория: Я создаю расширение для Game Maker, популярного пакета для разработки игр. Расширение — это DLL, которая добавляет новые функции к встроенному языку сценариев, но написана на C, Pascal или чем-то еще. Обычно он используется, чтобы позволить играм использовать внешние библиотеки.

В моем случае я добавляю поддержку FMOD. Это не имеет значения. Важно то, что в целях отладки я также добавляю диалоговое окно, отображаемое во время выполнения, которое показывает мне внутреннее состояние моей библиотеки. Мне нужна помощь с этим окном. До сегодняшнего дня я буквально не занимался программированием необработанных форм Win32 (.NET WinForms 4eva), поэтому, вероятно, я делаю что-то действительно невежественное.

В любом случае. У меня есть список, и я хочу добавить что-то в список, но когда я пытаюсь добавить их, это не удается. Мой код:

extern DebugDialog * debugDialog;

DebugDialog::DebugDialog(HWND owner, HINSTANCE hInst) {
    this->hWnd = 0;

    HWND hWnd = CreateDialogParam(hInst,
                        MAKEINTRESOURCE(IDD_DEBUGDIALOG),
                        owner,
                        DialogProc,
                        reinterpret_cast<LPARAM>(this));

    ShowWindow(hWnd, SW_SHOW);

}

DebugDialog::~DebugDialog(void) {
    DestroyWindow(this->getHWnd());
    debugDialog = NULL;
}

BOOL CALLBACK DebugDialog::DialogProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
    DebugDialog * self;

    if(message == WM_INITDIALOG) {
        self = reinterpret_cast<DebugDialog *>(lParam);
        self->hWnd = hWnd;
        SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(self));
    } else {
        self = reinterpret_cast<DebugDialog*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
    }

    if(self) {
        return self->HandleMessage(message, wParam, lParam);
    } else {
        return FALSE;
    }
}


BOOL DebugDialog::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) {
    switch(uMsg) {
        case WM_INITDIALOG:
            MessageBox(this->getHWnd(), "Okay!", "Debug", 0);
            return TRUE;

        case WM_COMMAND:
            switch(LOWORD(wParam)) {
                case ID_CLOSE:
                case IDOK:
                case IDCANCEL:
                    delete this;
                    return TRUE;
                default:
                    return FALSE;
            }
            return TRUE;
    }

    return false;
}

void DebugDialog::loadedSound(FMODGM_Sound * sound) {
    HWND hwndList = GetDlgItem(this->getHWnd(), IDC_LIST);

    LPARAM sound_text = (LPARAM)sound->file.c_str();

    LRESULT lResult = SendMessage(hwndList, LB_ADDSTRING, NULL, sound_text);
    SendMessage(hwndList, LB_SETITEMDATA, lResult, (LPARAM)sound);

}

DebugDialog — это простой класс, который оборачивает окно и позволяет мне манипулировать им извне. В принципе, в какой-то другой момент я делаю это:

debugWindow = new DebugDialog(owner, hInst);

И затем, когда я выполняю и делаю интересные вещи, я делаю это:

FMODGM_Sound * sound = ...;

if(debugWindow) debugWindow->loadedSound(sound);

В loadedSound я отправляю сообщение в поле со списком: «Эй, вот элемент. Продолжайте и добавляйте», и он не возвращает ошибку. Тем не менее, это также ничего не добавляет к коробке. Он возвращает 0 каждый раз, когда я его вызываю. Согласно документации, 0 означает, что он добавил элемент, индекс которого равен 0. Однако этот элемент не существует.

У меня есть теория, почему это не работает. Я не контролирую поток сообщений, который запускает Game Maker, поэтому, если он делает что-то странное, я не знаю об этом и не могу его изменить. Тем не менее, все остальное в диалоговом окне работает, включая его перемещение, нажатие кнопки «Закрыть» и рисование выделения внутри списка с помощью мыши.

Кто-нибудь, подскажите, что я делаю не так :(

Редактировать: кто-то спросил о структуре FMODGM_Sound, так что вот она:

struct FMODGM_Sound {
FMOD::Sound * sound;
std::vector<FMOD::Channel*> channels;
    std::string file;

public:
    FMODGM_Sound() {
        sound = NULL;
    }
};

Ничего особенно необычного.


person Mike Caron    schedule 20.04.2011    source источник
comment
Говорит ли GetLastError() что-нибудь? Подсказка: вы можете добавить переменную @err в часы отладки, предполагая, что вы используете MSVC.   -  person Jonas Engström    schedule 20.04.2011
comment
@Jonas Gulle, я сделал это (это очень удобно: D). Ошибки не появляются, к сожалению.   -  person Mike Caron    schedule 20.04.2011
comment
Что произойдет, если вы UpdateWindow(hwndList) сразу после вызова SendMessage?   -  person Jonas Engström    schedule 21.04.2011
comment
Это не проблема с отрисовкой... Если бы это было так, я мог бы нажимать на элементы, и сообщение LB_ADDSTRING возвращало бы › 0 для последующих вызовов (чего нет). Я все равно решил отойти от этого и использую сторонний инструментарий. Спасибо, в любом случае.   -  person Mike Caron    schedule 21.04.2011


Ответы (3)


Можете ли вы показать объявление структуры FMODGM_Sound и файлового поля?

Что будет, если заменить

LRESULT lResult = SendMessage(hwndList, LB_ADDSTRING, NULL, sound_text);

с участием ?

LRESULT lResult = SendMessage(hwndList, LB_ADDSTRING, NULL, "some constant text");
person Andrew D.    schedule 20.04.2011
comment
Ничего другого не происходит. То же самое, если (по наитию) вместо этого я использую L"some constant text". - person Mike Caron; 21.04.2011
comment
Может быть, ваш список оформлен как OWNER_DRAWN? Проверьте это (из MSDN msdn.microsoft.com /en-us/library/bb775181%28v=vs.85%29.aspx): если поле со списком имеет стиль, нарисованный владельцем, но не стиль LBS_HASSTRINGS, этот параметр сохраняется как данные элемента, а не как нить. Вы можете отправлять сообщения LB_GETITEMDATA и LB_SETITEMDATA для получения или изменения данных элемента. - person Andrew D.; 21.04.2011

Ваша DLL скомпилирована как версия Unicode или версия с несколькими байтами?

Если это Unicode, sound_text должен быть строкой Unicode. Я предполагаю, что файл представляет собой std::string, поэтому file.c_str() вернет многобайтовую строку.

person Yi Zhao    schedule 20.04.2011
comment
В соответствии с этим вызовом: MessageBox(this-›getHWnd(), Okay!, Debug, 0); проект скомпилирован как MBCS (иначе должна произойти ошибка компиляции: преобразование из CHAR в WCHAR) - person Andrew D.; 20.04.2011
comment
Это верно. Он скомпилирован как Multibyte. В основном это сделано для совместимости с Game Maker, строковый формат которого char*. - person Mike Caron; 21.04.2011
comment
Это правильный HWND от GetDlgItem(this->getHWnd(), IDC_LIST);? Я думаю, что вы должны проверить это в первую очередь. - person Yi Zhao; 21.04.2011

У меня была очень похожая проблема, которая была решена. По сути, вы должны передать его как строку в стиле c вместо (str.c_str()). Хотя я полный новичок, после того, как я погуглил, как это использовать, это сработало.

Хотя код, который я использую, выполняет совершенно другую функцию, чем ваша, возможно, это будет хороший пример.

int i = res->getInt("ID");
    std::string str = boost::lexical_cast<std::string>(i);
    char *cstr = new char[10];
    strcpy_s(cstr, 10, str.c_str());
    SendDlgItemMessage(hwnd, IDC_lbList, LB_ADDSTRING, 0, (LPARAM)cstr);

РЕДАКТИРОВАТЬ: Вау, я даже не посмотрел на даты. Я некромант...

person Laurgrin    schedule 03.06.2014