0

我不是 Delphi 专家,我对消息流以及事件和回调的处理只有一个基本的了解。我正在尝试在 D7 中调试一个应用程序,该应用程序需要将前台过程(由单击按钮启动)与在后台发生的消息接收和处理(由组件处理)结合起来。它们都独立地正常工作,但是当我将它们组合在一个程序中时,消息接收不起作用。

现有的应用程序已经具有在单击按钮时发送消息的功能程序,并且它可以在运行而不处理任何按钮时接收消息。

正常的消息接收由一个组件处理,该组件将我的处理程序 (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 输入端口打开时,回调被设置为指向一个处理程序:procedure midiHandler

在 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;

在 Object Inspector 中,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

感谢 Jay 的评论,我开始更深入地研究调用过程时被禁止的内容。

为了简化我的伪代码,我没有包括对 SendMessage 过程有两次连续调用的事实——一次用于设置参数,一次用于在回复中请求数据。我认为输出和输入组件之间没有交互,因为它们是分开的。

但我没有意识到发送组件可以与自身交互。查看 SendMessage 代码,我发现它在完成发送后会向自己发送一条消息,这会重新使其能够接受另一条消息。第二条消息(响应请求)没有被发送,因为发送过程没有重新启用。

在对 SendMessage 过程的两次调用之间放置一个 application.processmessages 调用似乎已经解决了这个问题。

于 2012-10-12T22:38:47.523 回答