0

私は 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 プロシージャに到達していません。

4

1 に答える 1

0

ジェイのコメントのおかげで、私はプロシージャが呼び出されたときに何が抑制されるのかを深く掘り下げ始めました。

擬似コードを単純化するために、SendMessageプロシージャへの2つの連続した呼び出しがあるという事実を含めませんでした。1つはパラメータを設定するためのもので、もう1つは応答でデータを要求するためのものです。出力コンポーネントと入力コンポーネントは別々であるため、相互作用があるとは思いませんでした。

しかし、送信コンポーネントがそれ自体と相互作用できることに気づいていませんでした。SendMessageコードを見ると、送信が完了するとメッセージが送信され、別のメッセージを受け入れることができるようになります。送信手順が再度有効にされなかったため、2番目のメッセージ(応答の要求)は送信されませんでした。

SendMessageプロシージャへの2つの呼び出しの間にapplication.processmessages呼び出しを配置すると、この問題が修正されたようです。

于 2012-10-12T22:38:47.523 に答える