在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
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:=0; 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=200) then begin d2:=now; ShowMessage(IntToStr(MinutesBetween(d1,d2))); end; MainForm.Canvas.TextOut(0,0,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, 0, 0, 0, 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; 第四步,程序员手工建立消息循环: procedure TApplication.ProcessMessages; var Msg: TMsg; begin while ProcessMessage(Msg) do {loop}; end; 个人感想:程序的任何一个地方,都可以主动执行PeekMessage等消息函数,接管主程序的消息循环,参考: http://blog.csdn.net/mengde666/article/details/4045656 |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论