原创 Delpih中的windowsAPI编程初步

2006-11-29 13:08 3019 3 3 分类: 软件与OS
Delpih中的windowsAPI编程初步


 
  一、消息的定义
  我们先从使用的角度看看windows的运作过程。我们都知道windows是一个多任务的平台,使用这个平台,我们可以一边工作,一边听歌曲,等等。所以对于这个操作平台可以想象到它除了一般操作系统所提供的对文件系统,内存系统等的管理之外,更重要的就是我们所熟知的消息驱动了,也就是说,要通过一定的方法和结构可以给每一个运行中的程序实例以及其中的每一个窗口传递其中所触发的事件。Windows中究竟是怎样做到的呢?让我们打开安装delphi的目录,在其中的source\rtl\Win\Windows.pas文件(或者在一个工程文件,找到uses,在其中找到Windows,然后按下Ctrl键,用鼠标点击单词),在其中的第18919行,我们可以看到这样一个结构的定义:
  
  { Message structure }
  
  PMsg = ^TMsg ;
  
  tagMSG = packed record
  
  hwnd : HWND ;
  
  message : UINT ;
  
  wParam : WPARAM ;
  
  lParam : LPARAM ;
  
  time : DWORD ;
  
  pt : TPoint ;
  
  end ;
  
  { $ EXTERNALSYM tagMSG }
  
  TMsg = tagMSG ;
  
  MSG = tagMSG ;
  
  { $ EXTERNALSYM MSG }
  
  其中hwnd字段表示触发了消息的窗口的ID,由此可以保证消息正确的发送到每一个窗口去。 Message 表示消息的类型,其中更细致的解释要通过wParam和lParam一起来进行,不同的消息,wParam和lParam的值也就不相同。time用来记录消息触发的时间。Pt则表示触发的位置(毕竟window中有了鼠标)。我们也可以用同样的方法打开Messages文件。其中定义了windows中的绝大部分消息和结构。下面是我们截取的其中一部分。
  
  const
  
  { $ EXTERNALSYM WM_NULL }
  
  WM_NULL       = $0000 ;
  
  { $ EXTERNALSYM WM_CREATE }
  
  WM_CREATE      = $0001 ;
  
  { $ EXTERNALSYM WM_DESTROY }
  
  WM_DESTROY     = $0002 ;
  
  { $ EXTERNALSYM WM_MOVE }
  
  WM_MOVE       = $0003 ;
  
  { $ EXTERNALSYM WM_SIZE }
  
  WM_SIZE       = $0005 ;
  
  ……            ……
  
  WM_APP = $8000 ;
  
  { NOTE : All Message Numbers below 0x0400 are RESERVED }
  
  { Private Window Messages Start Here }
  
  { $ EXTERNALSYM WM_USER }
  
  WM_USER       = $0400 ;
  
  ……            ……
  
  { Dialog messages }
  
  { $ EXTERNALSYM DM_GETDEFID }
  
  DM_GETDEFID = ( WM_USER+0 ) ;
  
  { $ EXTERNALSYM DM_SETDEFID }
  
  DM_SETDEFID = ( WM_USER+1 ) ;
  
  { $ EXTERNALSYM DM_REPOSITION }
  
  DM_REPOSITION = ( WM_USER+2 ) ;
  
  { $ EXTERNALSYM PSM_PAGEINFO }
  
  PSM_PAGEINFO = ( WM_USER+100 ) ;
  
  { $ EXTERNALSYM PSM_SHEETINFO }
  
  PSM_SHEETINFO = ( WM_USER+101 ) ;
  
  { Button Notification Codes }
  
  ……            ……
  
  可以看到,windows中每一个消息都对应着一个唯一的数值。当然我们也可以定义自己的消息,它的数值只要定义在WM_USER之后,保证和其中的定义不想重复即可。
  
  二、消息的接收
  消息到是有了,但怎样才能让程序以及窗口接收到呢?还是从使用的角度考虑,可以想象到,对于一个程序或窗口可以接收到来自鼠标、键盘等输入设备的消息,也可以接收到来自程序传递的消息,因为有了前面的tagMSG结构,我们就可以被动的在程序中接收消息了。这个功能的实现就是由下面的程序实现的(同样的这段程序来自于delphi的元代码):
  
  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 ;
  
  其中主要的是这几句:
  
  if PeekMessage ( Msg , 0 , 0 , 0 , PM_REMOVE ) then
  
  begin
  
  TranslateMessage ( Msg ) ;
  
  DispatchMessage ( Msg ) ;
  
  end ;
  
  但更常见的是:
  
  while GetMessage ( Msg , 0 , 0 , 0 ) do
  
  begin
  
  TranslateMessage ( Msg ) ;
  
  DispatchMessage ( Msg ) ;
  
  End ;
  
  PeekMessage和GetMessage都是从消息队列中得到发给程序的消息,只要有消息,就通过TranslateMessage ( Msg )和DispatchMessage ( Msg )两句将消息翻译为可处理的格式并分派给应用程序所注册的回调函数进行处理。
PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
3
关闭 站长推荐上一条 /3 下一条