• <label id="pxtpz"><meter id="pxtpz"></meter></label>
      1. <span id="pxtpz"><optgroup id="pxtpz"></optgroup></span>

        當前位置:雨林木風下載站 > 技術開發教程 > 詳細頁面

        為 Microsoft Visual Studio .NET 設計工具創建可設計式元件(轉貼)下

        為 Microsoft Visual Studio .NET 設計工具創建可設計式元件(轉貼)下

        更新時間:2022-04-27 文章作者:未知 信息來源:網絡 閱讀次數:

        以相同方式出入:透過程式碼保存元件
          不同於以往的設計工具,.Net Framework 元件的 Win Forms 與其它 VS .NET 設計工具,僅依賴表單狀態的程式碼保存性。沒有神奇的格式,也沒有隱藏資料,只是運作平穩的普通程式碼。當然,像點陣圖和本土化字串等,可以視為二進元資料與程式碼一起封裝,但元件狀態和元件所含內容,則必須透過程式碼來保存。在您設計工具的同時,也會產生程式碼。倘若您針對該程式碼進行處理,則會重新剖析,並且將變更內容反應在設計工具中。

        .Net Framework 的設計工具可提供所有配備以利用此功能。所有設計工具對於任何類型最希望得知的內容包括:

        有哪些關於物件狀態的資訊有助於保存性?

        如何將該類資訊以現行物件傳回?

        在先前的章節中,已經簡單討論過這個問題。再次聲明,TypeConverter 是處理的核心。產生程式碼和剖析程式碼設計工具,皆與名為 CreationBundle 的 PersistInfo 特定類型有關。例如:

        [TypeConverter(typeof(IntBoolString.IntBoolStringConverter))]
        public class IntBoolString {
        private int intVal;
        private string stringVal;
        private bool boolVal;

        public IntBoolString(string s, int I, bool b) {
        This.intVal = I;
        This.stringVal =s ;
        This.boolVal = b;
        }
        public bool Bool{
        get {return boolVal;}
        set {boolVal = value;}
        }

        public int Int {
        get {return intVal;}
        set {intVal = value;}
        }

        public string String {
        get {return stringVal;}
        set {stringVal = value;}
        }

        public override string ToString() {
        return intVal + "," + boolVal + "," + stringVal;
        }

        public class IntBoolStringConverter : TypeConverter {

        public override bool CanConvertFrom(
        ITypeDescriptorContext context,
        Type sourceType) {
        return (sourcetType == typeof(string));
        }

        public virtual object ConvertFrom(
        ITypeDescriptorContext context,
        object value,
        object[] arguments) {

        if (value is string) {
        string stringValue = (string)value;
        int intValue;
        bool boolValue;

        int commaIndex =
        stringValue.IndexOf(',');

        if (commaIndex != -1) {
        intValue = Int32.
        Parse(stringValue.
        Substring(0, commaIndex));
        commaIndex = stringValue.
        IndexOf(',',
        commaIndex + 1);
        if (commaIndex != -1) {
        int nextComma = stringValue.IndexOf(',', commaIndex + 1);
        if (nextComma != -1) {
        boolValue = Boolean.Parse(stringValue.Substring(commaIndex+1,
        nextComma - commaIndex));
        stringValue = stringValue.Substring(nextComma+1);
        return new IntBoolString(intVal, boolVal, stringValue);
        }

        }
        }
        throw new FormatException("Can't convert '" + stringValue + "' to IntBoolString Object");
        }
        }



        public override PersistInfo GetPersistInfo(ITypeDescriptorContext context, object value) {
        if (value is IntBoolString) {
        IntBoolString ibs = (IntBoolString)value;

        return new CreationBundle(typeof(IntBoolString), null,
        new CreationArgument[] {
        new CreationArgument(ibs.Int, typeof(Int32)),
        new CreationArgument(ibs.Bool, typeof(bool)),
        new CreationArgument(ibs.String, typeof(string))});
        }

        return base.GetPersistInfo(context, value);
        }
        }

        public override object CreateInstance(ITypeDescriptorContext
        context, IDictionary propertyValues) {
        return new IntBoolString((int)propertyValues["Int"],
        (bool)propertyValues["Bool"],
        (string)propertyValue["String"]);
        }

        public override bool GetCreateInstanceSupported(ITypeDescriptorContext context) {
        return true;
        }

        }


        使用 CreationBundle 物件的好處,在於這些物件若擁有符合傳入 CreationArgument 中各種類型的建構函式,就能夠得知用來儲存資訊的物件建立方式。在呼叫 TypeConverter::CreateInstance,並以此方式嘗試建立和初始設定物件時,TypeConverter 的預設實作會呼叫 CreationBundle::Invoke。倘若無可用的建構函式,則 CreateInstance 呼叫會採用 IDictionary,以允許物件製作更多自訂項目。傳入的 IDictionary 包含每個屬性名稱中不保存的值。

        元件的屬性值通常由多個物件所組成,其它架構通常就是為此目的而使用屬性陣列。然而,陣列卻有些缺點,例如,陣列必須在傳出時先行複製,於傳回時再次複製,結果當然大幅影響效能;在新增、修改或刪除值的時候,陣列也無法提供智慧型通知。事實上,如果屬性傳回陣列,是否新增或刪除項目就相當耗費工夫。陣列也是快照值,若基本物件不變更,就無法進行更新。

        反之,.Net Framework 在這種情況下,則使用實行 ICollection 物件的集合。物件可建立出集合並傳送給其它物件,同時參照項目可視基本物件的變更而保持最新狀態。若另一物件也針對集合進行變更,則亦將同時通知該物件。對於使用集合的 .Net Framework 設計工具,還需要支援含有 Get 和 Set 的 All 屬性,且其類型必須為集合可保留的物件陣列。例如:

        public class IntCollection : ICollection {
        private int[] values;

        public IntCollection(int[] intValues) {
        this.values = (int[])intValues.Clone();
        }

        public int[] All {
        get {
        return (int[])values.Clone();
        }
        set {
        values = (int[])value.Clone();
        }
        }

        public int Count {
        get {
        if (values == null) {
        return 0;
        }
        return values.Length;
        }
        }


        [Browsable(false)]
        public object SyncRoot {
        get {
        return this;
        }
        }

        [Browsable(false)]
        public bool IsReadOnly {
        get {
        return false;
        }
        }

        [Browsable(false)]
        public bool IsSynchronized {
        get {
        return true;
        }
        }
        }


        .Net Framework 的保存性機制,可保存或不保存本集合。若該集合由較先進的類型組成,如上述之 BoolIntString 範例類型,則需要利用與類型相關聯的 TypeConverter,為集合中每個項目建立有效的 PersistInfo (特別是 VS .NET 設計工具的 CreationBundle)。

        元件設計工具
          如之前所述,.Net Framework 中的內建設計工具,足以滿足元件的多數要求。不過,.Net Framework 還包括元件設計工具的完整擴充性架構。所有設計工具皆以 System.ComponentModel.Design.IDesigner 介面為基礎,列示如下:

        public interface IDesigner {

        // 與本設計工具相關的元件
        IComponent Component {get;}

        // 與元件相關的設計階段動作,
        // 如 TabControl 的「Add Tab」
        DesignerVerb[] Verbs {get;}

        // 處理設計工具所使用的任何資源。
        // 設計工具在本次呼叫後即無法使用。
        void Dispose();

        // 呼叫以要求設計工具執行「預設動作」。
        // 通常為了回應執行階段在元件上「連按兩下」
        // 動作而呼叫。
        void DoDefaultAction();

        // 以既定元件來初始設定設計工具。
        void Initialize(IComponent component);
        }


        不難看出,IDesigner 是相當直接的。設計工具透過 DesignerAttribute 與元件產生關聯:

        [Designer("MyNameSpace.Design.MyComponentDesigner, MyNameSpace.DLL")]
        Public class MyComponent : Component {
        }


        倘若 DesignerAttribute 未出現在類別中,則必須待找出設計工具位置後,才能夠跨越類別階層。在前述範例中,預設的 ComponentDesigner 可能位於元件基礎類別中,同時可供使用。有些設計工具會顯示出 UI,有些則不顯示。在 ComponentDesigner 中,由於元件通常沒有 UI,因此可以看到代表物件的圖示。另一方面,Win 表單控制項則有設計工具可於設計階段顯示出實際控制項。

        圖 3:設計階段的 Win 表單控制項

        請注意:位於設計工具下的圖示是未顯示 UI 的控制項;而顯示 UI 的 Win 表單控制項,則於執行階段顯示在表單設計工具中。然而不論顯示與否,這些控制項全數皆以 IDesigner 為基礎建立而成。控制項的設計工具通常會攔截設計中的控制項 WindowProc (來自System.WinForms.Design.ControlDesigner 的設計工具可以簡單地覆寫 WndProc 方法來完成),以執行諸如點擊測試等複雜的工作。然而,對於大部份元件而言,內建的預設設計工具應該已經足夠使用。

        使用設計工具服務與基礎架構
          在 VS .NET 中的 .Net Framework 設計工具,顯露出多樣化服務和基礎架構元件,可簡化複雜的作業或允許設計工具了解有關其它部份的狀態。這些服務永遠使用 GetServiceObject 方法透過 IServiceObjectProvider 進行存取。以下是部分特殊設計工具服務的清單:

        類型

         
        描述

        IDesignerHost
        與任何最上層設計工具相關的主要類別。可提供方法以增加服務、建立與放置元件、移除元件並進行批次作業。

        IComponentChangeService
        新增、移除、重新命名或修改元件時提供通知。

        ISelectionService
        設定或取得目前設計工具中選取的項目。

        IToolboxService
        允許在工具箱內查驗和修改項目及選項狀態等等。

        IUndoService
        提供配備以建立動作的復原/重做單位,並管理復原/重做堆疊。

        IHelpService
        允許設定說明主題或者叫用說明項目。

        IMenuCommandService
        允許處理設計工具功能表指令和動作。

        IReferenceService
        在設計工具中將參照內容對應到物件。例如,名稱 button1 對應到元件 button1 。



        IDesignerHost 是 VS .NET 中所有設計工具的基礎。IDesignerHost 亦為 IServiceObjectProvider,可利用動態方式新增和移除服務。它同時也提供建立元件的方法,以確保是否置於適當的位置。以下是使用 IDesignerHost 建立元件的範例:

        Public class MyDesigner : IDesigner {

        // ?.

        Private void OnSurfaceDoubleClick(object s, EventArgs e) {
        IDesignerHost host =
        (IDesignerHost)this.Component.Site.GetServiceObject(typeof(IDesignerHost));
        If (host != null) {
        Object newComponent = host.CreateComponent(typeof(MyComponent));
        DoSomethingInterestingWithComponent(newComponent);
        }
        }

        // ?}


        元件授權
          在擴充性的 .Net Framework 模型中,授權架構亦可同時擴充。為了方便使用,架構定義了一項內建的標準授權方法,以控制元件是否於設計使用階段獲得授權,不過研發人員可自由替換本機制。

        // 新增 LicenseProviderAttribute 到控制項。
        [LicenseProvider(typeof(LicFileLicenseProvider))]
        public class MyControl : RichControl {
        // 建立新的「空」授權。
        private License license = null;
        public MyControl () {
        // 使控制項的建構函式生效。
        license = LicenseManager.Validate(typeof(MyControl), this);
        // 是否執行其他範例工作? }
        public override void Dispose() {
        if (license != null) {
        license.Dispose();
        license = null;
        }
        }
        protected override void Finalize() {
        Dispose();
        base.Finalize();
        }
        }


        此範例可以使用內建授權支援來啟動授權工作。LicFileLicenseProvider 只要在類別的 Assembly 目錄中,尋找名為 <classname>.lic 的檔案,其中 classname 必須是完整的類型名稱。例如,對於 String 類型而言,名稱則為 System.String.lic。本檔案可包含字串「System.String 是已授權的元件」。若發現本檔案,LicenseManager.Validate 會傳回授權物件,並隨著類別實例來進行處置。

        實行您個人的授權機制也一樣輕鬆簡單。只要建立取自 LicenseProvider 的個人類別,並實行個人的 GetLicense 方法即可。您可以登錄為基礎實行授權機制,其中已授權的設計階段元件在登錄檔中有一個項目:

        public class RegistryLicenseProvider: LicenseProvider {
        public override License GetLicense(
        LicenseContext context,
        Type type,
        object instance,
        bool allowExceptions) {

        RegistryKey licenseKey = Registry.LocalMachine.
        OpenSubKey("Software\\MyCompany\\ComponentLicenses");

        if (context.UsageMode == LicenseUsageMode.Designtime) {
        if (licenseKey != null && licenseKey.GetValue(type.FullName) != null) {
        return new RegLicense(this, type);
        }
        if (allowExceptions) {
        throw new LicenseException(type, instance,
        "Couldn''t get design-time license for ''"" +
        type.FullName + "''");
        }
        return null;
        }
        else {
        return new RuntimeRegLicense(this, type);
        }
        }

        private class RuntimeRegLicense : License {
        public string LicenseKey {
        get {
        return type.FullName;
        }
        }
        public override void Dispose() {
        }


        }

        private class RegLicense : License {
        private RegistryLicenseProvider owner;
        private Type type;

        public RegLicense(RegistryLicenseProvider owner, Type type) {
        this.owner = owner;
        this.type = type;
        }

        public string LicenseKey {
        get {
        return type.FullName;
        }
        }
        public override void Dispose() {
        }
        }

        [LicenseProvider(typeof(RegistryLicenseProvider))]
        public class MyControl : Control {
        }


        使用本授權的元件在下列登錄檔中會有一個登錄項目:

        HKEY_LOCAL_MACHINE\Software\MyCompany\ComponentLicenses
        <Type full name>="true"


        結論
          在管理程式碼中撰寫控制項,可為傳統的 C++/COM 方法帶來更多的優勢。Microsoft 從最基本的通用語言執行階段開始策劃,遍及至 C# 甚至重組的 Visual Basic 語言,以提供研發人員效率最高的通用方法,將建構軟體時的阻礙降到最低。Microsoft .Net Framework 是第一個以這些技術和原理為基礎,所研發成功的大型程式碼庫範例,而支援的整合式設計工具,則是本方法成功的關鍵。

        溫馨提示:喜歡本站的話,請收藏一下本站!

        本類教程下載

        系統下載排行

        主站蜘蛛池模板: 一级毛片免费在线观看网站| 亚洲理论片在线中文字幕| 亚洲AV无码国产一区二区三区| 97性无码区免费| 亚洲va久久久久| 女性无套免费网站在线看| 亚洲伊人久久大香线蕉AV| 免费人成在线观看播放国产| 亚洲精品成人无限看| 久久亚洲日韩看片无码| 日韩人妻无码精品久久免费一| 亚洲一区中文字幕久久| 在线观看H网址免费入口| 亚洲国产日韩在线人成下载| A级毛片内射免费视频| 亚洲GV天堂GV无码男同 | 日韩视频在线精品视频免费观看| 666精品国产精品亚洲| 成年网站免费视频A在线双飞| 亚洲av日韩专区在线观看| 亚洲国产精品成人久久蜜臀| 中文字幕在线免费观看视频| 无码欧精品亚洲日韩一区| sss在线观看免费高清| 亚洲AV无一区二区三区久久| 免费观看无遮挡www的视频| 久久精品国产亚洲综合色| 99爱视频99爱在线观看免费| 亚洲一卡2卡3卡4卡乱码 在线 | 国产99精品一区二区三区免费| 亚洲小说区图片区另类春色| 免费看男女下面日出水来| 国产亚洲精品欧洲在线观看| 国产亚洲高清不卡在线观看| 成人无码区免费A片视频WWW| 一区在线免费观看| 亚洲欧洲尹人香蕉综合| 免费h黄肉动漫在线观看 | 成人在线免费观看| 久久精品国产亚洲AV蜜臀色欲| 免费一级毛片在播放视频|