Delphi 使用哪些 Windows 消息来通知组合框中的更改?

DP_*_*DP_ 3 delphi winapi delphi-2009

我有一个 Delphi 应用程序 A,我需要从 .NET 应用程序 B 控制它。

除此之外,我需要自动化这个过程:

  1. 用户从组合框中选择项目 X。
  2. 应用程序 A 注意到该变化并通过显示特定面板做出反应。

如果我手动执行此操作,效果很好。

但是,当应用程序 B 选择组合框值时,不会显示任何面板。

这就是问题。

其潜在原因:

  1. 当我选择组合框项目时,会触发特定的窗口消息。某些 Delphi 例程对此消息做出反应。
  2. 当我以编程方式选择组合框项时,我发送的唯一消息是CB_SETCURSELDelphi 应用程序似乎忽略它。

因此我认为我可以解决这个问题,如果我

  1. 了解哪些 Windows 消息用作有关组合框值更改的通知的基础(例如OnChange)和
  2. 从 C# 应用程序发送该 Windows 消息。

因此我的问题是:什么是Windows消息,它们的发生OnChange(以及通知Delphi应用程序更改组合框选择的其他事件)被触发?

更新1:开始实施David Heffernan提出的解决方案

private const int CB_SETCURSEL = 0x14E;
private const int WM_COMMAND = 0x0111;
private const int CBN_SELCHANGE = 0x001;
private const int CN_COMMAND = 0xBD11;

private int MakeWParam(int l, int h)
{
    return (l & 0xFFFF) | (h << 16);
}

...
IntPtr comboBoxHandle = new IntPtr(comboBox.Current.NativeWindowHandle);
SendMessage(comboBoxHandle, CB_SETCURSEL, (Int32)myIndexInComboBox, 0);
SendMessage(comboBoxHandle, CN_COMMAND, MakeWParam(0, CBN_SELCHANGE), 0);
Run Code Online (Sandbox Code Playgroud)

目前,它不起作用。

更新2:

我注意到一件非常奇怪的事情。

  1. 如果我CB_SETCURSEL仅调用,则在组合框中选择所需的项目。
  2. 如果我调用CB_SETCURSELand then (5 秒后)CN_COMMAND,则组合框中不会选择任何内容。

这意味着 -CB_SECURSEL选择该项目并CN_COMMAND撤消它。

更新 3:根据 Spy++ 的组合框样式:

  1. WS_CHILDWINDOW
  2. WS_VISIBLE
  3. WS_CLIPSIBLINGS
  4. 00000243

扩展样式:

  1. WS_EX_LEFT
  2. WS_EX_LTRREADING
  3. WS_EX_RIGHTSCROLLBAR

班级风格:

  1. CS_VREDRAW
  2. CS_HREDRAW
  3. CS_DBLCLKS

更新 4:当我手动选择组合框项目时,我在 Spy++ 输出中看到以下消息:

<00177> 0195085E S message:0xBD33 [Custom:WM_APP+15667] wParam:6801164A lParam:0195085E
<00178> 0195085E R message:0xBD33 [Custom:WM_APP+15667] lResult:4610165A
Run Code Online (Sandbox Code Playgroud)

不幸的是,我找不到此消息的文档。

更新 5:我注意到对组合框选择更改的反应确实发生,但只是在相对较长的时间(30 秒到 1 分钟)之后。当我手动做同样的事情时,反应会立即发生。

此行为的潜在原因:.NET 应用程序的线程使 Delphi 应用程序的线程等待它。请注意,.NET 应用程序中的 UI 交互代码是在单独的线程(而不是 UI 线程)中执行的。

Dav*_*nan 5

您应该按照该CB_SETCURSEL消息向组合框发送一条等于 的WM_COMMAND消息。这是触发事件的。NotifyCodeCBN_SELCHANGECBN_SELCHANGEOnChange

在 Delphi 中,代码如下所示:

SendMessage(ComboHandle, CB_SETCURSEL, NewSelectionIndex, 0);
SendMessage(ComboHandle, WM_COMMAND, MakeWParam(0, CBN_SELCHANGE), ComboHandle);
Run Code Online (Sandbox Code Playgroud)

或者您可以使用该CN_COMMAND消息,这可能会更直接一些:

SendMessage(ComboHandle, CB_SETCURSEL, NewSelectionIndex, 0);
SendMessage(ComboHandle, CN_COMMAND, MakeWParam(0, CBN_SELCHANGE), 0);
Run Code Online (Sandbox Code Playgroud)

您需要将其翻译成您正在使用的任何 .net 语言,但我相信这对您来说很容易。