.NET Compact Framework1.0下自定義控件的編寫3-小經驗與小技巧

 對庫的調試在將“屬性->配置屬性->調試->調試模式”改爲“程序”後,需點擊“應用”按鈕纔可以配置“啓動應用程序”等文本框。注意“命令行參數”中的路徑是字符串,需要用引號括起。

l         將某個項目(比如庫)設置爲啓動項目只要右擊某項目,即可直接選中。

l         System.Diagnostics.Debug.WriteLine

l         ComponentModel命名空間提供了編寫自定義控件時需要的整套特性,比如可以幫助修改組件在屬性瀏覽器中Category(如“行爲”、“外觀”)的特性,控制屬性在屬性瀏覽器中可見/不可見的特性,等等等等。

l         對DefaultProperty/DefaultEvent特性指定的默認屬性/事件,如果將屬性或事件拼寫錯誤,則會使用基類的默認屬性/事件。

l         如何屏蔽基類的屬性和事件?

將基類屬性重載後加上相應特性即可(如希望在屬性瀏覽器中不可見則加上“Browable”特性,如希望在智能感知時不可見加“EditBrowable”特性)。

l         “宿主窗體集成”一節的意思是:對HostingForm屬性,在設計期,設計器肯定會調用它的Getter,故可以利用這次機會,獲得只能在設計期獲得的宿主引用,保存後即可在運行期使用了。注意對於這種方法,調試時可能需要重新配置控件。

l         一旦窗體添加了一個實現了ISupportInitialize接口的組件,則窗體的InitializeComponent方法中將在首尾自動加入對該組件實現的ISupportInitialize接口中的BeginInit和EndInit方法的調用。(很可惜CF不支持ISupportInitialize接口)

l         自定義屬性,怎麼會出現了只能看不能編輯的情況?

原因可能是在CanConvertFrom函數中將sourceType錯判string外的其他類型。sourceType應該爲string類型。

l         OnPaintAdornments只在設計期被調用。

l         Custom tool屬性即選中某個文件後下方的屬性瀏覽器中的“高級->自定義工具”。

l         如果自定義控件的某個屬性是一個實現了ICollection接口的類型的實例,則使用該控件時,屬性瀏覽器顯示這個屬性時自動就有Collection對話框。注意Collection類的item對應的類型一定要實現一個默認ctor.。且如果要使該屬性支持窗體設計器的自動代碼生成,則必須爲該屬性添加 DesignerSerializationVisibility(DesignerSerializationVisibility.Content) 特性。

另外,如果是一個數組,則也會自動顯示一個類似的對話框。

l         EditorBrowable特性,用於控制智能感知時該屬性是否可見。

Browable特性,用於控制屬性在屬性瀏覽器中是否可見。

RefreshProperties特性,用於控制當屬性的值改變時屬性瀏覽器的行爲,例如當屬性值改變時引起屬性瀏覽器刷新等等。

Localizable特性,用於指定屬性是否本地化,當爲組件生成代碼時,該標記爲true的屬性及其值將保存在資源文件中。(?什麼意思,沒用過,還不是很明白!)

注意在完整版控件編寫中EditorBrowable特性和Browable特性經常同時使用,用於屏蔽基類中不需要的屬性,使它在屬性瀏覽器和智能感知時都不可見。但在CF中編寫控件中,要達到同樣的效果,往往是將他們分開使用,即將Browable特性施加於控件的設計期版本中的屬性,而EditorBrowable特性施加於控件的運行期版本中相應屬性。

l         如何屏蔽掉基類中的屬性或事件?

要屏蔽基類屬性或事件,只要override該屬性,然後爲其加上相應特性(EditorBrowable特性、Browable特性)即可。

另外,有時可能是希望使用一個與基類屬性同名,但卻有完全不同行爲的新屬性,這時的不是使用override,而是使用new。

l         若多個程序集中定義了相同的類C(類名相同、命名空間相同),而某個程序集A同時引用了這幾個程序集並且要使用類C,則A使用哪個程序集中的類C以添加引用時這幾個程序集的添加順序爲準,將使用先添加的那個程序集中的類C。(注意引用的多個程序集含有相同的類會引起編譯器警告,如需要消除警告,“項目屬性頁->配置屬性->生成->取消顯示特定警告”,填入1595)。

l         Control.PointToClient:將點的屏幕座標轉化爲客戶區座標

Control.PointToScreen:將點的客戶區座標轉換爲屏幕座標

l         如何創建一個類似於GroupBox這樣的容器控件:

使控件的設計器繼承自ParentControlDesigner即可。

l         FillRectangle(rect), rect=(0, 0, width,height)的效果:


即對於rect,只Fill圖中的紅色部分,不包括rect的右邊和下邊。例如,(0, 0, 1,10)的rect,如果DrawRectangle,則是相等於一條粗爲2的豎線,如果FillRectangle,則是一條粗爲1的豎線。

l         精簡版.NET下不支持ISupportInitialize接口,而有時對屬性Setter的調用次序又必須人爲控制,如何解決這個問題?

爲控件添加一個initializing私有變量,指示當前過程是否正在初始化。在每個屬性的Setter中,將那些與其他屬性(成員變量)的取值相關的代碼放在(!initializing)中,的確與其他屬性(成員變量)取值無關的代碼才直接放在Setter中。然後在適當的地方,比如OnPaint中,添加一段(initializing)代碼,在其中完成所有存在取值依賴的屬性(成員變量)的值的設置,在這段代碼的末尾將initializing設爲false,標誌初始化完成。

l         如何提供一個與基類屬性同名,卻有完全不同行爲(即不是通過重載)的屬性?

做法如下(以BackColor爲例):在設計期控件中,使用new關鍵字定義一個BackColor屬性,然後重載ShouldSerializeBackColor方法,最後在控件的ctor中爲BackColor設置一個默認值;在運行期控件中,在ctor中將BackColor設置爲相同的默認值。

以上做法可行的原因:在設計期,父窗體的BackColor如果改變,窗體設計器會檢查窗體上的所有子控件,如果控件的BackColor與之一致,說明它應該具有環境變量的行爲,這時窗體設計器就會引起控件BackColor的Setter被調用;如果子控件的BackColor與父窗體不一致,說明控件已經有了自己的BackColor,不應該再像環境變量一樣處理它了,所以此時BackColor的Setter不會再被調用了。但要注意的是一定要重載BackColor是ShouldSerialize函數,因爲窗體設計器看到的始終是基類的BackColor,而由於控件new掉了基類的BackColor,故窗體設計器看到的基類的BackColor始終與父窗體一致,所以它就不會爲改變了的BackColor生成代碼,而這樣的話,在運行期,將只能看到ctor中設置的BackColor的默認值。設計期和運行期行爲不一致。

l         如何使圓角後的背景顏色與父窗體一致?

使用父窗體的背景顏色填充控件的客戶區(FillRectangle(this.Parent.BackColor, ClientRectangle)),然後在利用控件自己的BackColor完成剩餘的圓角內的填充。

l         CF下如何填充一個Pie?

利用Graphics對象的Clip屬性,而CF支持FillEllipse,可以使用這個函數但將Clip屬性屬性只設置爲FillEllipse所Fill的Ellipse外接Rectangle的一部分,這樣就只看到Ellipse的一部分,即一個Pie。

l         如何混淆控件庫?(即Dotfuscator的使用):

1.  運行Dotfuscator,“選擇項目類型”選擇“創建新項目”,“確定”

2.  選擇“觸發器”屬性頁,“瀏覽”到目標程序集。

3.  選擇“重命名->排除”屬性頁,排除(即將其選中)所有類名、類中所有的ResetXxx、ShouldSerializeXxx函數、枚舉的所有枚舉值。

4.  選擇“生成”屬性頁,指定目標目錄,單擊“生成”

l         如何對控件庫加密(加殼)?

首先用VC6寫一個Dll,提供加密(加殼)核心函數;然後在控件庫工程之設計期庫中通過DllImport特性,將這個Dll提供的加密(加殼)函數導入

[DllImport(@”D:/Shellxxx.dll”)

public static extern bool DateShell();

並將這些函數封裝到一個專門提供加密(加殼)功能的類(不可繼承,不可實例化的類)中供需要加密(加殼)的類調用。

這樣的做法使破解者即使反編譯了控件庫的源代碼,發現了加殼機制,但由於加殼功能的核心實現是在VC6寫的Dll中,所以最後他還必須去破解這個Dll,而這個Dll由於是原生Win32程序,有許多現成的加密(加殼)工具可以使用。

l         如何製作庫的安裝文件?

首先創建一個.NET安裝項目,然後右擊“目標計算機上的文件系統->添加特殊文件夾”,選擇相應的文件夾添加,在文件夾下加入需要安裝的文件即可。

各文件夾的意義如下:

Program Files文件夾:即c:/ Program Files

System文件夾:即c:/ winnt/System32

Windows文件夾:即c:/ winnt

GAC文件夾:目標計算機的GAC文件夾

自定義文件夾:在“用戶界面”視圖中添加一個“文本框”,改動“文本框”的Edit1Property屬性,取一個有意義的名字,將這個名字賦給“自定義文件夾”的Property屬性。這樣就可以將“自定義文件夾”中添加的文件拷貝到安裝程序運行時客戶在“文本框”中輸入的路徑下了。

注意“文本框”的Edit1Value屬性是安裝程序運行時“文本框”顯示的初始路徑,故最好將其設置爲一個有意義的路徑;另外不要改動“自定義文件夾”的DefaultLocation屬性。

l         編程小技巧、小經驗:

1.  如果要將控件的客戶區等分爲若干等份,但由於Width和Height屬性都是整型變量,存在無法整除的情況,這樣就無法做得精確的等分了。如果必須保證等分的每一份相同,一個可行發方案如下:

Width = Width / Cols * Cols ;

Height = Height / Rows * Rows ;

  這樣就可以保證Width和Height一定是Cols和Rows的整倍數了。但注意一般不直接操作Width和Height這樣的屬性,而是將它們的值保存到某個局部變量中,然後去操作這些局部變量。

2.  控件的Size爲Width和Height,注意此時如另它的坐上角座標(0,0),則它的右下角座標是(Width-1,Height-1),而不是(Width,Height)

l         遺留的問題:

1.在CF中不知是否能提供UITypeEditor,如何提供?

2.是否能獲得GDI+的效果,如何獲得?

 

本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/yejun8214/archive/2008/03/24/2214764.aspx

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章