程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> vc教程 >> 深入VCL理解BCB的消息機制2

深入VCL理解BCB的消息機制2

編輯:vc教程

重載TControl的WndProc方法

還是先談談VCL的繼承策略。VCL中的繼承鏈的頂部是TObject基類。一切的VCL組件和對象都繼承自TObject。

打開BCB幫助查看TControl的繼承關系:

TObject->TPersistent->TComponent->TControl

呵呵,原來TControl是從TPersistent類的子類TComponent類繼承而來的。TPersistent抽象基類具有使用流stream來存取類的屬性的能力。

TComponent類則是所有VCL組件的父類。

這就是所有的VCL組件包括您的自定義組件可以使用dfm文件存取屬性的原因『當然要是TPersistent的子類,我想您很少需要直接從TObject類來派生您的自定義組件吧』。

TControl類的重要性並不亞於它的父類們。在BCB的繼承關系中,TControl類的是所有VCL可視化組件的父類。實際上就是控件的意思吧。所謂可視化是指您可以在運行期間看到和操縱的控件。這類控件所具有的一些基本屬性和方法都在TControl類中進行定義。

TControl的實現在\Borland\CBuilder5\Source\Vcl\control.pas中可以找到。『可能會有朋友問你怎麼知道在那裡?使用BCB提供的Search -> Find in files很容易找到。或者使用第三方插件的grep功能。』

好了,進入VCL的源碼吧。說到這裡免不了要抱怨一下Borland。哎,為什麼要用pascal實現這一切.....:-(

TControl繼承但並沒有重寫TObject的Dispatch()方法。反而提供了一個新的方法就是xycleo提到的WndProc()。一起來看看Borland的工程師們是怎麼寫的吧。

procedure TControl.WndProc(var Message: TMessage);
var
  Form: TCustomForm;
begin
//由擁有control的窗體來處理設計期間的消息
  if (csDesigning in ComponentState) then
  begin
   Form := GetParentForm(Self);
   if (Form <> nil) and (Form.Designer <> nil) and
    Form.Designer.IsDesignMsg(Self, Message) then Exit;
  end
//如果需要,鍵盤消息交由擁有control的窗體來處理
  else if (Message.Msg >= WM_KEYFIRST) and (Message.Msg <= WM_KEYLAST) then
  begin
   Form := GetParentForm(Self);
   if (Form <> nil) and Form.WantChildKey(Self, Message) then Exit;
  end
//處理鼠標消息
  else if (Message.Msg >= WM_MOUSEFIRST) and (Message.Msg <= WM_MOUSELAST) then
  begin
   if not (csDoubleClicks in ControlStyle) then
    case Message.Msg of
     WM_LBUTTONDBLCLK, WM_RBUTTONDBLCLK, WM_MBUTTONDBLCLK:
      Dec(Message.Msg, WM_LBUTTONDBLCLK - WM_LBUTTONDOWN);
    end;
   case Message.Msg of
    WM_MOUSEMOVE: Application.HintMouseMessage(Self, Message);
    WM_LBUTTONDOWN, WM_LBUTTONDBLCLK:
     begin
      if FDragMode = dmAutomatic then
      begin
       BeginAutoDrag;
       Exit;
      end;
      Include(FControlState, csLButtonDown);
     end;
    WM_LBUTTONUP:
     Exclude(FControlState, csLButtonDown);
   end;
  end
// 下面一行有點特別。如果您仔細的話會看到這個消息是CM_VISIBLECHANGED.
// 而不是我們熟悉的WM_開頭的標准Windows消息.
// 盡管Borland沒有在它的幫助中提到有這一類的CM消息存在。但很顯然這是BCB的
// 自定義消息。呵呵,如果您對此有興趣可以在VCL源碼中查找相關的內容。一定會有不小的收獲。
  else if Message.Msg = CM_VISIBLECHANGED then
   with Message do
    SendDockNotification(Msg, WParam, LParam);
// 最後調用dispatch方法。
  Dispatch(Message);
end;

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved