• <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>

            twzheng's cppblog

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

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

            自定義控件基礎(chǔ)知識

            一 、概述

            Windows 窗體控件是可再次使用的組件,它們封裝了用戶界面功能,并且可以用于客戶端 Windows 應(yīng)用程序。“Windows 窗體不僅提供了許多現(xiàn)成控件,還提供了自行開發(fā)控件的基礎(chǔ)結(jié)構(gòu)??梢越M合現(xiàn)有控件、擴展現(xiàn)有控件或創(chuàng)作自己的自定義控件。Windows 窗體控件是從 System.Windows.Forms.Control 直接或間接派生的類。以下列表描述了開發(fā) Windows 窗體控件的常見方案:

            · 組合現(xiàn)有控件來創(chuàng)作一個復(fù)合控件。

            復(fù)合控件封裝有一個可以作為控件重復(fù)使用的用戶界面??梢暬O(shè)計器為創(chuàng)建復(fù)合控件提供了有力的支持。要創(chuàng)作一個派生System.Windows.Forms.UserControl 的復(fù)合控件。基類 UserControl 為子控件提供了鍵盤路由并使子控件可以作為一個組進行工作。

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

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

            · 創(chuàng)作一個不是通過組合或擴展現(xiàn)有控件而形成的控件。

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

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

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

            下面的示例創(chuàng)建一個簡單控件,該控件通過處理 Paint 事件顯示其 Text 屬性的值。為了創(chuàng)建此控件和處理事件,必須創(chuàng)建一個從 Control 繼承的類,并創(chuàng)建一個重寫 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中創(chuàng)建自定義控件的步驟:

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

            2. 出現(xiàn)“新建項目”對話框。

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

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

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

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

            2.3、檢查控件的設(shè)計時行為

            1. 啟動 VS2005。

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

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

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

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

            三、為控件添加屬性

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

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

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

                      
            return number; 
                   }
                
                
            set 
                   

                      number 
            = value;
                   }

                }


             

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

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

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

            1、   必須將屬性應(yīng)用于定義的屬性。屬性用來指定設(shè)計器顯示屬性的方式。

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

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

            例:首先創(chuàng)建一個名為 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 方法的調(diào)用只是根據(jù) myDrawingMode 的值設(shè)置控件的 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;
                        }

                    }


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

                    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

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

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

            代理(delegate

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

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

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

            2. 創(chuàng)建delegate對象,并將你想要傳遞的函數(shù)作為參數(shù)傳入。

            3. 在要實現(xiàn)異步調(diào)用的地方,通過上一步創(chuàng)建的對象來調(diào)用方法。

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

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

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

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


             

            事件處理

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

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

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

            結(jié)合delegate的實現(xiàn),我們可以將自定義事件的實現(xiàn)歸結(jié)為以下幾步:

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

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

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

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

            5:用+=操作符添加事件到事件隊列中(-=操作符能夠?qū)⑹录年犃兄袆h除)。

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

            7:在適當?shù)牡胤秸{(diào)用事件觸發(fā)方法觸發(fā)事件。

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

            事件的觸發(fā)者:

            /**//// <summary>
            /// 事件的觸發(fā)者
            /// </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的情況下觸發(fā)事件,否則不觸發(fā)
                    if (s == "a")
                    
            {
                        SomeEvent(
            this, e);
                    }

                }

                
            //事件的觸發(fā)者自己對事件進行處理,這個方法的參數(shù)必須和代理中聲名的一致
                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();
                }

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

            }

             

            程序運行的結(jié)果如下:

            please input 'a':a

            hello

            Some event occur!
             

            五、其他屬性設(shè)置

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

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

            即在控件類前面加上ToolboxBitmap屬性,屬性參數(shù)指向一個圖片的地址就可以了,加上這句程序以后,生成的控件如下圖,圖標變成了一個漂亮的心。
             
            再比如,我自己定義了一個屬性,如果不進行設(shè)置,是不會在屬性窗口顯示的,也就是我們在用控件的時候不能夠通過可視化的界面對其進行設(shè)置,想讓它在屬性窗口顯示,就要用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屬性,讓它的參數(shù)等于Appearance,這時我們自己定義的屬性就從屬性框中的雜項轉(zhuǎn)到了外觀項里面了,如圖:
            [Browsable(true), Category("Appearance")]
            public DrawingMode MyDrawingMode
                    
            {
                        
            get
                        
            {
                            
            return myDrawingMode;
                        }

                        
            set
                        
            {
                            myDrawingMode 
            = value;
                        }

              }


             
             

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

            Browsable

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

            Category

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

            Description

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

            Bindable

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

            DefaultProperty

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

            DefaultValue

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

            Editor

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

            Localizable

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

            DesignerSerializationVisibility

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

            TypeConverter

            適用于屬性,指定將屬性的類型轉(zhuǎn)換為另一個數(shù)據(jù)類型時要使用的類型轉(zhuǎn)換器。

            DefaultEvent

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



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

            評論

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

            久久久久亚洲AV片无码下载蜜桃| 久久精品无码专区免费东京热| 99久久精品影院老鸭窝| 国产亚洲婷婷香蕉久久精品| www.久久热| 香蕉99久久国产综合精品宅男自 | 97久久久精品综合88久久| 99久久久精品免费观看国产| 97超级碰碰碰碰久久久久 | 亚洲av成人无码久久精品| 久久久婷婷五月亚洲97号色| 久久综合九色综合久99| 国内精品久久久久影院亚洲| avtt天堂网久久精品| 色综合久久天天综线观看| 久久久久久夜精品精品免费啦| 国内精品伊人久久久久影院对白| 久久国产免费直播| 品成人欧美大片久久国产欧美| 一本久道久久综合狠狠爱| 日本三级久久网| 精品久久久噜噜噜久久久| 思思久久99热免费精品6| 97久久超碰成人精品网站| 亚洲性久久久影院| 青青青国产精品国产精品久久久久| 久久精品国产亚洲av麻豆图片| 亚洲一区中文字幕久久| 新狼窝色AV性久久久久久| 久久精品国产男包| 久久综合一区二区无码| 国产精品99久久久久久宅男| 精品久久无码中文字幕| 亚洲精品乱码久久久久66| 久久无码国产| 久久久久国产精品麻豆AR影院| 国产69精品久久久久99尤物| 94久久国产乱子伦精品免费| 久久99国产精一区二区三区| 97久久久久人妻精品专区| 欧美激情精品久久久久|