麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

組件制作之四(定制外觀)

2019-11-18 18:39:41
字體:
供稿:網(wǎng)友
時(shí)常想,如果一個(gè)組件能夠按自己想要的外觀顯示,那該是件多么COOL的事啊,這一篇就要來做一個(gè)精美外觀的組件,但是,做什么好呢.Button? 高手突破>有關(guān)于自己定義外觀的Button,以及CheckBox等的做法,Button從CustomPanel繼承,重載Paint方法來畫外觀.如果你有興趣,可以去找來看,這里就不做Button了,做一個(gè)Memo如何呢.?是個(gè)不錯(cuò)的主意。
 
我們先起個(gè)名字叫做TCoolMemo。以上篇已經(jīng)講了很多組件的技術(shù),這里就只說出幾個(gè)重點(diǎn)。其余不多說了。
 
首先,該Memo從CustomMemo繼承,它有這樣外觀:屬于平面的,邊框是可以設(shè)置顏色的線,對(duì)應(yīng)的顏色變量為FEdgeColor,另外,離邊框以內(nèi)的兩個(gè)象素處,還有另一個(gè)框,當(dāng)鼠標(biāo)進(jìn)入Memo時(shí),這個(gè)框會(huì)顯示,當(dāng)鼠標(biāo)離開時(shí),為個(gè)框消失,同樣也可以設(shè)置顏色,對(duì)應(yīng)變量為FEnterColor。
那么鼠標(biāo)進(jìn)入和離開怎么判斷呢,這里Memo將截獲兩個(gè)Delphi的內(nèi)部消息:
//下面兩個(gè)獲得Delphi的內(nèi)部消息,鼠標(biāo)進(jìn)入和離開時(shí)發(fā)生
     PRocedure CMMouseEnter (var Message: TMessage); message CM_MOUSEENTER;
     procedure CMMouseLeave (var Message: TMessage); message CM_MOUSELEAVE;
其實(shí)父類已經(jīng)截獲了這兩個(gè)消息,并作了相應(yīng)處理,所以TCoolMemo中的消息處理函數(shù)要
Inherited;再作自己的處理。這里又用到了一個(gè)變量
MouseIn:Boolean;//標(biāo)識(shí)鼠標(biāo)是否進(jìn)入組件
 
接下來TCoolMemo還要截獲兩個(gè)消息:
procedure WMPaint (var Message: TMessage); message WM_PAINT;
procedure WMNCCalcSize (var Message: TWMNCCalcSize); message WM_NCCALCSIZE;
第一個(gè)很熟悉,當(dāng)需要重畫時(shí),觸發(fā)該消息,
第二個(gè)是當(dāng)窗體需要計(jì)算位置和尺寸時(shí)觸發(fā),消息中包含了窗口客戶區(qū)的大小,我們用這個(gè)的目的主要是將客戶區(qū)縮小三個(gè)象素,以便畫組件時(shí)不會(huì)畫到客戶區(qū)。
procedure TCoolMemo.WMNCCalcSize (var Message: TWMNCCalcSize);
begin
  inherited;
  InflateRect(Message.CalcSize_Params^.rgrc[0], -3, -3);
end;
 
而上面幾個(gè)消息處理函數(shù),CM_MOUSEENTER和CM_MOUSELEAVE;將引起TCoolMemo的外觀變化,WM_PAINT保存其外觀不被擦去。所以要用到一個(gè)畫組件的函數(shù),即:
drawBorder;
里面用到了幾個(gè)API的GDI函數(shù)。我在代碼中有詳細(xì)的說明,加上自己看幫助,應(yīng)該是可以看懂的。
 
另外,相比于Memo,它的擴(kuò)展了這樣的功能:設(shè)置邊距和獲得光標(biāo)的位置。這兩個(gè)對(duì)應(yīng)的性屬為Margin,Position。他們都是Public的,不可以在對(duì)象察看器中看到。
我們一個(gè)個(gè)來說
邊距設(shè)置
property Margin:byte read FMargin write setMargin default 0;
其中setMargin函數(shù)中發(fā)送了兩個(gè)消息:
//該消息取得輸入?yún)^(qū)的尺寸
SendMessage(Handle, EM_GETRECT, 0, Longint(@Rect));
//該消息設(shè)定輸入?yún)^(qū)的大小
SendMessage(Handle, EM_SETRECT, 0, Longint(@Rect));
 
光標(biāo)的位置:
property Position:TPosition read getPosition;
TPostion是一個(gè)結(jié)構(gòu),其中有行和列兩個(gè)值:
TPosition=record  //指定光標(biāo)的行和列
     row:longint;
     col:longint;
   end;
getPosition;中還要處理中文的問題,代碼有詳細(xì)說明,如果文本中有中文,一樣也可以得到正確的行和列。
 
最后增加了兩個(gè)事件
property OnEnter;
property OnExit;
都是從父類中顯化出來的,其實(shí)就是CM_MOUSEENTER和CM_MOUSELEAVE;消息引起的。,當(dāng)你想作一個(gè)三態(tài)按鈕,這兩個(gè)事件很有作用。
 
好了,重點(diǎn)就是上面那幾個(gè)了,以下是源代碼,其中也有詳細(xì)的說明:
 
unit CoolMemo;
 
interface
 
uses
   Windows, Messages, Classes, Forms,Controls, Graphics, StdCtrls;
 
type
    //用設(shè)定邊緣的空白
   TPosition=record  //指定光標(biāo)的行和列
     row:longint;
     col:longint;
   end;
   TCoolMemo=class(TCustomMemo)
   private
     FMargin:byte;  //邊距的大小
     FEdgeColor:TColor;//邊框的顏色
     FEnterColor:TColor;//鼠標(biāo)進(jìn)入時(shí)邊框內(nèi)側(cè)的框顏色
     MouseIn: Boolean; //標(biāo)識(shí)鼠標(biāo)是否進(jìn)入
     function getPosition:TPosition;//光標(biāo)的行和列
     procedure setMargin(value:byte);
     procedure setEdgeColor(Value:TColor);
     procedure setEnterColor(Value:TColor);
     //下面兩個(gè)獲得Delphi的內(nèi)部消息,鼠標(biāo)進(jìn)入和離開時(shí)發(fā)生
     procedure CMMouseEnter (var Message: TMessage); message CM_MOUSEENTER;
     procedure CMMouseLeave (var Message: TMessage); message CM_MOUSELEAVE;
     //當(dāng)一個(gè)窗口的外觀必須被畫時(shí),應(yīng)用程序發(fā)送這個(gè)消息給該窗口
     procedure WMPaint (var Message: TMessage); message WM_PAINT;
     //窗體需要計(jì)算位置和尺寸時(shí)觸發(fā)
     //我們用這個(gè)的目的主要是將客戶區(qū)縮小三個(gè)象素,以便畫組件時(shí)不會(huì)畫到客戶區(qū)。
  procedure WMNCCalcSize (var Message: TWMNCCalcSize); message WM_NCCALCSIZE;
   protected
   //畫窗體的邊框,使其看起來更美觀.
     procedure drawBorder;
   public
     constructor Create (AOwner: TComponent); override;
     property Position:TPosition read getPosition;
     property Margin:byte read FMargin write setMargin default 0;
   published
    property EdgeColor:TColor read FEdgeColor write SetEdgeColor default $ff0000;
    property EnterColor:TColor read FEnterColor write SetEnterColor default $0000ff;
    //顯式化父類的屬性
    property Align;
    property Alignment;
    property DragCursor;
    property DragMode;
    property Enabled;
    property Color;
    property Font;
    property Lines;
    property MaxLength;
    property OEMConvert;
    property ParentFont;
    property ParentShowHint;
    property PopupMenu;
    property ReadOnly;
    property ShowHint;
    property ScrollBars;
    property TabOrder;
    property TabStop;
    property Visible;
    property WantReturns;
    property WantTabs;
    property WordWrap;
 
    property OnChange;
    property OnClick;
    property OnDblClick;
    property OnDragDrop;
    property OnDragOver;
    property OnEndDrag;
    //增加這兩個(gè)事件,處理鼠標(biāo)進(jìn)入和離開
    property OnEnter;
    property OnExit;
    property OnKeyDown;
    property OnKeyPress;
    property OnKeyUp;
    property OnMouseDown;
    property OnMouseMove;
    property OnMouseUp;
    property OnStartDrag;
   end;
 
procedure Register;
 
implementation
 
procedure Register;
begin
  RegisterComponents('Samples', [TCoolMemo]);
end;
 
constructor TCoolMemo.Create(AOwner:TComponent);
begin
  inherited Create(Aowner);
  ControlStyle := ControlStyle - [csFramed];
  ParentFont := True;
  FEdgeColor := $ff0000;
  FEnterColor := $0000ff;
  //設(shè)定外觀,平面無邊形
  Ctl3D := False;
  FMargin:=0;
  BorderStyle:=bsNone;
  height:=150;
  width:=200;
end;
 
procedure TCoolMemo.setMargin(Value:byte);
var
  Rect: TRect;
begin
//該消息取得客戶區(qū)的尺寸
  SendMessage(Handle, EM_GETRECT, 0, Longint(@Rect));
  //以下是重新確定尺寸
  Rect.Top := Value;
  Rect.Left := Value;
  Rect.Right := Width -Value;
  Rect.Bottom := Height -Value;
//該消息設(shè)定客戶區(qū)的大小
  SendMessage(Handle, EM_SETRECT, 0, Longint(@Rect));
  Fmargin:=value;
end;
 
function TCoolMemo.getPosition:TPosition;
var
  row,Col:longint;
  CBLines:longint;
  str:WideString;
begin
//該消息取得光標(biāo)所在的行,
  row:= SendMessage(Handle,EM_LINEFROMCHAR,SelStart,0);
  //該消息取得光標(biāo)所在行開始的位置,位置從第一行的0開始計(jì)數(shù),
  //每過一個(gè)字符增加1,
  CBLines:=SendMessage(Handle,EM_LINEINDEX,row,0);
  //得到光標(biāo)的所在行的所在列
  Col:=SelStart-CBLines;
  //為了解決中文的問題,需要用寬字符型來取得光標(biāo)所在行
  //,行中光標(biāo)所在列之前的字符串,這樣可以解決中文列數(shù)的確定問題.
  str:=Copy(Lines[row],1,col);
  col:=Length(Str)+1;
  result.row:=row+1;
  result.col:=col;
end;
 
procedure TCoolMemo.setEdgeColor(Value:TCOlor);
begin
 if FEdgeColor<>value then
 begin
  FEdgeColor:=value;
  drawBorder;
 end;
end;
 
procedure TCoolMemo.setEnterColor(Value:TColor);
begin
 if FEnterColor<>value then
 begin
   FEnterColor:=value;
   drawBorder;
 end;
end;
 
procedure TCoolMemo.CMMouseEnter(var Message: TMessage);
begin
  inherited;
    MouseIn:= True;
    drawBorder;
end;
 
procedure TCoolMemo.CMMouseLeave(var Message:TMessage);
begin
  inherited;
  MouseIn:=False;
  drawBorder;
end;
 
procedure TCoolMemo.WMPaint (var Message: TMessage);
begin
  inherited;
  drawBorder;
end;
 
procedure TCoolMemo.WMNCCalcSize (var Message: TWMNCCalcSize);
begin
  inherited;
  InflateRect(Message.CalcSize_Params^.rgrc[0], -3, -3);
end;
 
procedure TCoolMemo.drawBorder;
var
  DC: HDC;  //設(shè)備描述表
  R: TRect; //客戶區(qū)
  EnterBrush,OuterBrush,BorderBrush:HBRUSH;  //畫筆句柄,API
begin
  DC:= GetWindowDC(Handle);  //取得該組件的設(shè)備描述表
  try
    GetWindowRect(Handle, R);  //取得該組件的客戶區(qū)尺寸
    OffsetRect(R, -R.Left, -R.Top); //左上偏移
    //創(chuàng)建畫筆,兩個(gè),分別代碼邊框,邊框內(nèi),白色畫筆
    BorderBrush := CreateSolidBrush(ColorToRGB(FEdgeColor));
    EnterBrush:= CreateSolidBrush(ColorToRGB(FEnterColor));
    OuterBrush:=CreateSolidBrush(ColorToRGB(clWhite));
//not(csDesigning in ComponentState保證在設(shè)計(jì)期不變
    if (not(csDesigning in ComponentState)) and
    (MouseIn=true) then  //如果鼠標(biāo)進(jìn)入
    begin
      //畫一個(gè)矩形框,用BorderBrush畫筆
      FrameRect(DC, R, BorderBrush);
      //把R縮小一個(gè)象素
      InflateRect(R, -1, -1);
      //畫一個(gè)矩形框,用outerBrush畫筆
      FrameRect(DC, R, outerBrush);
      InflateRect(R, -1, -1);
      FrameRect(DC, R, EnterBrush);
    end
    else  //如果鼠標(biāo)沒有進(jìn)入
    begin
      FrameRect(DC, R, BorderBrush);
      InflateRect(R, -1, -1);
      FrameRect(DC, R, outerBrush);
      InflateRect(R, -1, -1);
      FrameRect(DC, R, outerBrush);
    end;
  finally
    ReleaseDC(Handle, DC);  //釋放設(shè)備描述表
  end;
  DeleteObject(BorderBrush);   //釋放畫筆
  DeleteObject(EnterBrush);
  DeleteObject(OuterBrush);
end;
 
end.
 
安裝上去試試吧,比Memo1好看多了,功能也強(qiáng)多了。是嗎。
 
至此已經(jīng)做了三個(gè)組件了,其實(shí)不算很復(fù)雜,只要理清思緒。到這里似乎可以結(jié)束這次的組件制作之旅了,但是還沒有。我們似乎還沒有做過非可視化組件。所以我想最后一個(gè),就是做一個(gè)非可視化組件。想知道是什么,往下看吧。

上一篇:并發(fā)

下一篇:組件制作之五(托盤組件)

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
學(xué)習(xí)交流
熱門圖片

新聞熱點(diǎn)

疑難解答

圖片精選

網(wǎng)友關(guān)注

主站蜘蛛池模板: 91国在线高清视频 | 毛片视频免费观看 | 国产91影院| 国产精品一区在线免费观看 | 中文字幕在线日韩 | 亚洲视频在线网 | 欧美一级做a | 黄色片网站在线免费观看 | 少妇一级淫片免费放播放 | 欧美18一19sex性护士农村 | 久久成年网站 | 国产一区二区久久精品 | 亚洲特黄妇女高潮 | 97黄色网| 毛片在线免费视频 | 最近日本电影hd免费观看 | 黄在线看 | 福利在线免费视频 | 欧洲成人一区二区 | 久综合 | 狠狠操人人干 | 欧美一级黄视频 | 免费永久在线观看黄网 | 欧美性受xxxx白人性爽 | 嫩呦国产一区二区三区av | 精品一区二区三区中文字幕老牛 | 毛片免费观看视频 | 中文字幕在线播放第一页 | 日韩激情一区 | 动漫孕妇被羞羞视频 | 国产一区二区欧美 | 亚洲草逼视频 | av免费在线观看国产 | 国产69精品久久99不卡免费版 | 九色在线78m| 在线成人看片 | 久久久久久久久成人 | 综合国产在线 | 精品国产一区二区久久 | 色阁阁69婷婷 | 国产精品视频一区二区三区四区国 |