【问题标题】:Cannot add items to Win32 List Box Control无法将项目添加到 Win32 列表框控件
【发布时间】:2011-04-20 07:45:28
【问题描述】:

背景故事:我正在为流行的游戏开发套件 Game Maker 创建一个扩展。扩展是向内置脚本语言添加新功能的 DLL,但它是用 C 或 Pascal 或其他语言编写的。通常,它用于允许游戏使用外部库。

就我而言,我正在添加 FMOD 支持。这无关紧要。相关的是,出于调试目的,我还添加了一个在运行时显示的对话框,该对话框显示了我的库的内部状态。我需要有关此窗口的帮助。在今天(.NET WinForms 4eva)之前,我确实完全没有做过原始的 Win32 表单编程,所以我可能在做一些非常无能为力的事情。

无论如何。我有一个列表框,我想在列表框中添加一些东西,但是当我尝试添加它们时,它失败了。我的代码:

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;
    }
};

没什么特别的。

【问题讨论】:

  • GetLastError() 是否说明了什么?提示:假设您使用的是 MSVC,您可以在 Debug 监视中添加“@err”变量。
  • @Jonas Gulle,我已经做到了(非常方便:D)。不幸的是,没有出现任何错误。
  • 如果您在 SendMessage 调用后立即UpdateWindow(hwndList) 会发生什么?
  • 这不是油漆问题...如果是,我可以点击这些项目,LB_ADDSTRING 消息将返回 > 0 用于后续调用(它不会)。无论如何,我决定放弃这个,并且正在使用第三方工具包。还是谢谢。

标签: c++ winapi listbox dialog game-maker


【解决方案1】:

你能显示 FMODGM_Sound 结构和文件字段的声明吗?

如果替换会发生什么

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

用 ?

LRESULT lResult = SendMessage(hwndList, LB_ADDSTRING, NULL, "some constant text");

【讨论】:

  • 没有什么不同。如果(凭直觉)相同,我改用L"some constant text"
  • 可能是您的列表框设计为“OWNER_DRAWN”?检查这一点(来自 MSDN msdn.microsoft.com/en-us/library/bb775181%28v=vs.85%29.aspx):如果列表框具有自绘样式但不是 LBS_HASSTRINGS 样式,则此参数存储为项目数据而不是字符串。您可以发送 LB_GETITEMDATA 和 LB_SETITEMDATA 消息来检索或修改项目数据。
【解决方案2】:

您的 DLL 是编译为 Unicode 版本还是多字节版本?

如果是 Unicode,则 sound_text 应该是 Unicode 字符串。我猜该文件是一个 std::string,所以 file.c_str() 将返回一个多字节字符串。

【讨论】:

  • 按照这个调用:MessageBox(this->getHWnd(), "Okay!", "Debug", 0);项目编译为MBCS(否则一定会出现编译错误:从CHAR转换为WCHAR)
  • 这是正确的。它被编译为多字节。这主要是为了兼容Game Maker,其字符串格式为char*
  • GetDlgItem(this-&gt;getHWnd(), IDC_LIST); 的 HWND 是否正确?我认为你应该先验证一下。
【解决方案3】:

我有一个非常相似的问题,已经解决了。基本上,您必须将其作为 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);

编辑:哇,我什至没有看日期。我是死灵法师……

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多