WinForm應(yīng)用界面開發(fā)實(shí)戰(zhàn) - 如何使用DevExpress內(nèi)置圖標(biāo)資源?
在開發(fā)Winform程序界面的時(shí)候我們往往會(huì)使用一些較好看的圖表以便能夠?yàn)槌绦蚪缑嬖錾己玫膱D標(biāo)設(shè)置可以讓界面看起來更加美觀舒服而且也比較容易理解。圖標(biāo)我們可以通過一些網(wǎng)站獲取各種場景的資源不過本文主要介紹如何利用DevExpress的內(nèi)置圖標(biāo)資源來實(shí)現(xiàn)界面圖標(biāo)的設(shè)置。PS給大家推薦一個(gè)C#開發(fā)可以用到的界面組件——DevExpress WinForms它能完美構(gòu)建流暢、美觀且易于使用的應(yīng)用程序無論是Office風(fēng)格的界面還是分析處理大批量的業(yè)務(wù)數(shù)據(jù)它都能輕松勝任DevExpress新舊版本幫助文檔下載可進(jìn)QQ qun獲取169725316一、設(shè)計(jì)時(shí)的圖標(biāo)處理豐富的圖標(biāo)處理在菜單、工具欄、樹列表等地方以及按鈕等地方都可以使用而這些我們可以利用DevExpress的內(nèi)置圖標(biāo)選擇來減輕我們尋找合適圖標(biāo)的煩惱。一些按鈕、工具欄等的圖標(biāo)設(shè)置一般是固定的往往可以在設(shè)計(jì)時(shí)刻就指定它這樣我們可以使用本地的圖標(biāo)也可以使用DevExpresss的內(nèi)置圖標(biāo)。而使用DevExpress內(nèi)置圖標(biāo)資源的時(shí)候可以調(diào)出DevExpress的內(nèi)置圖標(biāo)選擇框的。如下是按鈕添加圖標(biāo)方式操作非常簡單在按鈕的右上角小圖標(biāo)上單擊一下進(jìn)入編輯界面如下所示。然后選擇Image按鈕進(jìn)入圖標(biāo)選擇界面選擇內(nèi)置的DevExpress圖標(biāo)庫即可基本上只要是DevExpress的原生控件那么就可以通過這種內(nèi)置圖標(biāo)的對話框進(jìn)行圖標(biāo)選擇非常方便。二、運(yùn)行時(shí)的圖標(biāo)處理上面的操作是在設(shè)計(jì)時(shí)DevExpress設(shè)計(jì)器給我們提供很多便利選擇內(nèi)置圖標(biāo)而在界面運(yùn)行時(shí)想動(dòng)態(tài)處理界面按鈕圖標(biāo)或者樹形菜單的圖標(biāo)的時(shí)候就沒有這個(gè)直接的接口來設(shè)置圖標(biāo)了而我們框架的菜單往往都是需用動(dòng)態(tài)增加的因此圖標(biāo)的設(shè)置也是在運(yùn)行時(shí)的。如下面的樹列表中圖標(biāo)就是動(dòng)態(tài)指定的。這些動(dòng)態(tài)的樹形菜單是在權(quán)限系統(tǒng)里面動(dòng)態(tài)配置的菜單的配置界面如下所示。上面的選擇圖圖標(biāo)就是我們需要?jiǎng)討B(tài)設(shè)置的圖標(biāo)由于圖標(biāo)資源是以圖片形式存儲(chǔ)在對應(yīng)的記錄里面的因此使用起來也是比較方便的。我們在配置的時(shí)候獲取到對應(yīng)的圖標(biāo)資源并存儲(chǔ)起來即可。除了上面可以參考從DevExpress內(nèi)置圖標(biāo)資源獲取圖標(biāo)的方式外。我們還可以選擇自己喜歡的圖標(biāo)資源也就是從系統(tǒng)圖標(biāo)文件中選擇自己喜歡的如下界面所示。因此考慮在運(yùn)行時(shí)整合兩種不同選擇圖標(biāo)的方式。我們先來看看整合后的圖表選擇界面如下所示包含了運(yùn)行時(shí)刻提取DevExpress內(nèi)置圖標(biāo)的功能和從系統(tǒng)文件中選擇圖標(biāo)的功能。三、運(yùn)行時(shí)提取DevExpress內(nèi)置圖標(biāo)的功能實(shí)現(xiàn)首先我們參考設(shè)計(jì)時(shí)的界面展示來設(shè)計(jì)一個(gè)界面來展示圖標(biāo)信息參考原版的界面設(shè)計(jì)盡可能貼近即可另外我們自己加入一個(gè)從系統(tǒng)選擇圖標(biāo)資源的操作。至于圖標(biāo)選中后我們返回對應(yīng)的Image對象給調(diào)用者則通過事件進(jìn)行處理以便選中后即使更新顯示效果。如下所示我們定義一個(gè)委托和事件。/// summary /// DevExpress圖標(biāo)和系統(tǒng)圖標(biāo)選擇窗體 /// /summary public partial class FrmImageGallery : BaseForm { /// summary /// 自定義一個(gè)委托處理圖標(biāo)選擇 /// /summary public delegate void IconSelectHandlerDelegate(Image image, string name); /// summary /// 圖標(biāo)選擇的事件 /// /summary public event IconSelectHandlerDelegate OnIconSelected; private DXImageGalleryLoader loader null; public FrmImageGallery() { InitializeComponent(); InitDictItem();//初始化 } /// summary /// 處理圖標(biāo)選擇的事件觸發(fā) /// /summary public virtual void ProcessIconSelected(Image image, string name) { if (OnIconSelected ! null) { OnIconSelected(image, name); } }然后在內(nèi)置圖標(biāo)顯示中如果觸發(fā)圖標(biāo)的單擊我們就觸發(fā)事件以便讓調(diào)用者更新界面顯示如下代碼所示。foreach (GalleryItem item in items[key]) { item.ItemClick (s, e) { //選擇處理 ProcessIconSelected(item.ImageOptions.Image, item.Description); }; }而對于從系統(tǒng)文件加載文件進(jìn)行顯示圖標(biāo)的類似的觸發(fā)方式。/// summary /// 從系統(tǒng)資源中加載圖標(biāo)文件然后觸發(fā)事件進(jìn)行顯示 /// /summary private void txtFilePath_Properties_ButtonClick(object sender, ButtonPressedEventArgs e) { string file GetIconPath(); if (!string.IsNullOrEmpty(file)) { this.txtFilePath.Text file;//記錄文件名 this.txtEmbedIcon.Image LoadIcon(file);//顯示圖片 this.txtEmbedIcon.Size new System.Drawing.Size(64, 64); //返回處理 ProcessIconSelected(this.txtEmbedIcon.Image, file); } }這樣我們在菜單的選擇圖標(biāo)的時(shí)候就可以觸發(fā)事件進(jìn)行獲取圖表并更新自身了。private void btnSelectIcon_Click(object sender, EventArgs e) { FrmImageGallery dlg new FrmImageGallery(); dlg.OnIconSelected (image, name) { this.txtEmbedIcon.Image image; }; dlg.ShowDialog(); }完成了這些處理我們再次將焦點(diǎn)放在如何提取并展示DevExpress內(nèi)置圖標(biāo)的身上。為了獲取圖表資源里面的分類及大小等信息我們需要把圖標(biāo)資源進(jìn)行一個(gè)加載出來然后讀取里面的類別和大小、集合等信息。先定義幾個(gè)變量來承載這些信息。/// summary /// 圖標(biāo)分類 /// /summary public Liststring Categories { get; set; } /// summary /// 圖標(biāo)集合 /// /summary public Liststring Collection { get; set; } /// summary /// 圖標(biāo)尺寸 /// /summary public Liststring Size { get; set; }DevExpress的圖標(biāo)資源在程序集DevExpress.Utils.DxImageAssemblyUtil.ImageAssembly里面因此我們需要對它進(jìn)行讀取并依次對各個(gè)資源進(jìn)行處理。來看看具體的處理代碼如下所示。using (System.Resources.ResourceReader reader GetResourceReader(DevExpress.Utils.DxImageAssemblyUtil.ImageAssembly)) { System.Collections.IDictionaryEnumerator dict reader.GetEnumerator(); while (dict.MoveNext()) { string key (string)dict.Key as string; if (!DevExpress.Utils.DxImageAssemblyUtil.ImageProvider.IsBrowsable(key)) continue; if (key.EndsWith(.png, StringComparison.Ordinal)) { string reg (?collection\S*?)/(?category\S*?)/(?name\S*); var collectionItem CRegex.GetText(key, reg, collection); var categoryItem CRegex.GetText(key, reg, category); string sizeReg _(?size\S*)\.; var sizeItem CRegex.GetText(key, sizeReg, size); if (!this.Collection.Contains(collectionItem)) { this.Collection.Add(collectionItem); } if (!this.Categories.Contains(categoryItem)) { this.Categories.Add(categoryItem); } if (!this.Size.Contains(sizeItem)) { this.Size.Add(sizeItem); } Image image GetImageFromStream((System.IO.Stream)dict.Value); if (image ! null) { var item new DevExpress.XtraBars.Ribbon.GalleryItem(image, key, key); if (!ImageCollection.ContainsKey(key)) { ImageCollection.Add(key, item); } } } } }其中讀取資源的操作代碼是GetResourceReader(DevExpress.Utils.DxImageAssemblyUtil.ImageAssembly)這個(gè)代碼它就是從資源里面進(jìn)行獲取對應(yīng)的圖表資源。private System.Resources.ResourceReader GetResourceReader(System.Reflection.Assembly imagesAssembly) { var resources imagesAssembly.GetManifestResourceNames(); var imageResources Array.FindAll(resources, resourceName resourceName.EndsWith(.resources)); if (imageResources.Length ! 1) { throw new Exception(讀取異常); } return new System.Resources.ResourceReader(imagesAssembly.GetManifestResourceStream(imageResources[0])); }另外根據(jù)圖表的文件名結(jié)構(gòu)我們通過正則表達(dá)式來讀取它的對應(yīng)信息然后把它的大小、類別、集合信息存儲(chǔ)起來。string reg (?collection\S*?)/(?category\S*?)/(?name\S*); var collectionItem CRegex.GetText(key, reg, collection); var categoryItem CRegex.GetText(key, reg, category); string sizeReg _(?size\S*)\.; var sizeItem CRegex.GetText(key, sizeReg, size);圖表信息讀取了我們需要解析它然后存儲(chǔ)起來把圖標(biāo)的Image對象放在一個(gè)字典類別里面方便按照組別進(jìn)行展示。Image image GetImageFromStream((System.IO.Stream)dict.Value); if (image ! null) { var item new DevExpress.XtraBars.Ribbon.GalleryItem(image, key, key); if (!ImageCollection.ContainsKey(key)) { ImageCollection.Add(key, item); } }有了這些資源我們對它們進(jìn)行搜索就顯得很方便了如果需要根據(jù)文件名或者其他條件進(jìn)行查詢集合的數(shù)據(jù)提供一個(gè)通用的方法即可如下代碼所示。/// summary /// 根據(jù)條件獲取集合 /// /summary /// returns/returns public Dictionarystring, GalleryItemCollection Search(Liststring collection, Liststring categories, Liststring size, string fileName ) { Dictionarystring, GalleryItemCollection dict new Dictionarystring, GalleryItemCollection(); GalleryItemCollection list new GalleryItemCollection(); foreach (var key in ImageCollection.Keys) { //使用正則表達(dá)式獲取圖標(biāo)文件名中的集合、類別、大小等信息 string reg (?collection\S*?)/(?category\S*?)/(?name\S*); var collectionItem CRegex.GetText(key, reg, collection); var categoryItem CRegex.GetText(key, reg, category); string sizeReg _(?size\S*)\.; var sizeItem CRegex.GetText(key, sizeReg, size); //如果是查詢處理把記錄放到查詢結(jié)果里面 if (!string.IsNullOrEmpty(fileName)) { if(key.Contains(fileName)) { list.Add(ImageCollection[key]); } dict[查詢結(jié)果] list; } else { //如果是集合和列表中包含的把它們按類別添加到字典里面 if (collection.Contains(collectionItem) categories.Contains(categoryItem) size.Contains(sizeItem)) { if (!dict.ContainsKey(categoryItem)) { GalleryItemCollection cateList new GalleryItemCollection(); cateList.Add(ImageCollection[key]); dict[categoryItem] cateList; } else { GalleryItemCollection cateList dict[categoryItem]; cateList.Add(ImageCollection[key]); } } } } return dict; }這次搜索就直接基于已有的集合ImageCollection 進(jìn)行搜索的了不用再次讀取程序集并依次分析它速度提供不少的。由于圖表資源的處理是比較耗時(shí)的我們把整個(gè)圖標(biāo)加載的類作為一個(gè)靜態(tài)的對象緩存起來這樣下次使用直接從緩存里面拿對應(yīng)的資源也不用重新加載更好的提高重用的效果了體驗(yàn)更好了。/// summary /// 圖標(biāo)庫加載處理 /// /summary public class DXImageGalleryLoader { /// summary /// 圖標(biāo)字典類別集合 /// /summary public Dictionarystring, GalleryItem ImageCollection { get; set; } /// summary /// 圖標(biāo)分類 /// /summary public Liststring Categories { get; set; } /// summary /// 圖標(biāo)集合 /// /summary public Liststring Collection { get; set; } /// summary /// 圖標(biāo)尺寸 /// /summary public Liststring Size { get; set; } /// summary /// 使用緩存處理獲得對象實(shí)例 /// /summary public static DXImageGalleryLoader Default { get { System.Reflection.MethodBase method System.Reflection.MethodBase.GetCurrentMethod(); string keyName string.Format({0}-{1}, method.DeclaringType.FullName, method.Name); var result MemoryCacheHelper.GetCacheItemDXImageGalleryLoader(keyName, delegate () { return new DXImageGalleryLoader().LoadData(); }, new TimeSpan(0, 30, 0));//30分鐘過期 return result; } }以上代碼通過public static DXImageGalleryLoader Default定義了一個(gè)靜態(tài)的實(shí)例屬性這樣這個(gè) DXImageGalleryLoader 實(shí)例只會(huì)在程序第一次使用的時(shí)候構(gòu)建并加載圖片資源后續(xù)都是從緩存里面讀取提高響應(yīng)速度的同時(shí)也會(huì)記住上次的選擇界面內(nèi)容。以上就是整個(gè)功能的處理思路以及一步步的優(yōu)化處理以便實(shí)現(xiàn)功能展示的同時(shí)也提高響應(yīng)速度最終界面就是我們開始的時(shí)候介紹的那樣。單擊或者選中系統(tǒng)圖標(biāo)后 需要設(shè)置的按鈕或者界面就會(huì)及時(shí)更新圖標(biāo)展示體驗(yàn)效果還是非常不錯(cuò)的。由于這個(gè)界面功能的通用性我把它作為系統(tǒng)界面基礎(chǔ)模塊放到了我的框架BaseUIDx里面各個(gè)系統(tǒng)模塊都可以調(diào)用了。本文轉(zhuǎn)載自博客園 - 伍華聰

相關(guān)新聞

TrafficMonitor插件架構(gòu)設(shè)計(jì)與多場景應(yīng)用實(shí)踐

TrafficMonitor插件架構(gòu)設(shè)計(jì)與多場景應(yīng)用實(shí)踐

TrafficMonitor插件架構(gòu)設(shè)計(jì)與多場景應(yīng)用實(shí)踐 【免費(fèi)下載鏈接】TrafficMonitorPlugins 用于TrafficMonitor的插件 項(xiàng)目地址: https://gitcode.com/gh_mirrors/tr/TrafficMonitorPlugins 插件化系統(tǒng)架構(gòu)的技術(shù)實(shí)現(xiàn)原理 TrafficMonitor插件系統(tǒng)采用模塊化設(shè)計(jì)理念&#x…

2026/8/1 19:31:51 閱讀更多
現(xiàn)在不學(xué)可靈畫質(zhì)增強(qiáng),半年后會(huì)被淘汰!AI視頻增強(qiáng)領(lǐng)域正在發(fā)生的3次范式遷移,附2024Q3最新SDK適配方案

現(xiàn)在不學(xué)可靈畫質(zhì)增強(qiáng),半年后會(huì)被淘汰!AI視頻增強(qiáng)領(lǐng)域正在發(fā)生的3次范式遷移,附2024Q3最新SDK適配方案

更多請點(diǎn)擊: https://codechina.net 第一章:可靈畫質(zhì)增強(qiáng)方法的演進(jìn)邏輯與行業(yè)定位 可靈(Kling)作為新一代AI視頻生成與增強(qiáng)平臺(tái),其畫質(zhì)增強(qiáng)方法并非孤立演進(jìn),而是深度耦合于計(jì)算視覺、生成式建模與邊緣部…

2026/8/1 19:31:51 閱讀更多
emlearn API完全參考:C與Python接口使用指南

emlearn API完全參考:C與Python接口使用指南

emlearn API完全參考:C與Python接口使用指南 【免費(fèi)下載鏈接】emlearn Machine Learning inference engine for Microcontrollers and Embedded devices 項(xiàng)目地址: https://gitcode.com/gh_mirrors/em/emlearn emlearn是一款專為微控制器和嵌入式設(shè)備設(shè)計(jì)的機(jī)…

2026/8/1 20:32:50 閱讀更多
阿里云rds,誤刪數(shù)據(jù)后,如何找回

阿里云rds,誤刪數(shù)據(jù)后,如何找回

教訓(xùn):一定要備份,一定要備份,一定要備份!我在晚上20點(diǎn)的時(shí)候,操作了刪除重復(fù)數(shù)據(jù),指引說要備份。我還嫌麻煩,沒有備份。幸好,阿里云提供了很好的工具,可以恢復(fù)到指定時(shí)間點(diǎn)的數(shù)據(jù)。還…

2026/8/1 20:32:50 閱讀更多
模塊化AI編程助手架構(gòu):基于上下文聚合與協(xié)議擴(kuò)展的智能編碼系統(tǒng)解析

模塊化AI編程助手架構(gòu):基于上下文聚合與協(xié)議擴(kuò)展的智能編碼系統(tǒng)解析

模塊化AI編程助手架構(gòu):基于上下文聚合與協(xié)議擴(kuò)展的智能編碼系統(tǒng)解析 【免費(fèi)下載鏈接】continue open-source coding agent 項(xiàng)目地址: https://gitcode.com/GitHub_Trending/co/continue Continue作為開源AI編程助手,其核心創(chuàng)新在于構(gòu)建了一個(gè)基于…

2026/8/1 20:32:50 閱讀更多
AMAT 0100-02186 I/O 分配 PCB

AMAT 0100-02186 I/O 分配 PCB

AMAT 0100-02186 I/O分配PCB板是應(yīng)用材料(Applied Materials)公司生產(chǎn)的一款用于半導(dǎo)體設(shè)備的I/O信號(hào)分配電路板。該型號(hào)(0100-02186)的核心特點(diǎn)如下:專用于Endura等半導(dǎo)體工藝腔室。集成信號(hào)路由與分配功能。連接控制…

2026/8/1 0:09:33 閱讀更多
Nissei Corp FFMN-32L-10-T0 40AX 三相異步電動(dòng)機(jī)

Nissei Corp FFMN-32L-10-T0 40AX 三相異步電動(dòng)機(jī)

Nissei Corp FFMN-32L-10-T0 40AX 三相異步電動(dòng)機(jī)是日本日清(Nissei)品牌的一款工業(yè)用三相異步電機(jī),適用于自動(dòng)化設(shè)備及通用機(jī)械驅(qū)動(dòng)。該型號(hào)(FFMN-32L-10-T0 40AX)的核心特點(diǎn)如下:三相交流異步電動(dòng)機(jī)。額定…

2026/8/1 0:09:33 閱讀更多
AMAT 0100-02186 I/O 分配 PCB

AMAT 0100-02186 I/O 分配 PCB

AMAT 0100-02186 I/O分配PCB板是應(yīng)用材料(Applied Materials)公司生產(chǎn)的一款用于半導(dǎo)體設(shè)備的I/O信號(hào)分配電路板。該型號(hào)(0100-02186)的核心特點(diǎn)如下:專用于Endura等半導(dǎo)體工藝腔室。集成信號(hào)路由與分配功能。連接控制…

2026/8/1 0:09:33 閱讀更多
Nissei Corp FFMN-32L-10-T0 40AX 三相異步電動(dòng)機(jī)

Nissei Corp FFMN-32L-10-T0 40AX 三相異步電動(dòng)機(jī)

Nissei Corp FFMN-32L-10-T0 40AX 三相異步電動(dòng)機(jī)是日本日清(Nissei)品牌的一款工業(yè)用三相異步電機(jī),適用于自動(dòng)化設(shè)備及通用機(jī)械驅(qū)動(dòng)。該型號(hào)(FFMN-32L-10-T0 40AX)的核心特點(diǎn)如下:三相交流異步電動(dòng)機(jī)。額定…

2026/8/1 0:09:33 閱讀更多