当拖动窗口或单击下拉菜单时,VCL TTimer 停止
我启用了 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;
发生的事情是这样的。当 TTimer 启用并运行时,您拖动应用程序的任何窗口或单击下拉菜单,TTimer 事件完全停止工作,即使我在代码的其他部分采取了预防措施来防止这种情况发生。然而,这似乎没有帮助。
重新启动OnTimer
事件的唯一方法是用户通过TButton事件停止并重新启动Timer。
相同的代码或程序在使用 Delphi 7 编译的 Windows XP 下运行良好。目前,我正在使用 Windows 7 和 Delphi 2010 来重建我的系统。
我会尽力为您提供更多信息。我正在开发的是一个受版权保护的软件。
有一个名为 HandleMsg 的用户定义过程。它实际上处理串行端口消息。 HandleMsg设置为Application事件onMessage;
Application.onMessage :=HandleMsg();
PostMessage 与应用程序的 onMessage 事件相关联。
每当调用 PostMessage 时,它都会触发设置为 HandleMsg() 的 onMessage 事件。
这里是我的更多代码:
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;
HandleMsg() 响应 PostMessage。如果我错了请纠正我。
I have TTimer
enabled and is supposed to run non-stop forever until the user stop it. However, it doesn't work that way. Within OnTimer
event, it processes window messages over and over again in milliseconds.
For instance, here is a snippet of my code.
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;
What happens is this. While the TTimer is enabled and running, you drag any windows of the application or click on pull down menu the TTimer event completely stops working, even though I have taken precautionary steps in other part of the code to prevent this from happening. However, it doesn't seem to be helping.
The only way to restart the OnTimer
event is to stop and restart the Timer by the user through TButton event.
The same code or program works fine under Windows XP compiled with Delphi 7. Currently, I am using Windows 7 and Delphi 2010 to rebuild my system.
I will try to give you more information. What I am working on is a copyrighted software.
There is a user defined procedure called HandleMsg. It actually processes the serial port messages. HandleMsg is set to the Application event onMessage;
Application.onMessage:=HandleMsg();
PostMessage is associated with onMessage event of the application.
Whenever PostMessage is called, it fires onMessage event which is set to HandleMsg().
Here more of my code:
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;
HandleMsg() responds to PostMessage. Correct me if I am wrong.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在这两种情况下(开始调整窗口大小/移动窗口或打开菜单),从
TApplication.ProcessMessage
分派的最后一条消息是WM_NCLBUTTONDOWN
(或WM_NCRBUTTONDOWN
如果标题和系统菜单存在并单击标题..或WM_RBUTTONUP
(如果打开上下文菜单等)。所有人的共同点是他们正在启动模式消息循环。例如,以下内容来自
WM_ENTERSIZEMOVE
文档:模态消息循环启动后,
TApplication.Run
中的HandleMessage
调用将不会返回,直到相关窗口的DefWindowProc
返回(在例如,>WM_NCLBUTTONDOWN
情况下,分派的消息将导致将WM_SYSCOMMAND
发送到窗口,该窗口将启动模式消息循环,并且在移动/调整大小完成之前不会返回)。因此,在此期间您将无法使用应用程序的OnMessage
处理程序(在TApplication.ProcessMessage
中调用)。你的解决方案很简单。不要使用
OnMessage
处理程序,而是使用您的表单的消息处理程序来处理消息:或者,将您的代码放入
OnTimer
事件中,因为WM_TIMER
本身已发布。In both cases (starting to size/move window or opening a menu) the last message dispatched from
TApplication.ProcessMessage
isWM_NCLBUTTONDOWN
(or aWM_NCRBUTTONDOWN
if caption and system menu exists and clicked on the caption.. or aWM_RBUTTONUP
if opening a context menu, etc..). Common to all is they are starting a modal message loop.For instance the below is from
WM_ENTERSIZEMOVE
documentation:After a modal message loop is started the
HandleMessage
call inTApplication.Run
will not return untilDefWindowProc
for the relevant window returns (in theWM_NCLBUTTONDOWN
case for instance, the dispatched message will cause aWM_SYSCOMMAND
to be sent to the window which will start the modal message loop and will not return until moving/sizing is complete). So you won't be able to use anOnMessage
handler of the application in this period which is called inTApplication.ProcessMessage
.Your solution is simple. Instead of using the
OnMessage
handler, handle the message with a message handler of your form:Or, put your code in the
OnTimer
event, sinceWM_TIMER
is itself posted.这是可以预料的。 Windows定时器基于消息队列标志,并且它是优先级最低的事件。当您开始调整窗口大小时,主应用程序事件队列中的计时器标志将停止处理,并且计时器将停止。你对此无能为力。需要明确的是,普通消息仍然有效,但计时器停止了。这很容易测试。
现在,要解决此问题,您可以向自己发送 WM_USER 消息(该消息应该会通过),或者更好的解决方案是使用线程执行关键操作,并使用计时器根据线程更新的信息更新 UI。然后,当用户调整窗口大小时,用户界面会暂停,但操作仍在继续。
This is to be expected. The Windows timer is based on a message queue flag, and it is the lowest priority event. When you start resizing a window, the timer flag in the main application event queue stops being processed, and the timer will stop. Nothing you can do about that. To be clear, ordinary messages will still work, but the timer stops. This is very easy to test.
Now, to resolve this, you can either send yourself WM_USER messages, which should get through, or the better solution is to use a thread to do the critical operation and use the timer to update UI from information that the thread updates. Then when the user resizes the window, you get a UI pause, but the operations are continuing.