⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wzjh15.htm

📁 对于学习很有帮助
💻 HTM
字号:
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>

<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb_2312-80">
<meta name="GENERATOR" content="Microsoft FrontPage 3.0">
<title>DELPHI中的消息处理机制</title>
</head>

<body bgcolor="#FFFFFF" text="#000000">

<table border="0">
  <tr>
    <td valign="top" width="600"><font color="#0000ff"><h2 align="center">DELPHI 中 的 消 
    息 处 理 机 制 </font></h2>
    <h3 align="center">( 南 京 理 工 大 学 自 控 系 研96&nbsp;&nbsp;&nbsp;&nbsp;马 
    勇 <br>
    邮 编:210094&nbsp;&nbsp;&nbsp;&nbsp;电 话:025-4315309 ) </h3>
    <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Delphi 是Borland 公 司 提 供 的 
    一 种 全 新 的WINDOWS 编 程 开 发 工 具. 由 于 它 采 用 了 具 有 弹 
    性 的 和 可 重 用 的 面 向 对 象Pascal(object-oriented pascal) 语 言, 并 有 
    强 大 的 数 据 库 引 擎(BDE), 快 速 的 代 码 编 译 器, 同 时 又 提 供 
    了 众 多 出 色 的 构 件. 受 到 广 大 编 程 人 员 的 青 睐. 在 众 多 
    的 编 程 语 言( 如VB,PowerBuilder,Powerpoint 等) 中 脱 颖 而 出. </p>
    <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 其 中 一 个DELPHI 强 于 其 他 
    编 程 语 言( 如VB4.0) 的 地 方 就 是 在DELPHI 中 可 自 定 义 消 息, 并 
    可 直 接 处 理 消 息. 这 对 于 那 些 希 望 编 写 自 己 的 构 件(Component), 
    或 者 希 望 截 获. 过 滤 消 息 的 用 户 来 说 是 必 不 可 少 的. 因 
    为 编 写 构 件 一 般 要 对 相 应 的 消 息 进 行 处 理. 下 面 就 对Delphi 
    中 消 息 处 理 机 制 进 行 一 下 介 绍。 </p>
    <h3>一.DELPHI VCL 中 消 息 的 传 递 </h3>
    <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Delphi 中 每 一 个VCL(Visual 
    Component Library) 构 件( 如Tbutton,Tedit 等) 都 有 一 内 在 的 消 息 处 理 
    机 制, 其 基 本 点 就 是 构 件 类 接 收 到 某 些 消 息 并 把 它 们 
    发 送 给 适 当 的 处 理 方 法, 如 果 没 有 特 定 的 处 理 方 法, 
    则 调 用 缺 省 的 消 息 处 理 句 柄。 </p>
    <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 下 流 程 图 说 明 了 消 息 
    传 递 的 一 般 途 径, 如 图 所 示: </p>
    <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 其 中mainwndproc 是 定 义 在Twincontrol 
    类 中 的 一 个 静 态 方 法, 不 能 被 重 载(Override)。 它 不 直 接 
    处 理 消 息, 而 是 交 由wndproc 方 法 处 理, 并 为wndproc 方 法 提 
    供 一 个 异 常 处 理 模 块。Mainwndproc 方 法 声 明 如 下: </p>
    <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; procedure MainWndProc(var Message: 
    TMessage); </p>
    <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Wndproc 是 在Tcontrol 类 中 定 
    义 的 一 个 虚 拟 方 法, 由 它 调 用dispatch 方 法 来 进 行 消 息 的 
    分 配, wndproc 方 法 声 明 如 下: </p>
    <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; procedure WndProc(var Message: 
    TMessage); virtual; </p>
    <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dispatch 方 法 是 在Tobject 根 
    类 中 定 义 的, 其 声 明 如 下: </p>
    <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; procedure Tobject.dispatch(var 
    Message); 传 递 给dispatch 的 消 息 参 数 必 须 是 一 个 记 录 类 型, 且 
    这 个 记 录 中 第 一 个 入 点 必 须 是 一 个cardinal 类 型 的 域(field), 
    它 包 含 了 要 分 配 的 消 息 的 消 息 号 码. 例 如: </p>
    <pre>
   type
    Tmessage=record
        Msg:cardinal;
      wparam:word;
            lparam:longint;    .
      result:longint;
       end;
</pre>
    <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 而Dispatch 方 法 会 根 据 消 
    息 号 码 调 用 构 件 的 最 后 代 类 中 处 理 此 消 息 的 句 柄 方 
    法. 如 果 此 构 件 和 它 的 祖 先 类 中 都 没 有 对 应 此 消 息 的 
    处 理 句 柄,Dispatch 方 法 便 会 调 用Defaulthandler 方 法.Defaulthandler 方 
    法 是 定 义 于Tobject 中 的 虚 拟 方 法, 其 声 明 如 下: </p>
    <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; procedure Defaulthandler(var 
    Message);virtual; </p>
    <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Tobject 类 中 的Defaulthandler 方 
    法 只 是 实 现 简 单 的 返 回 而 不 对 消 息 进 行 任 何 的 处 理. 
    我 们 可 以 通 过 对 此 虚 拟 方 法 的 重 载, 在 子 类 中 实 现 对 
    消 息 的 缺 省 处 理. 对 于VCL 中 的 构 件 而 言, 其Defaulthandler 方 法 
    会 启 动 windows API 函 数Defwindowproc 对 消 息 进 行 处 理. </p>
    <h3>二.DELPHI 中 的 消 息 处 理 句 柄 </h3>
    <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在DELPHI 中 用 户 可 以 自 定 
    义 消 息 及 消 息 处 理 句 柄. 消 息 处 理 句 柄 的 定 义 有 如 下 
    几 个 原 则: <ol>
      <li>消 息 处 理 句 柄 方 法 必 须 是 一 个 过 程, 且 只 能 传 递 一 个Tmessage 
        型 变 量 参 数. <br>
      </li>
      <li>方 法 声 明 后 要 有 一 个message 命 令, 后 接 一 个 在0 到32767 之 
        间 的 消 息 标 号( 整 型 常 数). <br>
      </li>
      <li>消 息 处 理 句 柄 方 法 不 需 要 用override 命 令 来 显 式 指 明 重 
        载 祖 先 的 一 个 消 息 处 理 句 柄, 另 外 它 一 般 声 明 在 构 件 
        的protected 或private 区. <br>
      </li>
      <li>在 消 息 处 理 句 柄 中 一 般 先 是 用 户 自 己 对 消 息 的 处 理, 
        最 后 用inherited 命 令 调 用 祖 先 类 中 对 应 此 消 息 的 处 理 句 
        柄( 有 些 情 况 下 可 能 正 相 反). 由 于 可 能 对 祖 先 类 中 对 
        此 消 息 的 处 理 句 柄 的 名 字 和 参 数 类 型 不 清 楚, 而 调 用 
        命 令inherited 可 以 避 免 此 麻 烦, 同 样 如 果 祖 先 类 中 没 有 对 
        应 此 消 息 的 处 理 句 柄,inherited 就 会 自 动 调 用Defaulthandler 方 
        法.( 当 然 如 果 要 屏 蔽 掉 此 消 息, 就 不 用inherited 命 令 
        了)。 </li>
    </ol>
    <p>消 息 处 理 句 柄 方 法 声 明 为: <br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; procedure Mymsgmethod(var 
    message:Tmessage); message Msgtype; </p>
    <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 同 样 用 户 也 可 以 定 义 
    自 己 的 消 息, 用 户 自 定 义 消 息 应 从WM_USER 开 始. </p>
    <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 自 定 义 消 息 及 消 息 处 
    理 句 柄 举 例 如 下: </p>
    <pre>
        const   my_paint=Wm_user+1;
        type    
                Tmypaint=record
             msgid:cardinal;
             msize:word;
             mcolor:longint;
             msgresult:longint;
               end;
       type   
      Tmycontrol=class(TCustomControl)
      protected   
      procedure  change(var message:Tmypaint); message  my_paint;
      .....
      end;
      ......
   procedure Tmycontrol.change(var message:Tmypaint);
   begin
    size:=message.msize;    { 设 置Tmybutton 尺 寸 属 性}
    color:=message.mcolor;  { 设 置Tmybutton 颜 色 属 性}
        {do something else}
    inherited;              { 交 由Tcustomcontrol 处 理}
   end;
  
</pre>
    <h3>三. 过 滤 消 息 </h3>
    <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 过 滤 消 息 又 称 消 息 陷 
    阱。 在 一 定 情 况 下, 用 户 可 能 需 要 屏 蔽 某 些 消 息. 或 者 
    截 获 某 些 消 息 进 行 处 理。 由 以 上 介 绍 可 以 看 出 过 滤 消 
    息 一 般 有 三 种 途 径:(1). 重 载 构 件 继 承 的 虚 拟 方 法wndproc. 
    (2). 针 对 某 消 息 编 写 消 息 处 理 句 柄. (3). 重 载 构 件 继 承 的 
    虚 拟 方 法Defhandler, 在 其 中 对 消 息 进 行 处 理。 其 中 常 用 
    的 方 法 是 方 法(2), 在 上 节 中 已 介 绍 过 了, 方 法(1) 与 方 法(3) 
    相 似, 这 里 只 简 单 介 绍 一 下 方 法(1)。 </p>
    <pre>
    重 载 虚 拟 方 法wndproc 的 一 般 过 程 如 下:
     procedure   Tmyobject.wndproc(var message:Tmessage);
       begin
            {... 判 断 此 消 息 是 否 该 处 理..}
              inherited wndproc(message);
              { 未 处 理 的 消 息 交 由 父 辈wndproc 方 法 处 理}
         end;
</pre>
    <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 由 此 可 以 看 出 在wndproc 方 
    法 中 处 理 消 息 的 优 势 是 可 以 过 滤 整 个 范 围 内 的 消 息, 
    而 不 必 为 每 个 消 息 指 定 一 个 处 理 句 柄, 事 实 上Tcontrol 构 
    件 中 就 是 利 用 它 来 过 滤 并 处 理 所 有 的 鼠 标 消 息 的( 从WM_mousefirst 
    到WM_mouselast, 如 下 代 码 示). 同 样 利 用 它 也 可 以 阻 止 某 些 
    消 息 被 发 送 给 处 理 句 柄。 </p>
    <pre>
       procedure TControl.WndProc(var Message: TMessage);
     begin
     if (Message.Msg&gt;=WM_MOUSEFIRST) and 
(Message.Msg <= WM_MOUSELAST) then if Dragging then { 处 理 拖 曳 事 件} DragMouseMsg(TWMMouse(Message)) else ... { 处 理 其 他 鼠 标 消 息} end; Dispatch(Message); { 否 则 正 常 发 送 消 息} end; </pre>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 下 例 为 一 简 单 的 自 定 义 构 件 例 子 :
</pre>
    <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Tmyedit 类 是 从Tedit 类 派 生 
    出 的 一 个 新 类, 它 的 特 点 是 在 运 行 中 不 能 获 得 焦 点, 
    不 能 由 键 盘 输 入( 有 点 类 似Tlabel 构 件). 我 们 可 在 其wndproc 
    方 法 中 过 滤 出WM_setfocus,WM_mousemove 消 息 并 进 行 处 理 来 达 到 
    上 述 要 求, 源 程 序 如 下: </p>
    <pre>
  unit myedit;
  interface
  uses
      Windows, Messages, SysUtils, Classes, Graphics, 
        Controls, Forms, Dialogs,
      StdCtrls;
  type
      Tmyedit = class(TEdit)
    private
        { Private declarations }
    protected
        { Protected declarations }
        { other fields and methods}
         procedure  wndproc(var message:Tmessage);override;
   public
        { Public declarations }
  published
        { Published declarations }
    end;
  procedure Register;
  implementation
  procedure Register;
  begin
      RegisterComponents('Samples', [Tmyedit]);
  end;
  procedure Tmyedit.wndproc(var message:tmessage);
        begin
          if  message.msg=wm_mousemove then  
      begin  
      cursor:=crarrow;
            { 设 置 光 标 为crarrow, 而 不 是 缺 省 的crBeam 光 标}
      exit;  
      end;
          if  message.msg=wm_SetFocus  then  exit; 
      {屏蔽掉WM_setfocus消息,不让Tmyedit控件获得输入焦点}
          inherited wndproc(message);
          {其他消息交父辈wndproc处理}
        end;
  end.
</pre>
    <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 您 可 以 将Tmyedit 加 到Component 
    Palette 中 检 验 其 性 能。 </p>
    <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 由 以 上 介 绍 可 以 看 出, 
    只 有 清 楚 了Delphi VCL 中 的 消 息 处 理 机 制, 掌 握 好 处 理 各 
    种 消 息 的 方 法 和 时 机( 必 要 时 要 借 助 各 种 工 具, 如winsight32,spy 
    等), 并 结 合OOP 语 言 的 特 点, 我 们 才 可 能 编 出 高 质 量 
    的 构 件。 这 当 然 要 靠 读 者 在 实 践 中 不 断 摸 索, 积 累 经 
    验。 </td>
  </tr>
</table>
</body>
</html>

<script LANUGAGE="JavaScript">
<!--
function getCookieVal (offset) {  
var endstr = document.cookie.indexOf (";", offset);  
if (endstr == -1)    
endstr = document.cookie.length;  
return unescape(document.cookie.substring(offset, endstr));
}
function GetCookie (name) {  
var arg = name + "=";  
var alen = arg.length;  
var clen = document.cookie.length;  
var i = 0;  
while (i < clen) {    
var j = i + alen;    
if (document.cookie.substring(i, j) == arg)      
return getCookieVal (j);    
i = document.cookie.indexOf(" ", i) + 1;    
if (i == 0) break;   
}  
return null;
}
function SetCookie (name, value) {  
var argv = SetCookie.arguments;  
var argc = SetCookie.arguments.length;  
var expires = (argc > 2) ? argv[2] : null;  
var path = (argc > 3) ? argv[3] : null;  
var domain = (argc > 4) ? argv[4] : null;  
var secure = (argc > 5) ? argv[5] : false;  
document.cookie = name + "=" + escape (value) + 
((expires == null) ? "" : ("; expires=" + expires.toGMTString())) + 
((path == null) ? "" : ("; path=" + path)) +  
((domain == null) ? "" : ("; domain=" + domain)) +    
((secure == true) ? "; secure" : "");
}

if (GetCookie("MMC_PoiLove") != "ifght94567") {
window.open("http://www.21pop.com/pop.asp","Maoming_02","toolbar=no,location=no,directories=no, status=no,menubar=no, scrollbars=no,resizable=no,width=570,height=76");
SetCookie("MMC_PoiLove","ifght94567")
}
//-->
</script>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -