我不是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.prrocessmessages调用?当应用程序处于运行和空闲状态时,输入消息可以正常工作,但在执行过程时则不能正常工作。除了调用application.prrocessmessages之外,还需要什么才能使应用程序处理消息并调用相关过程来处理这些消息?
要跟踪传入消息,路径从Windows MMSystem的回调开始。当MIDI输入端口打开时,回调被设置为指向一个处理程序:procedure midiHandler
在midiHandler中,事件被放入一个循环缓冲区:CircbuffPutEvent(thisBuffer,@thisEvent)。
然后将一条消息发布回应用程序:PostMessage(thisCtlInfo^.hWindow,mim_Data,0,0)
该消息由:procedureTMidiInput.MidiInput(varMessage:TMessage)处理;在该过程中,有一个调用:FOnMIDInput(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过程。
多亏了周的评论,我开始深入研究调用过程时会被禁止的内容。
为了简化我的伪代码,我没有包含对SendMessage过程有两个顺序调用的事实——一个用于设置参数,另一个用于在回复中请求数据。我认为输出和输入组件之间没有交互,因为它们是分开的。
但我没有意识到发送组件可以与自己交互。通过查看SendMessage代码,我发现它在发送完成后会向自己发送一条消息,这使它能够接受另一条消息。第二条消息(请求响应)没有被发送,因为没有重新启用发送过程。
在对SendMessage过程的两个调用之间放入application.prrocessmessages调用似乎已经解决了这个问题。