(WinAPI)在ComboBox中模拟项目选择

时间:2014-04-17 14:42:33

标签: c++ windows winapi user-interface combobox

我目前正在为具有自己的GUI的现有应用程序编写包装器。我不能访问原始应用程序的源代码(不幸的是)。我写的程序是用C ++编写的,我正在使用WinAPI。我通过模拟按钮时钟,勾选复选框等操作目标应用程序。

我目前面临的问题如下:

我需要在实施为WinAPI ComboBox的droplist中进行选择。我是通过使用宏ComboBox_SetCurSel来完成的。下拉列表中的选择会正确更改。但是在原始应用程序中有一个只读文本框,它根据组合框中的选择更改值。当我执行ComboBox_SetCurSel时,这个不会改变。

我做的假设是在手动选择ComboBox中的条目时发送CBN_SELENDOK和/或CBN_SELCHANGE,这是我在使用ComboBox_SetCurSel宏设置选择时没有做的。

然而,由于缺乏经验,我无法弄清楚如何解决问题。谁通常在听CBN_SELENDOK和CBN_SELCHANGE。它是主应用程序窗口,组合框的父元素还是主应用程序线程?我如何找到答案。

是否有可以完成整个事情的宏?比如在ComboBox中更改所选项目并发送所有必要的通知?有一些聪明的解决方法吗?

欢迎任何有关此主题的帮助,或任何有助于使情况更加清晰的其他问题。

更新:感谢Jonathan Potter的评论。我现在正试图明确发送消息。以下是我正在执行的代码部分:

int res = ComboBox_SetCurSel(this->handle, index);
if (res == CB_ERR)
{
    return false;
}
PostMessage(GetParent(this->handle),WM_COMMAND, MAKEWPARAM(0,CBN_SELENDOK),0);
PostMessage(GetParent(this->handle),WM_COMMAND, MAKEWPARAM(0,CBN_SELCHANGE),0);

注意this->handle只是ComboBox本身的句柄,因为为方便起见,我已将其打包到结构中。 GetParent(this->handle)应该获得ComboBox的直接父母

仍然没有结果。消息的顺序是否重要?另外我如何获得需要进入与WM_COMMAND一起发送的WPARAM的LOWORD的标识符?

解答:

感谢 AlwaysLearningNewStuff ,我找到了答案。我一直在发送带有0作为LPARAM的消息。显然,ComboBox本身的句柄需要作为LPARAM发送才能使解决方案正常工作。这需要我很长时间才能弄明白。 @AlwaysLearningNewStuff ,您应该将此作为答案发布,而不是评论。

使用GetDlgCtrlID()来获取ComboBox的ControlID也非常有用。这使代码更可靠。

谢谢大家的参与。

这是我的最终代码:

if (this->handle == NULL)
{
    return false;
}
int res = ComboBox_SetCurSel(this->handle, index);
if (res == CB_ERR)
{
    return false;
}
PostMessage(GetParent(this->handle), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID( this->handle ),CBN_SELENDOK),
        (LPARAM)(this->handle));
PostMessage(GetParent(this->handle), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID( this->handle ),CBN_SELCHANGE),
        (LPARAM)(this->handle));
return true;

1 个答案:

答案 0 :(得分:4)

您使用CBN_SELCHANGE时未发送ComboBox_SetCurSel()是正确的,documentation表示同意:

  

使用CB_SETCURSEL消息设置当前选择时,CBN_SELCHANGE通知代码

因此您必须手动发送通知。但是,您缺少消息中的关键元素 - ComboBox的控件ID HWND 。父窗口使用这些窗口来识别哪个子控件正在向它发送消息,以便它可以相应地执行操作。

请改为尝试:

int res = ComboBox_SetCurSel(this->handle, index);
if (res == CB_ERR)
{
    return false;
}
HWND hParent = GetParent(this->handle);
int iCtrlId = GetDlgCtrlID(this->handle);
if (GetWindowLong(this->handle, GWL_STYLE) & CBS_SIMPLE)
    PostMessage(hParent, WM_COMMAND, MAKEWPARAM(iCtrlId,CBN_SELENDOK), LPARAM(this->handle));
PostMessage(hParent, WM_COMMAND, MAKEWPARAM(iCtrlId,CBN_SELCHANGE), LPARAM(this->handle));