我有一个 Delphi 应用程序 A,我需要从 .NET 应用程序 B 控制它。
除其他外,我需要自动化这个过程:
- 用户从组合框中选择项目 X。
- 应用程序 A 注意到更改并通过显示某个面板做出反应。
如果我手动操作,这可以正常工作。
但是当应用程序 B 选择一个组合框值时,不会显示任何面板。
这就是问题。
它的潜在原因:
- 当我选择一个组合框项目时,会触发某个 Windows 消息。一些 Delphi 例程对此消息作出反应。
- 当我以编程方式选择组合框项时,我发送的唯一消息是
CB_SETCURSEL
Delphi 应用程序似乎忽略了它。
因此,我假设我可以解决问题,如果我
- 了解使用哪些 Windows 消息作为组合框值更改通知的基础(例如
OnChange
)和 - 从 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);
目前,它不起作用。
更新 2:
我注意到一件非常奇怪的事情。
- 如果我只调用
CB_SETCURSEL
,则在组合框中选择所需的项目。 - 如果我调用
CB_SETCURSEL
and then (after 5 seconds)CN_COMMAND
,则组合框中没有选择任何内容。
这意味着 -CB_SECURSEL
选择项目并CN_COMMAND
撤消它。
更新 3:根据 Spy++ 的组合框样式:
- WS_CHILDWINDOW
- WS_VISIBLE
- WS_CLIPSIBLINGS
- 00000243
扩展样式:
- WS_EX_LEFT
- WS_EX_LTRREADING
- WS_EX_RIGHTSCROLLBAR
课堂风格:
- CS_VREDRAW
- CS_HREDRAW
- 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
不幸的是,我找不到此消息的文档。
更新 5:我注意到对组合框选择更改的反应确实发生了,但只有在相对较长的时间(30 秒到 1 分钟)之后才会发生。当我手动做同样的事情时,反应会立即发生。
此行为的潜在原因:.NET 应用程序的线程使 Delphi 应用程序的线程等待它。请注意,.NET 应用程序中的 UI 交互代码在单独的线程(不是 UI 线程)中执行。