下面为Delphi中,方法TCustomForm.ShowModal的代码,通过分析以下代码,可以了解ShowModal到底是怎么一回事!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
function TCustomForm.ShowModal: Integer;
var
  WindowList: TTaskWindowList;
  LSaveFocusState: TFocusState;
  SaveCursor: TCursor;
  SaveCount: Integer;
  ActiveWindow: HWnd;
begin
  CancelDrag;
  if Visible or not Enabled or (fsModal in FFormState) or
    (FormStyle = fsMDIChild) then
    raise EInvalidOperation.Create(SCannotShowModal);
  if GetCapture <> 0 then SendMessage(GetCapture, WM_CANCELMODE, 0, 0);
  ReleaseCapture;
  Application.ModalStarted;
  try
    { RecreateWnd could change the active window }
    ActiveWindow := GetActiveWindow;
    Include(FFormState, fsModal);
    if (PopupMode = pmNone) and (Application.ModalPopupMode <> pmNone) then
    begin
      RecreateWnd;
      HandleNeeded;
      { The active window might have become invalid, refresh it }
      if (ActiveWindow = 0) or not IsWindow(ActiveWindow) then
        ActiveWindow := GetActiveWindow;
    end;
    LSaveFocusState := SaveFocusState;
    Screen.SaveFocusedList.Insert(0, Screen.FocusedForm);
    Screen.FocusedForm := Self;
    SaveCursor := Screen.Cursor;
    Screen.Cursor := crDefault;
    SaveCount := Screen.CursorCount;
    WindowList := DisableTaskWindows(0);
    try
      Show;
      try
        SendMessage(Handle, CM_ACTIVATE, 0, 0);
        ModalResult := 0;
        repeat
          Application.HandleMessage;
          if Application.Terminated then ModalResult := mrCancel else
            if ModalResult <> 0 then CloseModal;
        until ModalResult <> 0;
        Result := ModalResult;
        SendMessage(Handle, CM_DEACTIVATE, 0, 0);
        if GetActiveWindow <> Handle then ActiveWindow := 0;
      finally
        Hide;
      end;
    finally
      if Screen.CursorCount = SaveCount then
        Screen.Cursor := SaveCursor
      else Screen.Cursor := crDefault;
      EnableTaskWindows(WindowList);
      if Screen.SaveFocusedList.Count > 0 then
      begin
        Screen.FocusedForm := TCustomForm(Screen.SaveFocusedList.First);
        Screen.SaveFocusedList.Remove(Screen.FocusedForm);
      end else Screen.FocusedForm := nil;
      { ActiveWindow might have been destroyed and using it as active window will
        force Windows to activate another application }
      if (ActiveWindow <> 0) and not IsWindow(ActiveWindow) then
        ActiveWindow := FindTopMostWindow(0);
      if ActiveWindow <> 0 then
        SetActiveWindow(ActiveWindow);
      RestoreFocusState(LSaveFocusState);
      Exclude(FFormState, fsModal);
    end;
  finally
    Application.ModalFinished;
  end;

集中精力看这代码:

1
2
3
4
5
repeat
  Application.HandleMessage;
  if Application.Terminated then ModalResult := mrCancel else
    if ModalResult <> 0 then CloseModal;
until ModalResult <> 0;

众所周知,Windows是一个消息驱动的系统,一个窗口总是不断地在获取消息,处理消息这样的一个大循环中,以实时响应我们的操作。而上面这段代码,就是模拟了这样的一种过程,不断地去处理消息,判断程序是否退出,ModalResult是否为特定的值,如果是,则退出这个简单的消息。这段循环代码就保证了只有这代码代码执行完毕,才会在上一层代码中继续往下执行。

代码中通过

1
WindowList := DisableTaskWindows(0);

来禁止当前应用程序的其他窗口鼠标与键盘输入,通过

1
EnableTaskWindows(WindowList);

来激活其他窗口允许鼠标与键盘输入

Following listed the code of TCustomForm.ShowModal of Delphi, by analysis the source code, we can know how it works.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
function TCustomForm.ShowModal: Integer;
var
  WindowList: TTaskWindowList;
  LSaveFocusState: TFocusState;
  SaveCursor: TCursor;
  SaveCount: Integer;
  ActiveWindow: HWnd;
begin
  CancelDrag;
  if Visible or not Enabled or (fsModal in FFormState) or
    (FormStyle = fsMDIChild) then
    raise EInvalidOperation.Create(SCannotShowModal);
  if GetCapture <> 0 then SendMessage(GetCapture, WM_CANCELMODE, 0, 0);
  ReleaseCapture;
  Application.ModalStarted;
  try
    { RecreateWnd could change the active window }
    ActiveWindow := GetActiveWindow;
    Include(FFormState, fsModal);
    if (PopupMode = pmNone) and (Application.ModalPopupMode <> pmNone) then
    begin
      RecreateWnd;
      HandleNeeded;
      { The active window might have become invalid, refresh it }
      if (ActiveWindow = 0) or not IsWindow(ActiveWindow) then
        ActiveWindow := GetActiveWindow;
    end;
    LSaveFocusState := SaveFocusState;
    Screen.SaveFocusedList.Insert(0, Screen.FocusedForm);
    Screen.FocusedForm := Self;
    SaveCursor := Screen.Cursor;
    Screen.Cursor := crDefault;
    SaveCount := Screen.CursorCount;
    WindowList := DisableTaskWindows(0);
    try
      Show;
      try
        SendMessage(Handle, CM_ACTIVATE, 0, 0);
        ModalResult := 0;
        repeat
          Application.HandleMessage;
          if Application.Terminated then ModalResult := mrCancel else
            if ModalResult <> 0 then CloseModal;
        until ModalResult <> 0;
        Result := ModalResult;
        SendMessage(Handle, CM_DEACTIVATE, 0, 0);
        if GetActiveWindow <> Handle then ActiveWindow := 0;
      finally
        Hide;
      end;
    finally
      if Screen.CursorCount = SaveCount then
        Screen.Cursor := SaveCursor
      else Screen.Cursor := crDefault;
      EnableTaskWindows(WindowList);
      if Screen.SaveFocusedList.Count > 0 then
      begin
        Screen.FocusedForm := TCustomForm(Screen.SaveFocusedList.First);
        Screen.SaveFocusedList.Remove(Screen.FocusedForm);
      end else Screen.FocusedForm := nil;
      { ActiveWindow might have been destroyed and using it as active window will
        force Windows to activate another application }
      if (ActiveWindow <> 0) and not IsWindow(ActiveWindow) then
        ActiveWindow := FindTopMostWindow(0);
      if ActiveWindow <> 0 then
        SetActiveWindow(ActiveWindow);
      RestoreFocusState(LSaveFocusState);
      Exclude(FFormState, fsModal);
    end;
  finally
    Application.ModalFinished;
  end;

Focus on the following code:

1
2
3
4
5
repeat
  Application.HandleMessage;
  if Application.Terminated then ModalResult := mrCancel else
    if ModalResult <> 0 then CloseModal;
until ModalResult <> 0;

As we all know that, windows is a message based operation system.  A window is always in the circle of get message, handle message, in order to response to our actions, but the up code had simulate this situation: the code by using repeat to circle handle messages by calling the Application.HandleMessage method, and then check whether the application is terminated or ModalResult property of the TCustomForm have reached the indicated condition. This block of code have made it possible that the higher layer code could not be executed until showModal have finished.

In the code of TCustomForm.ShowModal, it disable all windows from mouse and keyboard input  in the process by calling the DisableTaskWindows function which returns a pointer called TTaskWindowList.

1
WindowList := DisableTaskWindows(0);

and enable it by calling the following code

1
EnableTaskWindows(WindowList);

下面为Delphi中,方法TCustomForm.ShowModal的代码,通过分析以下代码,可以了解ShowModal到底是怎么一回事!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
function TCustomForm.ShowModal: Integer;
var
  WindowList: TTaskWindowList;
  LSaveFocusState: TFocusState;
  SaveCursor: TCursor;
  SaveCount: Integer;
  ActiveWindow: HWnd;
begin
  CancelDrag;
  if Visible or not Enabled or (fsModal in FFormState) or
    (FormStyle = fsMDIChild) then
    raise EInvalidOperation.Create(SCannotShowModal);
  if GetCapture <> 0 then SendMessage(GetCapture, WM_CANCELMODE, 0, 0);
  ReleaseCapture;
  Application.ModalStarted;
  try
    { RecreateWnd could change the active window }
    ActiveWindow := GetActiveWindow;
    Include(FFormState, fsModal);
    if (PopupMode = pmNone) and (Application.ModalPopupMode <> pmNone) then
    begin
      RecreateWnd;
      HandleNeeded;
      { The active window might have become invalid, refresh it }
      if (ActiveWindow = 0) or not IsWindow(ActiveWindow) then
        ActiveWindow := GetActiveWindow;
    end;
    LSaveFocusState := SaveFocusState;
    Screen.SaveFocusedList.Insert(0, Screen.FocusedForm);
    Screen.FocusedForm := Self;
    SaveCursor := Screen.Cursor;
    Screen.Cursor := crDefault;
    SaveCount := Screen.CursorCount;
    WindowList := DisableTaskWindows(0);
    try
      Show;
      try
        SendMessage(Handle, CM_ACTIVATE, 0, 0);
        ModalResult := 0;
        repeat
          Application.HandleMessage;
          if Application.Terminated then ModalResult := mrCancel else
            if ModalResult <> 0 then CloseModal;
        until ModalResult <> 0;
        Result := ModalResult;
        SendMessage(Handle, CM_DEACTIVATE, 0, 0);
        if GetActiveWindow <> Handle then ActiveWindow := 0;
      finally
        Hide;
      end;
    finally
      if Screen.CursorCount = SaveCount then
        Screen.Cursor := SaveCursor
      else Screen.Cursor := crDefault;
      EnableTaskWindows(WindowList);
      if Screen.SaveFocusedList.Count > 0 then
      begin
        Screen.FocusedForm := TCustomForm(Screen.SaveFocusedList.First);
        Screen.SaveFocusedList.Remove(Screen.FocusedForm);
      end else Screen.FocusedForm := nil;
      { ActiveWindow might have been destroyed and using it as active window will
        force Windows to activate another application }
      if (ActiveWindow <> 0) and not IsWindow(ActiveWindow) then
        ActiveWindow := FindTopMostWindow(0);
      if ActiveWindow <> 0 then
        SetActiveWindow(ActiveWindow);
      RestoreFocusState(LSaveFocusState);
      Exclude(FFormState, fsModal);
    end;
  finally
    Application.ModalFinished;
  end;

集中精力看这代码:

1
2
3
4
5
repeat
  Application.HandleMessage;
  if Application.Terminated then ModalResult := mrCancel else
    if ModalResult <> 0 then CloseModal;
until ModalResult <> 0;

众所周知,Windows是一个消息驱动的系统,一个窗口总是不断地在获取消息,处理消息这样的一个大循环中,以实时响应我们的操作。而上面这段代码,就是模拟了这样的一种过程,不断地去处理消息,判断程序是否退出,ModalResult是否为特定的值,如果是,则退出这个简单的消息。这段循环代码就保证了只有这代码代码执行完毕,才会在上一层代码中继续往下执行。

代码中通过

1
WindowList := DisableTaskWindows(0);

来禁止当前应用程序的其他窗口鼠标与键盘输入,通过

1
EnableTaskWindows(WindowList);

来激活其他窗口允许鼠标与键盘输入

- See more at: http://www.neugls.info/delphi-showmodal-%e4%bb%a3%e7%a0%81%e5%88%86%e6%9e%90/#sthash.e9PphVDW.dpuf

参考:

http://www.neugls.info/delphi-showmodal-%E4%BB%A3%E7%A0%81%E5%88%86%E6%9E%90/

ShowModal 代码分析的更多相关文章

  1. Android代码分析工具lint学习

    1 lint简介 1.1 概述 lint是随Android SDK自带的一个静态代码分析工具.它用来对Android工程的源文件进行检查,找出在正确性.安全.性能.可使用性.可访问性及国际化等方面可能 ...

  2. pmd静态代码分析

    在正式进入测试之前,进行一定的静态代码分析及code review对代码质量及系统提高是有帮助的,以上为数据证明 Pmd 它是一个基于静态规则集的Java源码分析器,它可以识别出潜在的如下问题:– 可 ...

  3. [Asp.net 5] DependencyInjection项目代码分析-目录

    微软DI文章系列如下所示: [Asp.net 5] DependencyInjection项目代码分析 [Asp.net 5] DependencyInjection项目代码分析2-Autofac [ ...

  4. [Asp.net 5] DependencyInjection项目代码分析4-微软的实现(5)(IEnumerable<>补充)

    Asp.net 5的依赖注入注入系列可以参考链接: [Asp.net 5] DependencyInjection项目代码分析-目录 我们在之前讲微软的实现时,对于OpenIEnumerableSer ...

  5. 完整全面的Java资源库(包括构建、操作、代码分析、编译器、数据库、社区等等)

    构建 这里搜集了用来构建应用程序的工具. Apache Maven:Maven使用声明进行构建并进行依赖管理,偏向于使用约定而不是配置进行构建.Maven优于Apache Ant.后者采用了一种过程化 ...

  6. STM32启动代码分析 IAR 比较好

    stm32启动代码分析 (2012-06-12 09:43:31) 转载▼     最近开始使用ST的stm32w108芯片(也是一款zigbee芯片).开始看他的启动代码看的晕晕呼呼呼的. 还好在c ...

  7. 常用 Java 静态代码分析工具的分析与比较

    常用 Java 静态代码分析工具的分析与比较 简介: 本文首先介绍了静态代码分析的基 本概念及主要技术,随后分别介绍了现有 4 种主流 Java 静态代码分析工具 (Checkstyle,FindBu ...

  8. SonarQube-5.6.3 代码分析平台搭建使用

    python代码分析 官网主页: http://docs.sonarqube.org/display/PLUG/Python+Plugin Windows下安装使用: 快速使用: 1.下载jdk ht ...

  9. angular代码分析之异常日志设计

    angular代码分析之异常日志设计 错误异常是面向对象开发中的记录提示程序执行问题的一种重要机制,在程序执行发生问题的条件下,异常会在中断程序执行,同时会沿着代码的执行路径一步一步的向上抛出异常,最 ...

随机推荐

  1. 配置php扩展memcache

    配置php扩展memcache 环境说明: 系统版本    CentOS 6.9 x86_64         软件版本    nginx-1.12.2        php-5.5.38       ...

  2. AndroidStudio怎么实现微信分享功能

    在应用中添加微信分享功能,需要在微信开放平台上传你的应用,审核通过后方可使用此功能. https://open.weixin.qq.com/网址 申请的过程比较简单,这里就不追溯了,贴一个友情链接 h ...

  3. java学习笔记——日期处理

    获取系统当前时间使用:java.util.Date类,而这个Date的构造方法如下: 无参构造:public Date() 有参构造:public Date(long date) 第一个实例: imp ...

  4. Windows虚拟内存如何设置

    当我们在运行一些大型的软件,或者是刚刚退出游戏的时候经常会提示"你的虚拟内存过低"的提示,出现这种情况一般是:一:你的物理内存比较小,运行大的软件比较吃力:二:你运行了许多窗口或者 ...

  5. WordPress安全检测工具

    Wordpres是一款非常流行cms系统,市面上有相当一部分的博客和站点都是使用wordpress搭建.正因为大多博客都使用wordpress,所以其安全性就显得尤为重要. 我们平时维护一个站点(不仅 ...

  6. Django的Form、CSRF、cookie和session

    Django是一个大而全的web框架,为我们提供了很多实用的功能,本文主要介绍Form.CSRF.cookie和session 一.Form 在web页面中form表单是重要的组成部分,为了数据安全和 ...

  7. Php函数之end

    Php函数之end end()函数 (PHP 4, PHP 5, PHP 7) end - 将数组的内部指针指向最后一个单元 说明 mixed end ( array &$array ) en ...

  8. ecplise内存配置

    -server -Xms256m -Xmx512m -XX:PermSize=128M -XX:MaxPermSize=256m -XX:+UseG1GC

  9. react-navigation + react-native-vector-icons

    1.安装 yarn add react-navigation react-native-vector-icons 2.创建 root.js import React, {Component} from ...

  10. iOS时间间隔判断

    如何计算两个NSDate之间的时间间隔呢? timeIntervalSinceDate: Returns the interval between the receiver and another g ...