青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

twzheng's cppblog

『站在風口浪尖緊握住鼠標旋轉!』 http://www.cnblogs.com/twzheng

  C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
  136 隨筆 :: 78 文章 :: 353 評論 :: 0 Trackbacks
C#制作WinForm控件  
摘自:http://www.cnblogs.com/salonliudong

自定義控件基礎知識

一 、概述

Windows 窗體控件是可再次使用的組件,它們封裝了用戶界面功能,并且可以用于客戶端 Windows 應用程序。“Windows 窗體不僅提供了許多現成控件,還提供了自行開發控件的基礎結構。可以組合現有控件、擴展現有控件或創作自己的自定義控件。Windows 窗體控件是從 System.Windows.Forms.Control 直接或間接派生的類。以下列表描述了開發 Windows 窗體控件的常見方案:

· 組合現有控件來創作一個復合控件。

復合控件封裝有一個可以作為控件重復使用的用戶界面。可視化設計器為創建復合控件提供了有力的支持。要創作一個派生System.Windows.Forms.UserControl 的復合控件。基類 UserControl 為子控件提供了鍵盤路由并使子控件可以作為一個組進行工作。

· 擴展現有控件,對其進行自定義或為其添加功能。

可以通過從任何 Windows 窗體控件派生控件并重寫或添加屬性、方法和事件的方式來自定義 Windows 窗體控件。

· 創作一個不是通過組合或擴展現有控件而形成的控件。

在這種方案中,需從基類 System.Windows.Forms.Control 派生控件。可以添加和重寫基類的屬性、方法和事件,來制作功能強大,能滿足自己需求的控件。

Windows 窗體控件的基類 System.Windows.Forms.Control 為客戶端 Windows 應用程序中的外觀顯示提供了所需的途徑。Control 提供了一個窗口句柄,用來處理消息路由并提供鼠標和鍵盤事件及許多其他用戶界面事件。還提供了高級布局,并具有用于外觀顯示的特定屬性,如 ForeColorBackColorHeightWidth 和許多其他屬性。此外,它還提供了安全性、線程支持以及與 ActiveX 控件的交互性。由于基類提供了很多基礎結構,使得開發自己的 Windows 窗體控件變得相對簡單。

二、編寫簡單的自定義控件
2.1、簡單控件例子

下面的示例創建一個簡單控件,該控件通過處理 Paint 事件顯示其 Text 屬性的值。為了創建此控件和處理事件,必須創建一個從 Control 繼承的類,并創建一個重寫 OnPaint 方法的方法。

public class HelloWorldControl : Control
 
{
protected override void OnPaint(PaintEventArgs e)
 
{
        RectangleF rect 
= new RectangleF(ClientRectangle.X,
                                         ClientRectangle.Y,
                                         ClientRectangle.Width,
                                         ClientRectangle.Height);

        e.Graphics.DrawString(
this.Text, Font, new SolidBrush(ForeColor), rect);
    }

}


 
2.2、我們在VS2005中創建自定義控件的步驟:

1. 打開vs2005,文件/新建/項目。

2. 出現“新建項目”對話框。

3. 在“名稱”框中,鍵入項目名稱,“位置”框選擇要存儲的位置。

4. 從“語言”列表中選擇要使用的編程語言。

5. 單擊“添加”,這時一個自定義控件工程已經建成,生成一下,就制作了一個簡單的自定義控件,只不過沒有任何功能。

6. 向新用戶控件添加任何標記和控件,并為該用戶控件添加執行的所有任務(例如,處理控件事件或從數據源讀取數據)添加代碼。

2.3、檢查控件的設計時行為

1. 啟動 VS2005

2. 通過從文件菜單單擊/新建/項目/Windows應用程序,添加新窗體。

3. 右鍵工具箱/選擇項…”,在彈出的“選擇工具箱項”對話框中點下面的瀏覽按鈕選擇要使用控件的 DLL;確定后,該控件出現在工具箱的底部。

4. 選擇該控件并將其添加到窗體中。將看到該控件出現在窗體上。

5. 如果從上一個示例添加控件,您將注意到即使如此簡單的控件都具有一整套屬性和廣泛的設計時行為。此默認行為是從 Control 類繼承的。

三、為控件添加屬性

控件應該定義屬性而不是公共字段,因為可視化設計器在屬性瀏覽器中顯示屬性,而不顯示字段。屬性就像智能字段。屬性通常具有帶訪問函數的專用數據成員,在語法上屬性被作為類的字段進行訪問。(雖然屬性可以具有不同的訪問級別,但此處的討論將重點放在公共訪問這種更加常見的情況上。

屬性定義通常由以下兩部分組成:
1
專用數據成員的定義。
   private int number = 0;

2、使用屬性聲明語法對公共屬性進行的定義。
該語法通過 get set 訪問函數將專用數據成員和公共屬性關聯起來。
        public int MyNumber 
    
{
    
get 
       

          
return number; 
       }
    
    
set 
       

          number 
= value;
       }

    }


 

value 這個術語是屬性定義語法中的一個關鍵字。在呼叫代碼中,將變量 value 分配給屬性。value 的類型必須同它被分配到的屬性的聲明類型相同。

雖然屬性定義中通常包含專用數據成員,但這不是必需的。get 訪問器不用訪問私有數據成員就可以返回值。get 方法返回系統時間的屬性就屬于這種情況。屬性啟用數據隱藏,訪問器方法隱藏屬性的實現。

定義屬性時需考慮以下重要的注意事項:

1、   必須將屬性應用于定義的屬性。屬性用來指定設計器顯示屬性的方式。

2、   如果改變屬性將影響控件的外觀顯示,請從 set 訪問器中調用 Invalidate 方法(從 Control 繼承該方法)。Invalidate 隨后調用 OnPaint 方法,該方法將重新繪制控件。為提高效率起見,對 Invalidate 的多次調用將產生對 OnPaint 的一次調用。

3、   .NET Framework 類庫為常見數據類型(如整數、小數、布爾值和其他數據)提供了類型轉換器。類型轉換器的目的通常是用來提供字符串到數值的轉換(從字符串數據轉換為其他數據類型)。常見數據類型與默認類型轉換器(將數值轉換為字符串,并將字符串轉換為相應數據類型)相關聯。如果定義了自定義(即,非標準)數據類型的屬性,則應用的屬性必須將類型轉換器指定為與該屬性相關聯。還可以使用屬性使自定義 UI 類型編輯器與某個屬性相關聯。UI 類型編輯器提供了一個用來編輯屬性或數據類型的用戶界面。顏色選擇器是 UI 類型編輯器的一個示例。

例:首先創建一個名為 DrawingMode 的簡單枚舉。

        public enum DrawingMode
        
{
            Happy 
= 0,
            Sad 
= 1,
            Angry 
= 2
        }


接著,向該控件添加 MyDrawingMode 屬性。

       private DrawingMode myDrawingMode;
       [Browsable(
true), Category("Appearance")]
        
public DrawingMode MyDrawingMode
        
{
            
get
            
{
                
return myDrawingMode;
            }

            
set
            
{
                myDrawingMode 
= value;
                SetColors();
            }

        }

SetColors 方法的調用只是根據 myDrawingMode 的值設置控件的 BackColor ForeColor。向控件添加下面的代碼。

        private void SetColors()
        
{
            
switch (myDrawingMode)
            
{
                
case DrawingMode.Happy:
                    
this.BackColor = Color.Yellow;
                    
this.ForeColor = Color.Green;
                    
break;
                
case DrawingMode.Sad:
                    
this.BackColor = Color.LightSlateGray;
                    
this.ForeColor = Color.White;
                    
break;
                
case DrawingMode.Angry:
                    
this.BackColor = Color.Red;
                    
this.ForeColor = Color.Teal;
                    
break;
                
default:
                    
this.BackColor = Color.Black;
                    
this.ForeColor = Color.White;
                    
break;
            }

        }


現在可以向控件的paint方法添加代碼,來繪制控件的樣式,也可以添加現有的控件來組合實現想要的功能(例子里面有)。

        private void UserControl1_Paint(object sender, PaintEventArgs e)
        
{
            Graphics curG 
= e.Graphics;
            Pen curPen 
= new Pen(Color.Black);
            Rectangle curRect 
= new Rectangle(00, Width - 2, Height - 3);
            curG.DrawRectangle(curPen, curRect);
            curG.DrawEllipse(curPen, curRect);
        }


四、為控件添加添加事件

事件(Event

事件是對象發送的消息,以發信號通知操作的發生。操作可能是由用戶交互(例如鼠標單擊)引起的,也可能是由某些其他的程序邏輯觸發的。引發事件的對象稱為事件發送方。捕獲事件并對其作出響應的對象叫做事件接收方。

在事件通信中,事件發送方類不知道哪個對象或方法將接收到(處理)它引發的事件。所需要的是在源和接收方之間存在一個媒介(或類似指針的機制)。.NET Framework 定義了一個特殊的類型(Delegate),該類型提供函數指針的功能。

代理(delegate

delegateC#中的一種類型,它實際上是一個能夠持有對某個方法的引用的類。與其它的類不同,delegate類能夠擁有一個簽名(signature),并且它只能持有與它的簽名相匹配的方法的引用。這樣,代理就等效于一個類型安全函數指針或一個回調。它允許你傳遞一個類A的方法m給另一個類B的對象,使得類B的對象能夠調用這個方法m。但與函數指針相比,delegate有許多函數指針不具備的優點。首先,函數指針只能指向靜態函數,而delegate既可以引用靜態函數,又可以引用非靜態成員函數。在引用非靜態成員函數時,delegate不但保存了對此函數入口指針的引用,而且還保存了調用此函數的類實例的引用。其次,與函數指針相比,delegate是面向對象、類型安全、可靠的受控(managed)對象。也就是說,runtime能夠保證delegate指向一個有效的方法,你無須擔心delegate會指向無效地址或者越界地址。

實現一個delegate是很簡單的,通過以下3個步驟即可實現一個delegate

1. 聲明一個delegate對象,它應當與你想要傳遞的方法具有相同的參數和返回值類型。

2. 創建delegate對象,并將你想要傳遞的函數作為參數傳入。

3. 在要實現異步調用的地方,通過上一步創建的對象來調用方法。

下面是一個簡單的例子:
public class MyDelegateTest 

    
// 步驟1,聲明delegate對象 
    public delegate void MyDelegate(string name); 
    
// 這是我們欲傳遞的方法,它與MyDelegate具有相同的參數和返回值類型 
    public static void MyDelegateFunc(string name) 
    

        Console.WriteLine(
"Hello, {0}", name); 
    }
 
    
public static void Main () 
    

        
// 步驟2,創建delegate對象 
      MyDelegate md = new MyDelegate(MyDelegateTest.MyDelegateFunc); 
        
// 步驟3,調用delegate 
        md("sam1111"); 
    }
 
}


 

事件處理

C#中的事件處理實際上是一種具有特殊簽名的delegate,象下面這個樣子:

public delegate void MyEventHandler(object sender, MyEventArgs e);

其中的兩個參數,sender代表事件發送者,e是事件參數類。MyEventArgs類用來包含與事件相關的數據,所有的事件參數類都必須從System.EventArgs類派生。當然,如果你的事件不含特別的參數,那么可以直接用System.EventArgs類作為參數。

結合delegate的實現,我們可以將自定義事件的實現歸結為以下幾步:

1:定義delegate對象類型,它有兩個參數,第一個參數是事件發送者對象,第二個參數是事件參數類對象。

2:定義事件參數類,此類應當從System.EventArgs類派生。如果事件不帶參數,這一步可以省略。

3:定義事件處理方法,它應當與delegate對象具有相同的參數和返回值類型。

4:用event關鍵字定義事件對象,它同時也是一個delegate對象。

5:用+=操作符添加事件到事件隊列中(-=操作符能夠將事件從隊列中刪除)。

6:在需要觸發事件的地方用調用delegate的方式寫事件觸發方法。一般來說,此方法應為protected訪問限制,既不能以public方式調用,但可以被子類繼承。名字是可以是OnEventName

7:在適當的地方調用事件觸發方法觸發事件。

下面是一個例子,例子模仿容器和控件的模式,由控件觸發一個事件,在容器中捕捉并且進行處理。

事件的觸發者:

/**//// <summary>
/// 事件的觸發者
/// </summary>

public class Control
{
    
public delegate void SomeHandler(object sender, System.EventArgs e);
    
public event SomeHandler SomeEvent;
    
public Control()
    
{
        
//這里使用的delegate必須與事件中聲名的一致
        this.SomeEvent += new SomeHandler(this.ProcessSomeEvent);
    }

    
public void RaiseSomeEvent()
    
{
        EventArgs e 
= new EventArgs();
        Console.Write(
"Please input 'a':");
        
string s = Console.ReadLine();
        
//在用戶輸入一個小a的情況下觸發事件,否則不觸發
        if (s == "a")
        
{
            SomeEvent(
this, e);
        }

    }

    
//事件的觸發者自己對事件進行處理,這個方法的參數必須和代理中聲名的一致
    private void ProcessSomeEvent(object sender, EventArgs e)
    
{
        Console.WriteLine(
"hello");
    }

}


事件的接收者:

/**//// <summary>
/// 事件的接收和處理者
/// </summary>

class Container
{
    
private Control ctrl = new Control();
   
public Container()
    
{
        
//這里使用的delegate必須與事件中聲名的一致
        ctrl.SomeEvent += new Control.SomeHandler(this.ResponseSomeEvent);
        ctrl.RaiseSomeEvent();
    }

    
public static void Main()
    
{
        Container pane 
= new Container();
        Console.ReadLine();
    }

    
//這是事件的接受者對事件的響應
    private void ResponseSomeEvent(object sender, EventArgs e)
    
{
        Console.WriteLine(
"Some event occur!");
    }

}

 

程序運行的結果如下:

please input 'a':a

hello

Some event occur!
 

五、其他屬性設置

   自定義控件工程建立, 控件設置,屬性事件的添加完成以后,生成項目,控件就已經制作完成了,可以在測試工程中使用,這里還有許多設置屬性,需要我們了解,比如(下圖)我們自己制作的控件顯示的圖標總是一個齒輪。
 
   而我們看到的工具箱上的每個控件都有自己的圖標,我們可以通過下面語句為自己制作的控件添加圖標。

[ToolboxBitmap(@"D:\Program Files\qq\AirDLIcon\1381love.ico")]
public partial class UserControl1 : UserControl
{………….}

即在控件類前面加上ToolboxBitmap屬性,屬性參數指向一個圖片的地址就可以了,加上這句程序以后,生成的控件如下圖,圖標變成了一個漂亮的心。
 
再比如,我自己定義了一個屬性,如果不進行設置,是不會在屬性窗口顯示的,也就是我們在用控件的時候不能夠通過可視化的界面對其進行設置,想讓它在屬性窗口顯示,就要用Browsable屬性了,如下面的例子。
        public enum DrawingMode{Happy = 0,Sad = 1,Angry = 2}
        
private DrawingMode myDrawingMode;
        [Browsable(
true)]
        
public DrawingMode MyDrawingMode
        
{
            
get
            
{
                
return myDrawingMode;
            }

            
set
            
{
                myDrawingMode 
= value;
            }

  }


 
像這樣的屬性還可以組合使用,例如上面的例子,我在Browsable屬性后面再加上一個Category屬性,讓它的參數等于Appearance,這時我們自己定義的屬性就從屬性框中的雜項轉到了外觀項里面了,如圖:
[Browsable(true), Category("Appearance")]
public DrawingMode MyDrawingMode
        
{
            
get
            
{
                
return myDrawingMode;
            }

            
set
            
{
                myDrawingMode 
= value;
            }

  }


 
 

像這樣的屬性有很多,我主要羅列下面這些,在使用的時候大家可以參照。

Browsable

適用于屬性和事件,指定屬性或事件是否應該顯示在屬性瀏覽器中。

Category

 適用于屬性和事件,指定類別的名稱,在該類別中將對屬性或事件進行分組。當使用了類別時,組件屬性和事件可以按邏輯分組顯示在屬性瀏覽器中。

Description

適用于屬性和事件,定義一小塊文本,該文本將在用戶選擇屬性或事件時顯示在屬性瀏覽器底部。

Bindable

適用于屬性 指定是否要綁定到該屬性。

DefaultProperty

適用于屬性,(將此特性插入類聲明前。)指定組件的默認屬性。當用戶單擊控件時,將在屬性瀏覽器中選定該屬性。

DefaultValue

 適用于屬性,為屬性設置一個簡單的默認值。

Editor

 適用于屬性,指定在可視設計器中編輯(更改)屬性時要使用的編輯器。

Localizable

 適用于屬性,指定屬性可本地化。當用戶要本地化某個窗體時,任何具有該特性的屬性都將自動永久駐留到資源文件中。

DesignerSerializationVisibility

適用于屬性,指定顯示在屬性瀏覽器中的屬性是否應該(以及如何)永久駐留在代碼中。

TypeConverter

適用于屬性,指定將屬性的類型轉換為另一個數據類型時要使用的類型轉換器。

DefaultEvent

 適用于事件,(將此特性插入類聲明前。)指定組件的默認事件。這是當用戶單擊組件時在屬性瀏覽器中選定的事件。



實例下載:/Files/salonliudong/salonliudong.rar
posted on 2007-11-27 02:31 譚文政 閱讀(3872) 評論(1)  編輯 收藏 引用 所屬分類: C#

評論

# re: C#制作WinForm控件 2008-01-30 10:03 phcis
不錯,圖標的事情解決了。。。  回復  更多評論
  

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲欧美国产精品va在线观看| 国产日韩欧美日韩| 亚洲国产片色| 欧美a级大片| 久久综合伊人77777麻豆| 精品动漫av| 亚洲国产精品电影在线观看| 欧美一区午夜精品| 在线观看欧美亚洲| 亚洲国产美女精品久久久久∴| 欧美激情视频在线播放 | 欧美激情一区二区三区在线视频| 91久久亚洲| 宅男噜噜噜66国产日韩在线观看| 国产精品久久久久久久app| 久久av资源网| 蜜臀av性久久久久蜜臀aⅴ| 一区二区不卡在线视频 午夜欧美不卡在| 亚洲激情啪啪| 免费久久99精品国产自| 亚洲激情在线激情| 欧美另类专区| 久久国产手机看片| 欧美丰满少妇xxxbbb| 亚洲欧美日韩直播| 久久亚洲一区二区三区四区| 夜夜夜久久久| 欧美一区二区三区四区视频| 亚洲精品一区二区三区福利| 亚洲影院免费| 亚洲人成网站影音先锋播放| 在线一区二区三区做爰视频网站 | 欧美成人免费在线视频| 亚洲图片你懂的| 久久午夜视频| 午夜精品999| 欧美国产日韩一区二区三区| 欧美专区在线播放| 欧美日韩免费视频| 欧美国产日韩在线| 国产日韩一区二区三区| 亚洲精品免费一二三区| 韩国成人福利片在线播放| 最新国产の精品合集bt伙计| 激情小说另类小说亚洲欧美| 一区二区三区产品免费精品久久75| 怡红院精品视频在线观看极品| 在线中文字幕不卡| 9久草视频在线视频精品| 久久久久久伊人| 性欧美暴力猛交另类hd| 欧美日韩麻豆| 最近中文字幕日韩精品| 在线观看亚洲视频啊啊啊啊| 午夜精品久久久久久久久久久| 亚洲美女在线观看| 欧美xx视频| 欧美高清影院| 亚洲国产视频a| 久久综合图片| 欧美国产三级| 亚洲精品一二| 欧美丰满少妇xxxbbb| 亚洲高清成人| 欧美一区二区三区在| 欧美一区二区三区的| 欧美日韩一区二区在线观看视频| 亚洲国产精品专区久久| 亚洲三级电影在线观看| 欧美大片免费观看| 91久久国产综合久久91精品网站| 日韩午夜高潮| 欧美日韩综合视频网址| 亚洲视频1区2区| 欧美在线免费视频| 国产综合色精品一区二区三区| 欧美在线免费看| 免费亚洲电影| 亚洲免费观看| 欧美午夜在线一二页| 亚洲女人天堂成人av在线| 欧美在线视频观看免费网站| 国产一区再线| 牛牛国产精品| 欧美日韩国产综合一区二区| 日韩天堂在线视频| 亚洲一区二区久久| 国产午夜精品久久久久久久| 久久成人精品视频| 欧美成人tv| 亚洲午夜久久久久久久久电影院| 国产精品女主播| 久久免费视频在线| 亚洲狼人精品一区二区三区| 亚欧美中日韩视频| 亚洲高清三级视频| 欧美视频中文字幕| 欧美一级片久久久久久久| 欧美国产精品专区| 亚洲一区二区在线免费观看| 国产亚洲精品资源在线26u| 欧美在线精品免播放器视频| 欧美成人情趣视频| 亚洲欧美日韩区| 在线播放日韩专区| 国产精品久久久久7777婷婷| 久久久精品性| 亚洲婷婷免费| 亚洲成色777777女色窝| 欧美一区久久| 久久精品国产96久久久香蕉| 亚洲国产91精品在线观看| 性色av一区二区三区在线观看 | 91久久中文| 国产乱码精品一区二区三区忘忧草| 久久综合狠狠综合久久综青草| 99视频精品在线| 亚洲成在人线av| 久久久蜜桃精品| 亚洲欧美激情视频在线观看一区二区三区| 精品va天堂亚洲国产| 国产精品亚洲综合天堂夜夜| 欧美福利视频网站| 久久全球大尺度高清视频| 9色精品在线| 最新日韩av| 亚洲成人在线网| 老牛国产精品一区的观看方式| 亚洲女优在线| 亚洲一区影院| 亚洲一区二区精品在线观看| 亚洲精品视频一区二区三区| 亚洲国产成人一区| 伊人久久大香线蕉综合热线| 国产欧美精品一区二区色综合 | 精品成人a区在线观看| 国产精一区二区三区| 欧美日韩亚洲一区二区三区| 欧美高清在线播放| 欧美777四色影视在线| 久久综合狠狠综合久久激情| 亚洲大黄网站| 免费精品视频| 欧美成人小视频| 欧美不卡在线| 亚洲第一色在线| 最新国产拍偷乱拍精品 | 亚洲一区欧美一区| 在线视频你懂得一区二区三区| 亚洲毛片在线| 麻豆av一区二区三区| 日韩视频精品在线| 一区二区高清视频| 正在播放欧美一区| 亚洲欧美精品伊人久久| 午夜伦欧美伦电影理论片| 欧美一区2区三区4区公司二百| 性色av一区二区怡红| 久久国产高清| 欧美成人国产一区二区| 欧美另类69精品久久久久9999| 欧美日韩一区自拍| 国产精品人人做人人爽| 国产专区精品视频| 亚洲国产91| 一区二区三区www| 欧美一区二区三区在线观看| 久久久精品午夜少妇| 欧美黑人多人双交| 日韩亚洲视频| 欧美中日韩免费视频| 麻豆精品视频在线观看| 欧美片第1页综合| 国产麻豆午夜三级精品| 在线观看久久av| 亚洲性感激情| 麻豆精品精华液| 夜夜嗨av一区二区三区网站四季av| 亚洲网址在线| 老司机午夜精品| 欧美午夜精品| 亚洲国产精品va在看黑人| 亚洲天堂视频在线观看| 蜜臀a∨国产成人精品| 日韩一级二级三级| 久久久久国产精品麻豆ai换脸| 欧美日韩伦理在线| 在线看国产日韩| 欧美亚洲在线| 最新成人在线| 久久最新视频| 国产日韩欧美在线观看| 99精品热视频| 久久久久久国产精品一区| 亚洲人成在线播放| 久久久精品国产一区二区三区| 欧美午夜宅男影院| 日韩亚洲欧美在线观看| 免费一级欧美片在线观看| 午夜亚洲视频|