私は Delphi の専門家ではありません。メッセージの流れと、イベントとコールバックの処理についての基本的な知識しかありません。フォアグラウンド プロシージャ (ボタン クリックで開始) とバックグラウンドで発生するメッセージ受信および処理 (コンポーネントによって処理) を組み合わせる必要がある D7 でアプリケーションをデバッグしようとしています。どちらも独立しては正常に動作しますが、1 つの手順で組み合わせると、メッセージの受信が機能しません。
既存のアプリケーションには、ボタンのクリック時にメッセージを送信する機能するプロシージャが既にあり、ボタンを処理していなくても実行中にメッセージを受信できます。
通常のメッセージ受信は、私のハンドラー (OnInput) をイベントとして呼び出すコンポーネントによって処理されます。私のハンドラーはメッセージを ListBox に入れます。
ループでメッセージを送信し、応答を待つプロシージャを作成しようとしています。(疑似コード):
for N := 0 to nsequence do begin
prevcount := ListBox1.items.count;
SendMessage(mymessage); // request the response
sleep(500); // allow time for response to arrive
for 0 to timeout do begin
sleep(100);
application.processmessages; {allow processing to handle incoming message}
if ListBox1.items.count > prevcount then break; {has the message arrived?}
end;
if ListBox1.items.count = prevcount then exit: {timeout -- fail}
end;
これはスレッドなしで達成できるはずだと思いますが、メッセージは決して受信されません。いつもタイムアウトします。
コンポーネント イベント ハンドラーは application.processmessages から呼び出すことができますか? 入力メッセージは、アプリケーションが実行中およびアイドル状態のときは正しく機能しますが、プロシージャーの実行中は機能しません。application.processmessages の呼び出し以外に、アプリケーションでメッセージを処理し、関連するプロシージャを呼び出してそれらを処理するために必要なものは何ですか?
着信メッセージを追跡するために、パスは Windows MMSystem からのコールバックで始まります。MIDI 入力ポートが開かれると、コールバックはハンドラーを指すように設定されます。
midiHandler では、イベントは循環バッファーに入れられます: CircbufPutEvent( thisBuffer, @thisEvent)。
次に、メッセージがアプリケーションに戻されます: PostMessage(thisCtlInfo^.hWindow, mim_Data, 0, 0)
このメッセージは次のように処理されます。 procedure TMidiInput.MidiInput( var Message: TMessage ); そのプロシージャ内で次の呼び出しがあります。 FOnMIDIInput(Self);
これらのイベントは、コンポーネントのインターフェースで次のように定義されています。
{ Events }
FOnMIDIInput: TNotifyEvent; { MIDI Input arrived }
[公開済み] の下には、次のものがあります。
{ Events }
property OnMidiInput: TNotifyEvent read FOnMidiInput write FOnMidiInput;
property OnOverflow: TNotifyEvent read FOnOverflow write FOnOverflow;
オブジェクト インスペクタでは、OnMidiInput イベントはプロシージャ MIDIInput1MidiInput にリンクされています。
プロシージャ MIDIInput1MidiInput は、最初に GetMidiEvent を呼び出します。
with (Sender As TMidiInput) do
begin
while (MessageCount > 0) do
begin
{ Get the event as an object }
thisEvent := GetMidiEvent;
GetMidiEvent は循環バッファからメッセージを読み取ります。MIDIInput1MidiInput プロシージャは、いくつかのチェックと検証を行い、最終的にメッセージを ListBox1 に格納します。
PS - 入力コンポーネントには、循環バッファー内のキューに入れられたメッセージの数を返すプロパティがあります。待機ループがタイムアウトしたときにチェックすると、0 メッセージが報告されます。したがって、コールバックは明らかに midiHandler プロシージャに到達していません。