深入C++ Builder之編寫自己的元件-深入分析VCL繼承、訊息機制(1)

來源:互聯網
上載者:User
 

這篇文章提及內容可能大家已經在很多地方看到過了,作者也是如此,只不過還看了很多VCL原始碼,加上自己實際編寫元件的經驗,拼湊了這麼一篇文章。所以所有言論都是個人觀點、經驗的描述,僅供參考。

你可轉載,拷貝,但必須加入作者署名Aweay,如果用於商業目的,必須經過作者同意。

系統要求

如果你想一起跟著做的話,那麼你應該看看這裡,否則你可以直接跳過。
C++ Builder6 + updata4  (上帝造人的工具,以下簡稱BCB)
Windows2k or higher (必要)
作者強烈建議你使用WinNT,BCB在Win9x下有非常多的問題,而且非常不穩定,就算你不在乎這個,還有一個非常致命的問題,BCB的協助檔案在Win9x下顯示不完全(因為BCB的協助索引關鍵字數量超過Win9x的限制),這樣非常難於參考說明。
Delphi6 (必要)

嗎?是不是寫錯了,完全沒有寫錯,如果你要深入VCL查看原始碼的話,在沒有比用Delphi6更合適的了,在全部安裝Delphi6後,把VCL
Source的目錄加入Search Path中,這樣你可以在編輯器中按住Ctrl鍵,點擊滑鼠直接跳轉到原始碼處非常方便,比什麼grep好用多了。

起步

對於VCL的訊息機制,大家可以參考CKER的
http://www.csdn.net/develop/read_article.asp?id=8131

重複的內容我就不介紹了,但是對於編寫元件來說上面的訊息機制還是很模糊,而且很多時候並不是用那些方法來處理訊息的,還有就是元件特有的CM_XXXXXXXX訊息如何處理呢?如何加入自己的事件呢?這些問題我會在後面的討論中做詳細介紹。

站在巨人的肩膀

編寫元件的第一件事情就是確定我們從那裡繼承的問題,選取一個好的祖先類是編寫一個好的元件的第一步,那麼到底如何選取他山之石呢?一般性的規則是這樣的:
1.對於有介面的顯示的,需要處理鍵盤事件的,又不是容器的組件從TCustomControl繼承
2.對於有介面的顯示的,需要不處理鍵盤事件的,需要處理滑鼠事件的從TGraphicsControl繼承
3.對於沒有介面顯示的,類似與TOpenDialog/TXpMenu這樣的控制項從TComponent繼承
4.如果你想擴充某個指定的控制項,比如TPanel,你最好從TCustomPanel繼承,而不要從TPanel直接繼承。

注意上面第4條規則,基本上所有組件都有TCustomXXX的父類,這也是VCL鼓勵的繼承對象,原因在於你可以定製元件屬性的可見度,最重要的是他們的建構函式和解構函式是虛擬。

這篇文章主要針對1,2規則的元件進行介紹,3,4相對簡單就不作深入討論了。

畫出自己

元件要顯示在表單上,必須以一定的樣子出現,那麼可定要畫出自己,大家都知道處理WM_PAINT訊息就可以了,從CKER的文章裡,我們可以得出很多方法來處理這個訊息,比如:
__fastcall WndProc(TMessage msg)
{
  switch(msg->msg)
  {
    case WM_PAINT:
      //我們的處理代碼
  ...
}

或者乾脆用訊息映射的宏,但這些都不是最好的方法。

從TControl以後的組件都有Paint這個虛擬方法,我們只要重載這個方法就可以自動繪製,相當於處理了WM_PAINT,這是因為:
procedure TGraphicControl.WMPaint(var Message: TWMPaint);
begin
  if Message.DC <> 0 then
  begin
    Canvas.Lock;
    try
      Canvas.Handle := Message.DC;
      try
        Paint;
      finally
        Canvas.Handle := 0;
      end;
    finally
      Canvas.Unlock;
    end;
  end;
end;
以上代碼片斷說明了這一點,據我所研究過的專業級組件都是通過重載這個函數來繪製自己的。

注意上面的代碼片斷就是用我上面提到的方法(裝delphi6)按了幾次滑鼠左鍵得到的,是不是很實惠,^_^。

在Paint方裡我們可以自由繪製,在後面的文章裡我會交大家如何高效率繪製。

在很多時候,我們需要重繪自己,比如我前幾天給網友做的劃線的組件,當線的寬度改變時我們必須重繪自己,否則無法反映屬性的改變,我見很多朋友使用
repaint()方法,這也不是最好的方法,我們應該用Invalidate(),為什嗎?留給大家看原始碼吧,就算複習上面的知識了。
代碼示範:
void __fastcall TLine::SetLineWidth(int value)
{
  //TODO: Add your source code here
  if(FLineWidth!=value)
  {
    FLineWidth=value;
    Invalidate();
  }
}

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.