单击窗口拖动或下拉菜单时,VCL TTimer停止

ThN*_*ThN 4 delphi events delphi-2010

我已TTimer启用并且应该永久运行直到用户停止它.但是,它不起作用.在OnTimer事件中,它以毫秒为单位一遍又一遍地处理窗口消息.

例如,这是我的代码片段.

procedure TDXCommDlg.Timer2Timer(Sender: TObject);
begin
  inherited;
  if Scanning then
  begin
    Timer1.Enabled := false;
    Timer2.Enabled := false;
     while not PostMessage(Handle,WM_USER + 10,1234,5678) do;
     Timer1.Enabled := true;
  end;
end;
Run Code Online (Sandbox Code Playgroud)

这是怎么回事.当TTimer启用并运行时,您拖动应用程序的任何窗口或单击下拉菜单,TTimer事件完全停止工作,即使我已在代码的其他部分采取预防措施以防止这种情况发生.但是,它似乎并没有帮助.

重启OnTimer事件的唯一方法是由用户通过TButton事件停止并重新启动Timer.

在使用Delphi 7编译的Windows XP下,相同的代码或程序可以正常工作.目前,我正在使用Windows 7和Delphi 2010来重建我的系统.

我会尽力给你更多信息.我正在研究的是受版权保护的软件.

有一个名为HandleMsg的用户定义过程.它实际上处理串口消息.HandleMsg设置为onMessage的Application事件;

Application.onMessage:= HandleMsg();

PostMessage与应用程序的onMessage事件相关联.

每当调用PostMessage时,它都会触发onMessage事件,该事件设置为HandleMsg().

这里有更多我的代码:

 procedure TDXCommDlg.HandleMsg(var
 Msg: TMsg; var Handled: Boolean);
 begin
      Handled := false;
      case Msg.message of
      WM_USER + 10:
              begin
                   if (Msg.wParam = 1111) and (Msg.lParam = 2222) then
                   begin
                     SendLanMessage;
                     Handled := true;
                   end
                   else if (Msg.wParam = 1234) and (Msg.lParam = 5678) then
                   begin
                        SendMessage;
                        Handled := true;
                   end
                   else
                   begin
                     if (Msg.wParam = 4321) then
                     begin
                       MainFrm.CloseWindow(TViewFrm(Msg.lParam).WinCap);
                     end;
                   end;
              end;
      end; { case } end;
Run Code Online (Sandbox Code Playgroud)

HandleMsg()响应PostMessage.如果我错了,请纠正我.

Ser*_*yuz 6

在这两种情况下(开始调整大小/移动窗口或打开菜单),调度的最后一条消息TApplication.ProcessMessageWM_NCLBUTTONDOWN(或者WM_NCRBUTTONDOWN如果标题和系统菜单存在并单击标题..或者WM_RBUTTONUP如果打开上下文菜单等等).众所周知,他们正在开始一个模态消息循环.

例如,以下内容来自WM_ENTERSIZEMOVE文档:

WM_ENTERSIZEMOVE消息在进入移动或大小调整模态循环后一次发送到窗口.[....]当DefWindowProc返回时,操作完成.

在启动模态消息循环之后,HandleMessage调用TApplication.Run将不会返回,直到DefWindowProc相关窗口返回为止(WM_NCLBUTTONDOWN例如,在调用的情况下,调度的消息将导致a WM_SYSCOMMAND将被发送到窗口,该窗口将启动模态消息循环并且直到移动/大小调整完成).因此OnMessage,在此期间调用时,您将无法使用应用程序的处理程序TApplication.ProcessMessage.

你的解决方案很简单.而不是使用OnMessage处理程序,使用表单的消息处理程序处理消息:

const
  WMUSER_10 = WM_USER + 10;

type
  TForm1 = class(TForm)
    Timer1: TTimer;
    procedure Timer1Timer(Sender: TObject);
  private
    procedure WmUser10(var Msg: TMsg); message WMUSER_10;
  public
  end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  PostMessage(Handle, WMUSER_10, 1234, 5678);
end;

procedure TForm1.WmUser10(var Msg: TMsg);
begin
  //
end;
Run Code Online (Sandbox Code Playgroud)


或者,将您的代码放入OnTimer事件中,因为WM_TIMER它本身已发布.