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. List集合中对象的排序

    使用到的是: Collections.sort(); 用法是: List<Book> list_book = new ArrayList<Book>(); Book book= ...

  2. linux安装配置Redis,Swoole扩展

    我是使用的是lnmp环境(php5.6.3) 一.安装redis数据库(参考w3c手册) 下载地址:http://redis.io/download 本教程使用的最新文档版本为 2.8.17,下载并安 ...

  3. 代码检测docker-sonarqube

    gitlab-ce + gitlab-runner + sonarqube,在提交代码时对代码质量进行检测,对不符合要求的代码不允许提交到gitlab version: '3.1' services: ...

  4. Linux入门培训教程 linux网络编程socket介绍

    一.概念介绍 网络程序分为服务端程序和客户端程序.服务端即提供服务的一方,客户端为请求服务的一方.但实际情况是有些程序的客户端.服务器端角色不是这么明显,即互为Linux培训 客户端和服务端. 我们编 ...

  5. Python3学习笔记(五):列表和元组

    一.列表 列表是可变的--可以改变列表的内容 list函数可以把各种类型的序列拆分列表 >>> list('Hello') ['H', 'e', 'l', 'l', 'o'] 二.列 ...

  6. Min_25筛初级应用:求$[1,n]$内质数个数

    代码 #include <bits/stdc++.h> #define rin(i,a,b) for(int i=(a);i<=(b);++i) #define irin(i,a,b ...

  7. Spring Boot教程(十)异步方法测试

    测试 测试代码如下: @Component public class AppRunner implements CommandLineRunner { private static final Log ...

  8. sqli-libs(7)

    导出文件GET字符型注入 0x01介绍 导出到文件就是可以将查询结果导出到一个文件中,如常见的将一句话木马导出到一个php文件中,sqlmap中也有导出一句话和一个文件上传的页面 常用的语句是:  s ...

  9. [CSP-S模拟测试]:电压机制(图论+树上差分)

    题目描述 科学家在“无限神机”($Infinity\ Machine$)找到一个奇怪的机制,这个机制有$N$个元件,有$M$条电线连接这些元件,所有元件都是连通的.两个元件之间可能有多条电线连接.科学 ...

  10. [LeetCode]-DataBase-Rising Temperature

    Given a Weather table, write a SQL query to find all dates' Ids with higher temperature compared to ...