Delphi 在处理事件时忽略所有新传入的鼠标滚轮消息

Delphi 在处理事件时忽略所有新传入的鼠标滚轮消息,delphi,custom-controls,mouse,vcl,mousewheel,Delphi,Custom Controls,Mouse,Vcl,Mousewheel,我正在使用从TCustomControl派生的一些自定义组合框控件,并且正在处理鼠标事件。我们叫它TMYCOMBOX吧 我正在处理TMyComboBox.OnChange并执行一些需要一些时间才能完成的操作(大约200毫秒)(执行一些外部硬件更改) 因为我还实现了鼠标滚轮,所以我可以用鼠标滚轮更改自定义组合框中的项目 问题来了。鼠标滚轮事件发生得非常快(滚动时),这会引发我的TMyComboBox的OnChange事件 因为一次更改要花很多时间才能完成,所以我无法处理所有的消息,所以我的组合框仍

我正在使用从TCustomControl派生的一些自定义组合框控件,并且正在处理鼠标事件。我们叫它TMYCOMBOX吧

我正在处理TMyComboBox.OnChange并执行一些需要一些时间才能完成的操作(大约200毫秒)(执行一些外部硬件更改)

因为我还实现了鼠标滚轮,所以我可以用鼠标滚轮更改自定义组合框中的项目

问题来了。鼠标滚轮事件发生得非常快(滚动时),这会引发我的TMyComboBox的OnChange事件

因为一次更改要花很多时间才能完成,所以我无法处理所有的消息,所以我的组合框仍然在更改,即使我已经不再更改鼠标滚轮。我猜消息队列正在清空并发送所有鼠标滚轮事件

那个么,若OnChange仍在做一些工作,那个么如何防止在消息队列中接收鼠标滚轮消息呢

伪码

function TMyComboBox.DoMouseWheelDown(Shift: TShiftState;
  MousePos: TPoint): Boolean;
begin
  Self.Cursor := crHourGlass;
  if (Self.Focused and (Self.IndexSelectData + 1 < FScaleCode.Count ) ) then Self.IndexSelectData := Self.IndexSelectData + 1;
  Self.Cursor := crArrow;
end;

function TMyComboBox.DoMouseWheelUp(Shift: TShiftState; MousePos: TPoint): Boolean;
begin
  Self.Cursor := crHourGlass;
  if (Self.Focused and (Self.IndexSelectData - 1 > -1 ) ) then Self.IndexSelectData := Self.IndexSelectData - 1;
  Self.Cursor := crArrow;
end;

procedure TMyComboBox.OnChange(Sender: TNotifyEvent);
begin
  -> MessageQueue.Lock; // stop receiving message into queue
  ProcessHardware; // long procedure (approx. 200ms)
  -> MessageQueue.Unlock; // continue recieving message into queue
end;
功能TMyComboBox.domouseheeldown(换档:tshift状态;
鼠标点:TPoint):布尔值;
开始
Self.Cursor:=crHourGlass;
如果是(Self.Focused和(Self.IndexSelectData+1-1)),则Self.IndexSelectData:=Self.IndexSelectData-1;
Self.Cursor:=crArrow;
结束;
程序TMyComboBox.OnChange(发送方:TNotifyEvent);
开始
->MessageQueue.Lock;//停止将消息接收到队列中
ProcessHardware;//长程序(约200ms)
->MessageQueue.Unlock;//继续将消息接收到队列中
结束;
备注:设置IndexSelectData时,将引发OnChange

我读了一些关于Peek的信息,但我不知道如何使用它。。。(如果可以使用的话)


谢谢您的帮助。

我认为您无法阻止将邮件添加到队列中。但您可以接受队列中已存在的任何消息:

procedure SwallowPendingMessages(hWnd: HWND; MsgFilterMin, MsgFilterMax: UINT);
var
  M: TMsg;
begin
  while PeekMessage(M, hWnd, MsgFilterMin, MsgFilterMax, PM_REMOVE) do begin
    //gulp
  end;
end;
您可以在
OnChange
处理程序的末尾调用该函数


我不确定我是否会把你的提议视为一个好主意。我想我可能正在寻找解决这个问题的替代方案。可能是为了避免阻塞UI线程而使用线程的线程。

就是这样!直到我找到你提到的更好的解决方案。感谢+投票,但你可以简单地禁用/启用组合以防止收到进一步的输入,然后将焦点放回。。。(Veird comment策略更改,无法写入+1-…)@SertacAkyuz我认为,
ProcessHardware
没有泵入队列,这意味着消息将排队。我认为只有当队列及时得到服务时,禁用才有帮助。@David-禁用会阻止系统将输入发送到框中。似乎可用于睡眠。@SertacAkyuz是否会
PostMessage
失败?如果窗口被禁用?我不知道。