Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;

第一步,貌似什么都不做,但如果提前定义InitProc就不一样了

procedure TApplication.Initialize;
begin
if InitProc <> nil then TProcedure(InitProc);
end;

第二步,创建一部分Form,特别是MainForm

procedure TApplication.CreateForm(InstanceClass: TComponentClass; var Reference);
var
Instance: TComponent;
begin
Instance := TComponent(InstanceClass.NewInstance);
TComponent(Reference) := Instance;
try
Instance.Create(Self);
except
TComponent(Reference) := nil;
raise;
end;
if (FMainForm = nil) and (Instance is TForm) then
begin
TForm(Instance).HandleNeeded; // 这句话大有讲究,执行了许多动作。包括递归创建Parent的Handle

FMainForm := TForm(Instance);
end;
end;

第三步,使用repeat建立消息循环

procedure TApplication.Run;
var
i: integer;
d1,d2: TDateTime;
begin
i:=;
d1:=now;
FRunning := True;
try
AddExitProc(DoneApplication);
if FMainForm <> nil then
begin
case CmdShow of
SW_SHOWMINNOACTIVE: FMainForm.FWindowState := wsMinimized;
SW_SHOWMAXIMIZED: MainForm.WindowState := wsMaximized;
end;
if FShowMainForm then
if FMainForm.FWindowState = wsMinimized then Minimize
else FMainForm.Visible := True;
// 注意1,当鼠标移出当前窗口的范围时,不会继续执行当前repeat循环
// 注意2,经测试发现,每次点击鼠标或者按键,都会产生5个消息。
// 注意3,这里给每一个消息处理都包裹了一个异常处理。
repeat
begin
try
HandleMessage;
except
HandleException(Self);
end;
// 这里可以观察,当前窗口处理了多少个消息
inc(i);
if (i=) then begin d2:=now; ShowMessage(IntToStr(MinutesBetween(d1,d2))); end;
MainForm.Canvas.TextOut(,,IntToStr(i));
end
until Terminated;
end;
finally
FRunning := False;
end;
end;

第3.1步,具体处理每一个消息循环

procedure TApplication.HandleMessage;
var
Msg: TMsg;
begin
if not ProcessMessage(Msg) then
begin
Idle(Msg);
end;
end;

第3.2步,取得消息并分发消息,但是分发前好像还会先执行FOnMessage(Msg, Handled);

function TApplication.ProcessMessage(var Msg: TMsg): Boolean;
var
Handled: Boolean;
begin
Result := False;
if PeekMessage(Msg, , , , PM_REMOVE) then
begin
Result := True;
if Msg.Message <> WM_QUIT then
begin
Handled := False;
if Assigned(FOnMessage) then FOnMessage(Msg, Handled);
if not IsHintMsg(Msg) and not Handled and not IsMDIMsg(Msg) and not IsKeyMsg(Msg) and not IsDlgMsg(Msg) then
begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
end
else
FTerminate := True;
end;
end;

第3.3步 处理Hint,同步主线程,再调用 WaitMessage

procedure TApplication.Idle(const Msg: TMsg);
var
Control: TControl;
Done: Boolean;
begin
Control := DoMouseIdle;
if FShowHint and (FMouseControl = nil) then CancelHint;
Application.Hint := GetLongHint(GetHint(Control));
Done := True;
try
if Assigned(FOnIdle) then FOnIdle(Self, Done);
if Done then DoActionIdle;
except
HandleException(Self);
end;
if (GetCurrentThreadID = MainThreadID) and CheckSynchronize then
Done := False;
// 当一个线程的消息队列中无其它消息时,该函数就将控制权交给另外的线程,同时将该线程挂起,直到一个新的消息被放入线程的消息队列之中才返回。
// 在指定类型的新的输入消息抵达之前,它是不会返回的。
// 如果没有这句,或者不调用这个Idle,当前消息循环会不间断疯狂的去队列里取消息,1分钟即可执行30多万次,CPU 100%被占用
if Done then WaitMessage;
end;

第四步,程序员手工建立消息循环:
自己建立一个消息处理循环(while),把当前消息队列的所有消息一次性处理完毕,且不调用Idle。可以在while加上计数,看每次处理了多少个消息。

procedure TApplication.ProcessMessages;
var
Msg: TMsg;
begin
while ProcessMessage(Msg) do {loop};
end;

个人感想:程序的任何一个地方,都可以主动执行PeekMessage等消息函数,接管主程序的消息循环,参考:

http://blog.csdn.net/mengde666/article/details/4045656

Delphi主消息循环研究(Application.Run和Application.Initialize执行后的情况)的更多相关文章

  1. Chromium on Android: Android在系统Chromium为了实现主消息循环分析

    总结:刚开始接触一个Chromium on Android时间.很好奇Chromium主消息循环是如何整合Android应用. 为Android计划,一旦启动,主线程将具有Java消息层循环处理系统事 ...

  2. QObject::deleteLater()并没有将对象立即销毁,而是向主消息循环发送了一个event,下一次主消息循环收到这个event之后才会销毁对象 good

    程序编译运行过程很顺利,测试的时候也没发现什么问题.但后来我随手上传了一个1G大小的文件,发现每次文件上传到70%左右的时候程序就崩溃了,小文件就没这个问题.急忙打开任务管理器,这才发现上传文件的时候 ...

  3. 揭开.NET消息循环的神秘面纱(GetMessage()无法取得任何消息,就会进入Idle(空闲)状态,进入睡眠状态(而不是Busy Waiting)。当消息队列不再为空的时候,程序会自动醒过来)

    揭开.NET消息循环的神秘面纱(-) http://hi.baidu.com/sakiwer/item/f17dc33274a04df2a9842866 曾经在Win32平台下奋战的程序员们想必记得, ...

  4. Win32消息循环机制等【转载】http://blog.csdn.net/u013777351/article/details/49522219

    Dos的过程驱动与Windows的事件驱动 在讲本程序的消息循环之前,我想先谈一下Dos与Windows驱动机制的区别: DOS程序主要使用顺序的,过程驱动的程序设计方法.顺序的,过程驱动的程序有一个 ...

  5. Dart异步与消息循环机制

    Dart与消息循环机制 翻译自https://www.dartlang.org/articles/event-loop/ 异步任务在Dart中随处可见,例如许多库的方法调用都会返回Future对象来实 ...

  6. 【Dart学习】-- Dart之消息循环机制[翻译]

    概述 异步任务在Dart中随处可见,例如许多库的方法调用都会返回Future对象来实现异步处理,我们也可以注册Handler来响应一些事件,如:鼠标点击事件,I/O流结束和定时器到期. 这篇文章主要介 ...

  7. TMsgThread, TCommThread -- 在delphi线程中实现消息循环(105篇博客,好多研究消息的文章)

    在delphi线程中实现消息循环 在delphi线程中实现消息循环 Delphi的TThread类使用很方便,但是有时候我们需要在线程类中使用消息循环,delphi没有提供.   花了两天的事件研究了 ...

  8. TMsgThread, TCommThread -- 在delphi线程中实现消息循环

    http://delphi.cjcsoft.net//viewthread.php?tid=635 在delphi线程中实现消息循环 在delphi线程中实现消息循环 Delphi的TThread类使 ...

  9. Delphi主窗口任务栏菜单的问题(转发WM_SYSCOMMAND到Application)

    Delphi的VCL框架在创建应用时TApplication是一个自动创建的隐藏窗口,其它创建的窗口是自动以该窗口为窗口,这就导致创始的主窗口在任务栏的系统菜单只有三项,只要在主窗口的Create事件 ...

随机推荐

  1. springboot 出现异常 java.net.BindException: Address already in use: bind

    java.net.BindException: Address already in use: bind

  2. registry搭建及镜像管理

    registry 的搭建 docker pull registry:2 docker run -d -v /opt/registry:/var/lib/registry -p 5000:5000 -- ...

  3. Java多线程的创建方法

    Java 线程类也是一个 object 类,它的实例都继承自java.lang.Thread 或其子类. 可以用如下方式用 java 中创建一个线程,执行该线程可以调用该线程的 start()方法: ...

  4. [LeetCode]-DataBase-Trips and Users

    The Trips table holds all taxi trips. Each trip has a unique Id, while Client_Id and Driver_Id are b ...

  5. Vue 中 双向绑定数据

    1.文本 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <titl ...

  6. csdn专家主页

    百度张瑞琪: http://blog.csdn.net/abcjennifer 深度学习系列教程: http://suanfazu.com/t/caffe/9479

  7. React Native商城项目实战05 - 设置首页的导航条

    1.Home.js /** * 首页 */ import React, { Component } from 'react'; import { AppRegistry, StyleSheet, Te ...

  8. leetcode-mid-array-sorting and searching - 215 Kth Largest Element in an Array

    mycode  77.39% class Solution(object): def findKthLargest(self, nums, k): """ :type n ...

  9. win 10 hosts文件不生效

    win 10 hosts文件不生效       windows 10 hosts文件修改了,但是怎么都无法在浏览器中进行解析.一直都在等待,直到链接超时. 最后解决办法: 把hosts文件内容复制出来 ...

  10. 硬件-硬盘-SSD(固态硬盘):百科

    ylbtech-硬件-硬盘-SSD(固态硬盘):百科 固态驱动器(Solid State Disk或Solid State Drive,简称SSD),俗称固态硬盘,固态硬盘是用固态电子存储芯片阵列而制 ...