3

.NET アプリケーション B から制御する必要がある Delphi アプリケーション A があります。

とりわけ、このプロセスを自動化する必要があります。

  1. ユーザーがコンボ ボックスから項目 X を選択します。
  2. アプリケーション A は変化に気づき、特定のパネルを表示して反応します。

手動で行うと、これはうまく機能します。

しかし、アプリケーション B がコンボ ボックスの値を選択すると、パネルは表示されません。

これが問題です。

考えられる原因:

  1. コンボ ボックスの項目を選択すると、特定の Windows メッセージが表示されます。一部の Delphi ルーチンは、このメッセージに反応します。
  2. プログラムでコンボ ボックス項目を選択すると、送信される唯一のメッセージCB_SETCURSELが Delphi アプリで無視されるようです。

したがって、問題を解決できると思います。

  1. OnChangeコンボ ボックスの値の変更に関する通知の基礎として使用される Windows メッセージ (例: )を理解する
  2. その Windows メッセージを C# アプリケーションから送信します。

したがって、私の質問: 発生時にOnChange(およびコンボ ボックスの選択が変更されたときに Delphi アプリケーションに通知するその他のイベントが) 発生する Windows メッセージは何ですか?

更新 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:

私は非常に奇妙なことに気付きました。

  1. 呼び出すCB_SETCURSELだけの場合、目的の項目がコンボ ボックスで選択されます。
  2. 呼び出しCB_SETCURSELてから (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

残念ながら、このメッセージのドキュメントは見つかりませんでした。

更新 5 : コンボ ボックスの選択の変更に対する反応が発生することに気付きましたが、比較的長い時間 (30 秒から 1 分) が経過した後でのみ発生します。同じことを手動で行うと、瞬時に反応が起こります。

この動作の潜在的な原因: .NET アプリケーションのスレッドが Delphi アプリケーションのスレッドを待機させます。.NET アプリの UI 対話コードは、(UI スレッドではなく) 別のスレッドで実行されることに注意してください。

4

2 に答える 2

4

CB_SETCURSELコンボ ボックスにと等しいWM_COMMANDメッセージを送信して、メッセージを追跡する必要があります。イベントをトリガーするのは です。NotifyCodeCBN_SELCHANGECBN_SELCHANGEOnChange

Delphi では、コードは次のようになります。

SendMessage(ComboHandle, CB_SETCURSEL, NewSelectionIndex, 0);
SendMessage(ComboHandle, WM_COMMAND, MakeWParam(0, CBN_SELCHANGE), ComboHandle);

または、代わりにメッセージを使用することもできます。CN_COMMANDこれは、おそらくもう少し直接的です。

SendMessage(ComboHandle, CB_SETCURSEL, NewSelectionIndex, 0);
SendMessage(ComboHandle, CN_COMMAND, MakeWParam(0, CBN_SELCHANGE), 0);

使用している .net 言語に翻訳する必要がありますが、それは簡単なことだと思います。

于 2012-10-08T13:32:14.170 に答える
4

ユーザーが手動で ComboBox 項目を選択すると、コントロールはCBN_SELCHANGE通知を受け取り、イベントをトリガーしTComboBox.OnChangeます。ComboBox 項目をプログラムで選択すると、CBN_SELCHANGE通知は送信されません。これは文書化された動作です:

http://msdn.microsoft.com/en-us/library/windows/desktop/bb775821.aspx

現在の選択が CB_SETCURSEL メッセージを使用して設定されている場合、CBN_SELCHANGE 通知コードは送信されません。

于 2012-10-08T19:05:40.360 に答える