服务器之家

服务器之家 > 正文

Winform开发框架中如何使用DevExpress的内置图标资源

时间:2022-03-06 13:40     来源/作者:伍华聪

在开发winform程序界面的时候,我们往往会使用一些较好看的图表,以便能够为我们的程序界面增色,良好的图标设置可以让界面看起来更加美观舒服,而且也比较容易理解,图标我们可以通过一些网站获取各种场景的图标资源,不过本篇随笔主要介绍如何利用devexpress的内置图标资源来实现界面图标的设置。

1、设计时刻的图标处理

丰富的图标处理,在菜单、工具栏、树列表等地方,以及按钮等地方,都可以使用,而这些我们可以利用devexpress的内置图标选择来减轻我们寻找合适图标的烦恼。

Winform开发框架中如何使用DevExpress的内置图标资源

一些按钮、工具栏等的图标设置,一般是固定的,我们往往可以在设计时刻就指定它,这样我们可以使用本地的图标,也可以使用devexpress的内置图标。而使用devexpress内置图标资源的时候,我们可以调出devexpress的内置图标选择框的。

 如下是按钮添加图标方式,操作非常简单,在按钮的右上角小图标上单击一下进入编辑界面,如下所示。

Winform开发框架中如何使用DevExpress的内置图标资源

然后选择image按钮,进入图标选择界面,选择内置的devexpress图标库即可,基本上,只要是devexpress的原生控件,那么就可以通过这种内置图标的对话框进行图标选择,非常方便。

Winform开发框架中如何使用DevExpress的内置图标资源

 

2、运行时刻的图标处理

上面的操作是在设计时候,devexpress设计器给我们提供很多便利选择内置图标,而在界面运行时刻,想动态处理界面按钮图标,或者树形菜单的图标的时候,就没有这个直接的接口来设置图标了,而我们框架的菜单往往都是需用动态增加的,因此图标的设置也是在运行时刻的。如下面的树列表中,图标就是动态指定的。

Winform开发框架中如何使用DevExpress的内置图标资源

这些动态的树形菜单,是在权限系统里面动态配置的,菜单的配置界面如下所示。

Winform开发框架中如何使用DevExpress的内置图标资源

上面的选择图图标就是我们需要动态设置的图标,由于图标资源我们是以图片形式存储在对应的记录里面的,因此使用起来也是比较方便的,我们在配置的时候,获取到对应的图标资源并存储起来即可。

除了上面可以参考从devexpress内置图标资源获取图标的方式外

Winform开发框架中如何使用DevExpress的内置图标资源

我们还可以选择我们自己喜欢的图标资源,也就是从系统图标文件中选择自己喜欢的,如下界面所示。

Winform开发框架中如何使用DevExpress的内置图标资源

因此我考虑在运行时刻整合两种不同选择图标的方式。

我们先来看看我整合后的图表选择界面,如下所示,包含了运行时刻提取devexpress内置图标的功能和从系统文件中选择图标的功能。

Winform开发框架中如何使用DevExpress的内置图标资源

 

 3、运行时刻提取devexpress内置图标的功能实现

 首先我们参考设计时刻的界面展示

Winform开发框架中如何使用DevExpress的内置图标资源

来设计一个界面来展示图标信息

Winform开发框架中如何使用DevExpress的内置图标资源

 参考原版的界面,设计尽可能贴近即可,另外我们自己加入一个从系统选择图标资源的操作。

Winform开发框架中如何使用DevExpress的内置图标资源

至于图标选中后我们返回对应的image对象给调用者,则通过事件进行处理,以便选中后,即使更新显示效果。

如下所示,我们定义一个委托和事件。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/// <summary>
/// devexpress图标和系统图标选择窗体
/// </summary>
public partial class frmimagegallery : baseform
{
    /// <summary>
    /// 自定义一个委托处理图标选择
    /// </summary>
    public delegate void iconselecthandlerdelegate(image image, string name);
 
    /// <summary>
    /// 图标选择的事件
    /// </summary>
    public event iconselecthandlerdelegate oniconselected;
 
    private dximagegalleryloader loader = null;
 
    public frmimagegallery()
    {
        initializecomponent();
 
        initdictitem();//初始化
    }     
 
    /// <summary>
    /// 处理图标选择的事件触发
    /// </summary>
    public virtual void processiconselected(image image, string name)
    {
        if (oniconselected != null)
        {
            oniconselected(image, name);
        }
    }

然后在内置图标显示中,如果触发图标的单击,我们就触发事件,以便让调用者更新界面显示,如下代码所示。

?
1
2
3
4
5
6
7
8
foreach (galleryitem item in items[key])
{
    item.itemclick += (s, e) =>
    {
        //选择处理
        processiconselected(item.imageoptions.image, item.description);
    };
}

而对于从系统文件加载文件进行显示图标的,类似的触发方式。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/// <summary>
/// 从系统资源中加载图标文件,然后触发事件进行显示
/// </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);
    }
}

这样我们在菜单的选择图标的时候,就可以触发事件进行获取图表并更新自身了。

Winform开发框架中如何使用DevExpress的内置图标资源

?
1
2
3
4
5
6
7
8
9
private void btnselecticon_click(object sender, eventargs e)
{
    frmimagegallery dlg = new frmimagegallery();
    dlg.oniconselected += (image, name) =>
    {
        this.txtembedicon.image = image;
    };
    dlg.showdialog();
}

完成了这些处理,我们再次将焦点放在如何提取并展示devexpress内置图标的身上。

Winform开发框架中如何使用DevExpress的内置图标资源

 为了获取图表资源里面的分类及大小等信息,我们需要把图标资源进行一个加载出来,然后读取里面的类别和大小、集合等信息。先定义几个变量来承载这些信息。

?
1
2
3
4
5
6
7
8
9
10
11
12
/// <summary>
/// 图标分类
/// </summary>
public list<string> categories { get; set; }
/// <summary>
/// 图标集合
/// </summary>
public list<string> collection { get; set; }
/// <summary>
/// 图标尺寸
/// </summary>
public list<string> size { get; set; }

我们知道,devexpress的图标资源在程序集devexpress.utils.dximageassemblyutil.imageassembly里面,因此我们需要对它进行读取,并依次对各个资源进行处理。

我们来看看具体的处理代码,如下所示。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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);
                }
            }                       
        }
    }
}

其中读取资源的操作代码是

?
1
getresourcereader(devexpress.utils.dximageassemblyutil.imageassembly)

这个代码它就是从资源里面进行获取对应的图表资源。

?
1
2
3
4
5
6
7
8
9
10
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]));
}

另外,我们根据图表的文件名结构,我们通过正则表达式来读取它的对应信息,然后把它的大小、类别、集合信息存储起来。

?
1
2
3
4
5
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");

图表信息读取了,我们需要解析它然后存储起来,把图标的image对象放在一个字典类别里面,方便按照组别进行展示。

?
1
2
3
4
5
6
7
8
9
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);
    }
}

有了这些资源,我们对它们进行搜索就显得很方便了,我们如果需要根据文件名或者其他条件进行查询集合的数据,提供一个通用的方法即可,如下代码所示。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
/// <summary>
/// 根据条件获取集合
/// </summary>
/// <returns></returns>
public dictionary<string, galleryitemcollection> search(list<string> collection, list<string> categories,
    list<string> size, string filename = "")
{
    dictionary<string, galleryitemcollection> dict = new dictionary<string, galleryitemcollection>();
 
    galleryitemcollection list = new galleryitemcollection();
    foreach (var key in imagecollection.keys)
    {
        //使用正则表达式获取图标文件名中的集合、类别、大小等信息
        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 (!string.isnullorempty(filename))
        {
            if(key.contains(filename))
            {
                list.add(imagecollection[key]);
            }
            dict["查询结果"] = 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 进行搜索的了,不用再次读取程序集并依次分析它,速度提供不少的。

由于图表资源的处理是比较耗时的,我们把整个图标加载的类作为一个静态的对象缓存起来,这样下次使用直接从缓存里面拿,对应的资源也不用重新加载,更好的提高我们重用的效果了,体验更好了。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/// <summary>
/// 图标库加载处理
/// </summary>
public class dximagegalleryloader
{
    /// <summary>
    /// 图标字典类别集合
    /// </summary>
    public dictionary<string, galleryitem> imagecollection { get; set; }
    /// <summary>
    /// 图标分类
    /// </summary>
    public list<string> categories { get; set; }
    /// <summary>
    /// 图标集合
    /// </summary>
    public list<string> collection { get; set; }
    /// <summary>
    /// 图标尺寸
    /// </summary>
    public list<string> size { get; set; }
 
    /// <summary>
    /// 使用缓存处理,获得对象实例
    /// </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.getcacheitem<dximagegalleryloader>(keyname,
                   delegate () { return new dximagegalleryloader().loaddata(); },
                   new timespan(0, 30, 0));//30分钟过期
            return result;
        }
    }

以上代码通过

?
1
public static dximagegalleryloader default

定义了一个静态的实例属性,这样这个 dximagegalleryloader 实例只会在程序第一次使用的时候构建并加载图片资源,后续都是从缓存里面读取,提高响应速度的同时,也会记住上次的选择界面内容。

以上就是整个功能的处理思路,以及一步步的优化处理,以便实现功能展示的同时,也提高响应速度,最终界面就是我们开始的时候介绍的那样。

Winform开发框架中如何使用DevExpress的内置图标资源

 Winform开发框架中如何使用DevExpress的内置图标资源

单击或者选中系统图标后, 需要设置的按钮或者界面,就会及时更新图标展示,体验效果还是非常不错的。

由于这个界面功能的通用性,我把它作为系统界面基础模块,放到了我的框架baseuidx里面,各个系统模块都可以调用了。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对服务器之家的支持。

原文链接:https://www.cnblogs.com/wuhuacong/p/10095661.html

相关文章

热门资讯

2022年最旺的微信头像大全 微信头像2022年最新版图片
2022年最旺的微信头像大全 微信头像2022年最新版图片 2022-01-10
蜘蛛侠3英雄无归3正片免费播放 蜘蛛侠3在线观看免费高清完整
蜘蛛侠3英雄无归3正片免费播放 蜘蛛侠3在线观看免费高清完整 2021-08-24
背刺什么意思 网络词语背刺是什么梗
背刺什么意思 网络词语背刺是什么梗 2020-05-22
yue是什么意思 网络流行语yue了是什么梗
yue是什么意思 网络流行语yue了是什么梗 2020-10-11
2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全
2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全 2019-12-26
返回顶部