淺談Delpih中的windowsAPI程式設計初步(1)(轉)

post0發表於2007-08-12
淺談Delpih中的windowsAPI程式設計初步(1)(轉)[@more@]

  使用RAD型別工具的人越來越多了,雖然我對於RAD類的工具向來不多作評議,但我還是常常使用的。所以我深深的知道這類工具雖然給我們帶來了便利,使我們能不用將更多的精力放在介面上,但同時也將初學者緊緊的圈在了他所提供的控制元件和元件中。所以很多人並不能真正的瞭解windows的訊息驅動原理以及windows的運作過程。本文中我們就一起來學習一下windows的運作過程,使我們對delphi這樣一個優秀的程式設計工具有一個新的認識,並對windows下的程式編寫有更深刻、透闢的瞭解和認識。

  

  一、訊息的定義

  我們先從使用的角度看看windows的運作過程。我們都知道windows是一個多工的平臺,使用這個平臺,我們可以一邊工作,一邊聽歌曲,等等。所以對於這個操作平臺可以想象到它除了一般作業系統所提供的對檔案系統,記憶體系統等的管理之外,更重要的就是我們所熟知的訊息驅動了,也就是說,要透過一定的方法和結構可以給每一個執行中的程式例項以及其中的每一個視窗傳遞其中所觸發的事件。Windows中究竟是怎樣做到的呢?讓我們開啟安裝delphi的目錄,在其中的source tlWinWindows.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 )兩句將訊息翻譯為可處理的格式並分派給應用程式所註冊的回撥函式進行處理

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/8225414/viewspace-951876/,如需轉載,請註明出處,否則將追究法律責任。

相關文章