組件是如何顯示出來的?

來源:互聯網
上載者:User
組件是如何顯示出來的? VCL組件開發及應用
http://www.delphi2007.net/DelphiVCL/html/delphi_20061225141614123.html
同是一個基類比如twinctrol派生出來的的控制項,顯示的樣子各不相同,比如說BUTTON和STRINGGRID,看了看CREATE函數,好像裡邊只是對基本參數賦初試值,那當一個控制項被放置到視窗上後即被顯示出來,它是如何顯示出來的,這個過程怎樣處理的?換句話說它都調用了什麼函數實現顯示控制項的,控制項的樣式又是如何更改成各式各樣的?自己如何封裝才能讓一個控制項按自己的樣式顯示出來?

解答你的問題可以寫書了,建議看看入門書或者大全書,就瞭解了

一般通過調用TCanvas的方法或是GDI的API函數畫出的介面。  
  這個要做的多了畫起來就得心應手了,一般可以去找網上很多的時間日期控制項,有很多比較簡單的,很容易看懂,然後就照著他的畫,你想畫什麼樣的就畫什麼樣的,呵呵

To:   maozefa(阿發伯)  
        我知道問的問題有點範圍太大了,入門的書也看了一點,比如inside   vcl、高手突破、D5指南什麼的,只看明白了百分之70左右,總是感覺他講什麼知道,但是只是理性上的認識,沒有感性認識,或者說,明白其中的道理,但是讓自己作就又不知道如何下手了,希望可以找到以一個控制項比如BUTTON為主線講其整個實現過程。跟過源碼,但是總是無攻而返。能不能再給建議一些符合我情況要求的基本的書。順便問一下,有沒有專門介紹關於組件開發的書籍呢?還有關於DELPHI詳細文法的書籍,因為看VCL時發現一些文法書上根本就沒有介紹,比如說DEFAULT關鍵字等,看英文協助總是只能看董個大概,對所介紹知識的靈活運用協助不大,所以希望能找到一本詳細點的書籍。    
   
  To:zhangcheng125(老狼)    
        你說的時間控制項能不能給說一個具體的名稱,我好搜尋以下,謝謝。感覺寫控制項這個工作還是需要windowsAPI的知識比較多。

其實寫控制項並不是很難的東西,只是要學好畫圖的,像DELPHI裡的TCANVAS類,還有就是WINDOWS   API中關於GDI的部份,至於時間控制項,在DELPHI盒子裡很多的,可以去下來看看。個人認為只要把畫圖的這方面的知識學好了,管他什麼組件都可以寫出來(組件都是畫出來的。:)

下班了,粗粗的寫了一個,希望對你有協助。  
   
  unit   TestButtons;  
   
  interface  
   
  uses  
      SysUtils,   Classes,   Controls,   Buttons,   Windows,   Messages,   Graphics;  
   
  type  
      TTestButton   =   class(TCustomControl)  
      private  
          FShowEdge:   Boolean;  
          FEdgeColor:   TColor;  
          FEdgeWidth:   Integer;  
          procedure   SetShowEdge(const   Value:   Boolean);  
          procedure   SetEdgeColor(const   Value:   TColor);  
          procedure   SetEdgeWidth(const   Value:   Integer);  
          {   Private   declarations   }  
      protected  
          {   Protected   declarations   }  
          procedure   Paint;   override;  
      public  
          {   Public   declarations   }  
          constructor   Create(AOwner:   TComponent);   override;  
      published  
          {   Published   declarations   }  
          property   Caption;  
          property   Color;  
          property   Font;  
          property   ShowEdge:   Boolean   read   FShowEdge   write   SetShowEdge   default   True;  
          property   EdgeColor:   TColor   read   FEdgeColor   write   SetEdgeColor   default   clBlack;  
          property   EdgeWidth:   Integer   read   FEdgeWidth   write   SetEdgeWidth   default   1;  
      end;  
   
  procedure   Register;  
   
  implementation  
   
  procedure   Register;  
  begin  
      RegisterComponents('Samples',   [TTestButton]);  
  end;  
   
  {   TTestButton   }  
   
  constructor   TTestButton.Create(AOwner:   TComponent);  
  begin  
      inherited   Create(AOwner);  
   
      FShowEdge   :=   True;  
      FEdgeColor   :=   clBlack;  
      FEdgeWidth   :=   1;  
  end;  
   
  procedure   TTestButton.Paint;  
  var  
      R:   TRect;  
      procedure   DrawTexts(AText:   string;   ARect:   TRect);  
      begin  
          DrawText(Canvas.Handle,   PChar(AText),   -1,   ARect,   DT_CENTER   or   DT_VCENTER   or   DT_SINGLELINE);  
      end;  
  begin  
      inherited   Paint;  
   
      R   :=   ClientRect;  
      Canvas.Brush.Color   :=   Color;  
      Canvas.Brush.Style   :=   bsSolid;  
   
      Canvas.Pen.Width   :=   EdgeWidth;  
      Canvas.Pen.Color   :=   EdgeColor;  
      Canvas.Pen.Style   :=   psSolid;  
   
      if   ShowEdge   then  
          Canvas.Rectangle(ClientRect);  
   
      InflateRect(R,   -EdgeWidth,   -EdgeWidth);  
      Canvas.Font.Assign(Font);  
      DrawTexts(Caption,   R);  
  end;  
   
  procedure   TTestButton.SetEdgeColor(const   Value:   TColor);  
  begin  
      if   Value   <>   FEdgeColor   then  
      begin  
          FEdgeColor   :=   Value;  
          Repaint;  
      end;  
  end;  
   
  procedure   TTestButton.SetEdgeWidth(const   Value:   Integer);  
  begin  
      if   Value   <>   FEdgeWidth   then  
      begin  
          FEdgeWidth   :=   Value;  
          Repaint;  
      end;  
  end;  
   
  procedure   TTestButton.SetShowEdge(const   Value:   Boolean);  
  begin  
      if   Value   <>   FShowEdge   then  
      begin  
          FShowEdge   :=   Value;  
          Repaint;  
      end;  
  end;  
   
  end.  
 

TO:zhangcheng125(老狼)  
      謝謝,很有協助,藉機會問個問題:  
      property   ShowEdge:   Boolean   read   FShowEdge   write   SetShowEdge   default   True;  
          property   EdgeColor:   TColor   read   FEdgeColor   write   SetEdgeColor   default   clBlack;  
          property   EdgeWidth:   Integer   read   FEdgeWidth   write   SetEdgeWidth   default   1;  
  中都有個default關鍵字,協助中說不是預設值,是用來決定是否儲存屬性值,不太理解什麼含義,麻煩給解釋一下。  
   
  自己試著寫個控制項:主要是畫個類似GRID控制項。  
  具體做法是在TScrollBox控制項中來畫,代碼如下:  
  unit   test;  
   
  interface  
   
  uses  
      Windows,   Controls,   Forms,   Classes,   Graphics,   Messages,         dialogs;  
   
  type  
      TStatu   =   (bgNormal,   bgSelected,   bgMouseIn);  
   
      TCellInfo   =   record  
          Rect:   TRect;  
          Index:   Integer;  
          Status:   TStatu;  
      end;  
   
      TBrxDrawGrid   =   class(TGraphicControl)  
      private  
          FAlign:   TAlign;  
          FContainer:   TScrollBox;  
          FMax:   Integer;  
          FRow:   Integer;  
          FCol:   Integer;  
          FCellWidth:   Integer;  
          FCellHeight:   Integer;  
          FSpRow:   Integer;  
          FSpCol:   Integer;  
          FClientWidth:   Integer;  
          FClientHeight:   Integer;  
          FCIArray:   Array   of   Array   of   TCellInfo;  
          procedure   SetAlign(Value:   TAlign);  
          procedure   SetMax(const   Value:   Integer);  
          function   GetMax:   Integer;  
          procedure   SetRow(const   Value:   Integer);  
          procedure   SetCol(const   Value:   Integer);  
          procedure   SetCellWidth(const   Value:   Integer);  
          procedure   SetCellHeight(const   Value:   Integer);  
          procedure   SetSpRow(const   Value:   Integer);  
          procedure   SetSpCol(const   Value:   Integer);  
          procedure   SetClientHeight(const   Value:   Integer);  
          procedure   SetClientWidth(const   Value:   Integer);  
          procedure   InitCIArray(const   Row,   Col:   Integer);  
          procedure   WMPaint(var   Message:   TWMPaint);   message   WM_PAINT;  
      protected  
          procedure   SetCellInfo(const   Row,   Col:   Integer);  
   
          procedure   DrawCell;  
      published  
          property   Align:   TAlign   read   FAlign   write   SetAlign   default   alNone;  
          property   RowCount:   Integer   read   FRow   write   SetRow   default   5;  
          property   ColCount:   Integer   read   FCol   write   SetCol   default   5;  
          property   DefaultColWidth:   Integer   read   FCellWidth   write   SetCellWidth   default   64;  
          property   DefaultRowHeight:   Integer   read   FCellHeight   write   SetCellHeight   default   24;  
          property   SpaceOfRow:   Integer   read   FSpRow   write   SetSpRow   default   1;  
          property   SpaceOfCol:   Integer   read   FSpCol   write   SetSpCol   default   1;  
          property   Height:   Integer   read   FClientHeight   write   SetClientHeight   default   120;  
          property   Width:   Integer   read   FClientWidth   write   SetClientWidth   default   320;  
      public  
          constructor   Create(AOwner:   TComponent);   override;  
            procedure   Paint;   override;  
          function   GetCellCount:   Integer;  
          function   GetHandle:   HWND;  
      end;  
   
  implementation  
   
  {   TBrxDrawGrid   }  
   
  constructor   TBrxDrawGrid.Create(AOwner:   TComponent);  
  var  
      Max:   Integer;  
  begin  
      inherited   Create(AOwner);  
      FContainer   :=   TScrollBox.Create(AOwner);  
      FContainer.Parent   :=   TWinControl(AOwner);  
      FContainer.Align   :=   alNone;  
      SetRow(5);  
      SetCol(5);  
      SetCellWidth(64);  
      SetCellHeight(24);  
      SetSpRow(1);  
      SetSpCol(1);  
      Max   :=   25;  
      SetMax(Max);  
      InitCIArray(5,   5);  
   
  end;  
   
  procedure   TBrxDrawGrid.DrawCell;  
  var  
      i,   j:   Integer;  
  begin  
      Canvas.Handle   :=   GetDC(FContainer.Handle);  
      Canvas.Pen.Color   :=   clRed;  
      Canvas.Brush.Color   :=   clBlue;  
      for   i   :=   0   to   FRow   -   1   do  
      begin  
          for   j   :=   0   to   FCol   -   1   do  
          begin  
              Canvas.Rectangle(FCIArray[i][j].Rect);  
          end;  
      end;  
  end;  
   
  function   TBrxDrawGrid.GetCellCount:   Integer;  
  begin  
      Result   :=   GetMax;  
  end;  
   
  function   TBrxDrawGrid.GetHandle:   HWND;  
  begin  
      Result   :=   FContainer.Handle;  
  end;  
   
  function   TBrxDrawGrid.GetMax:   Integer;  
  begin  
      Result   :=   FMax;  
  end;  
   
  procedure   TBrxDrawGrid.InitCIArray(const   Row,   Col:   Integer);  
  var  
      i,   j:   Integer;  
  begin  
      SetLength(FCIArray,   Row,   Col);  
      for   i   :=   0   to   Row   -   1   do  
      begin  
          for   j   :=   0   to   Col   -   1   do  
          begin  
              FCIArray[i][j].Rect.Left   :=   j   *   (FCellWidth   +   FSpCol);  
              FCIArray[i][j].Rect.Top   :=   i   *   (FCellHeight   +   FSpRow);  
              FCIArray[i][j].Rect.Right   :=   FCIArray[i][j].Rect.Left   +   FCellWidth;  
              FCIArray[i][j].Rect.Bottom   :=   FCIArray[i][j].Rect.Top   +   FCellHeight;  
              FCIArray[i][j].Index   :=   i   *   Col   +   j;  
              FCIArray[i][j].Status   :=   bgNormal;  
          end;  
      end;  
  end;  
   
  procedure   TBrxDrawGrid.Paint;  
  begin  
      inherited;  
      DrawCell;  
  end;  
   
  procedure   TBrxDrawGrid.SetAlign(Value:   TAlign);  
  begin  
      if   FAlign   <>   Value   then  
      begin  
          FAlign   :=   Value;  
          FContainer.Align   :=   FAlign;  
      end;  
  end;  
   
  procedure   TBrxDrawGrid.SetCellHeight(const   Value:   Integer);  
  begin  
      if   FCellHeight   <>   Value   then  
      begin  
          FCellHeight   :=   Value;  
          InitCIArray(FRow,   FCol);  
      end;  
  end;  
   
  procedure   TBrxDrawGrid.SetCellInfo(const   Row,   Col:   Integer);  
  begin  
   
  end;  
   
  procedure   TBrxDrawGrid.SetCellWidth(const   Value:   Integer);  
  begin  
      if   FCellWidth   <>   Value   then  
      begin  
          FCellWidth   :=   Value;  
          InitCIArray(FRow,   FCol);  
      end;  
  end;  
   
  procedure   TBrxDrawGrid.SetClientHeight(const   Value:   Integer);  
  begin  
      if   FClientheight   <>   Value   then  
      begin  
          FClientHeight   :=   Value;  
          FContainer.Height   :=   FClientHeight;  
      end;  
  end;  
   
  procedure   TBrxDrawGrid.SetClientWidth(const   Value:   Integer);  
  begin  
      if   FClientWidth   <>   Value   then  
      begin  
          FClientWidth   :=   Value;  
          FContainer.Width   :=   FClientWidth;  
      end;  
  end;  
   
  procedure   TBrxDrawGrid.SetCol(const   Value:   Integer);  
  begin  
      if   FCol   <>   Value   then  
      begin  
          FCol   :=   Value;  
          InitCIArray(FRow,   FCol);  
      end;  
  end;  
   
  procedure   TBrxDrawGrid.SetMax(const   Value:   Integer);  
  begin  
      if   FMax   <>   Value   then  
      begin  
          FMax   :=   Value;  
      end;  
  end;  
   
  procedure   TBrxDrawGrid.SetRow(const   Value:   Integer);  
  begin  
      if   FRow   <>   Value   then  
      begin  
          FRow   :=   Value;  
          InitCIArray(FRow,   FCol);  
      end;  
  end;  
   
  procedure   TBrxDrawGrid.SetSpCol(const   Value:   Integer);  
  begin  
      if   FSpCol   <>   Value   then  
      begin  
          FSpCol   :=   Value;  
          InitCIArray(FRow,   FCol);  
      end;  
  end;  
   
  procedure   TBrxDrawGrid.SetSpRow(const   Value:   Integer);  
  begin  
      if   FSpRow   <>   Value   then  
      begin  
          FSpRow   :=   Value;  
          InitCIArray(FRow,   FCol);  
      end;  
  end;  
   
  procedure   TBrxDrawGrid.WMPaint(var   Message:   TWMPaint);  
  begin  
      Paint;  
  end;  
   
  end.  
   
  碰到幾個問題:  
  1.我的思路是系統發生WMPaint事件,調用Paint函數,Paint函數調用DrawCell,DrawCell完成畫圖工作並提供介面實現OnDrawCell。實現之後,當表單最小化再開啟,或是被其他船體覆蓋後,所畫的圖形消失,並沒有重畫,分析原因是因為沒有產生WM_PAINT訊息,控制項部分被擋住,當部分失效區有效時應該會產生個訊息,應該對這個訊息作處理,但是查看VCL中TDRAWGRID的實現,沒有弄明白他這一點是如何作的。  
  2.但寬度大於容器(TScrollBox)時,如何讓其產生捲軸。  
   
  3.以上諸如此類的問題,通過學習什麼書籍可以掌握解決方案?  
   
  謝謝

首先說明一下Default的問題,Default   是指將Default後面的值儲存到表單的dfm檔案中並不是指定預設值,如果要指定預設值的話要在建構函式中給定。  
   
  --------------------------  
  1.重繪的問題中你不用在WMPAINT訊息下調用Paint函數,WMPAINT函數本來就會調用PAINT函數的。還有就是Canvas本就是TGraphicControl的一個屬性,所以直接用就行了,不用去寫這個:Canvas.Handle   :=   GetDC(FContainer.Handle);了,再就是我不懂你為什麼要選建立個FContainer,直接畫不就行了。  
   
  2.關於捲軸。我一般是這麼做的自繪捲軸,比方說垂直的捲軸,道理是:  
  12321321  
  32323232   ----------top  
  43434343     捲軸  
  43434343   ----------Bottom  
  根據當前捲軸滑動的距離把頭部不顯示出來的畫在顯示地區外,也就是畫的時候:比方一個地區TRect,那麼就設他的Top為負的,這樣就能把不顯示的畫在地區外面,(這要根據計算捲軸滑塊滑動距離來得出TOp為負多少)同理水平捲軸也一樣。  
   
  3.諸如此類問題,最好的學習是看別人的原始碼,我是看了一些基礎的原始碼後自己在實踐中摸索的一些東西  
   
   
  以上個人覺的有些沒講清楚,也可能是錯的(全是我自己實踐中嘗試出來的,不過還算行還能用,呵呵),有不當或是不清楚的地方還望樓主和各位見諒,有空我可以寫個簡單的捲軸的例子給樓主。  
 

學習  
 

TO:zhangcheng125(老狼)  
        "有不當或是不清楚的地方還望樓主和各位見諒"---這我可不敢當,本來就是在向你請教問題,你能回答已經感不盡了。至於Default的問題現在脫您的富很清楚了,讀中文就是舒服,協助可以看懂,但是理解的不透徹。但是還有很多文法好笑一般文法書中也都沒有提到過,比如重新聲明什麼的,不知道你看的是哪本基礎的文法書籍,給推薦一下吧   :)  
          1.我故意用WMPAINT調用PAINT是因為我看了一下DRAWGRID的VCL源碼,它的WMPAINT好像沒有調用PAINT函數,(也可能在更早的父代對象中的WMPAINT中就調用了,但是我沒有跟蹤出來,沒有掠清頭緒,乾脆就覆寫了它),在PAINT中相應ONDRAWCELL,但是發現系統就沒有響應WMPAINT,正在鬱悶ing中,想不明白怎麼連一個WMPAINT訊息都沒有產生,或者說沒有相應。(之所以說沒有產生wmpaint訊息,是因為其中代碼根本沒執行)。各位知道是什麼原因嗎?  
        “Canvas.Handle   :=   GetDC(FContainer.Handle);了,再就是我不懂你為什麼要選建立個FContainer,直接畫不就行了。”--因為FContainer這個本身是一個TScrollBox對象執行個體。我的想法是將表格畫到這個控制項裡,本來開始想採用TPANEL,但是他沒有捲軸,所以就選擇了TScrollBox.雖然CANVAS被封裝可以直接使用,但是不將控制代碼給他就畫不到對應控制項上。不直接畫是因為可以省去一些屬性的實現,比如說ALIGN等等,而且他有捲軸,可以直接拿來用,捨得自己畫還要做更多的工作。  
          2.你說的捲軸的實現方法,我是聽董了,但是圖沒有看董,還有就是我想要是真的實現起來可能還會有接連不斷的問題隨之而來,不是怕遇到問題,只是想先解決目前的問題。  
   
          最後,謝謝zhangcheng125(老狼),目前還不會結帖,因為還有很多問題困擾。所以分遲遲不能發,請見諒。不過我知道您也不是為了分數對吧:),只是我心裡過不去。哈哈,還希望以後多多指教。  
   
   
 

今天又確認了一下,其他從TGraphicControl派生下來的控制項比如說TBevel,就是通過改寫Paint方法來實現繪製的,我直接派生了一個,只改寫了Paint方法,但是結果是又是會響應WMPAINT訊息,有時又不會,趕到納悶。在回到原來的控制項上來,同樣也是改寫了Paint方法,為什麼就不行呢,希望高人指點。

問題解決,開始是我有些基本屬性沒有初始化,初始化後問題解決。還有前面zhangcheng125(老狼)所說的Canva可以直接使用,是我多此一舉了。  
   
  最後再次感謝zhangcheng125(老狼),以後還請多指教。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.