上几张测试的 效果

虽然全是用.net 的绘图库画的,但是手动双缓冲,不会闪烁,感觉还不错,源码开放了,喜欢的拿去扩展吧;

用于撤销的存放图像的数据结构我设置为10个,怕是内存崩了,我看mspaint的内存占用一直很低啊,如有有比较棒的解决方案的话欢迎提出来分享分享

代码量短短300行





【2016.1.27】更新一下博文,因为扩展了一下,因为撤销功能放内存中实在是太耗资源了,我重新实现一种数据结构,这种数据结构同时兼容栈和队列的功能,栈大小固定,

压栈时会溢出,溢出的话从栈底抽走元素并返回,这样就可以在使用数据结构是把溢出的bitmap放到磁盘上

弹栈时如果有之前溢出的bitmap的话向栈底插入元素,把磁盘上的bitmap向栈底插入

这样的话控件既节省内存也不会因为磁盘的IO速度影响撤销功能导致界面卡顿

下面是这个数据结构的实现代码,为了节省代码,我不做成泛型了

 //_____________________________________________________________________________

        /*下面的stack and queue类是
         *
         * 一个兼容栈和队列的数据结构
         * 为了节省代码量,我没有设计成泛型
         * 设计这个数据结构为了节省空间在保留内存
         * 把纪录画纸保存在系统的临时目录下
         *
         *
         *
         * */
        /// <summary>
        /// 栈元素类
        /// </summary>
        internal class TElement
        {
            public TElement prev;
            public Bitmap i;
            public TElement next;

            internal TElement(TElement prev, Bitmap i, TElement next)
            {
                this.i = (Bitmap)i.Clone();
                this.prev = prev;
                this.next = next;
            }

        }

        internal class stack_and_queue
        {
            internal int size;
            ;
            ;
            private TElement head = null;
            private TElement tail = null;
            public stack_and_queue(int size)
            {
                ) size = ;
                this.size = size;
            }

            /// <summary>
            /// 压栈画纸
            /// </summary>
            /// <param name="x"></param>
            /// <returns></returns>
            public Bitmap Push(Bitmap x)
            {
                if (x == null) return null;
                TElement t = new TElement(tail, x, null);
                if (head == null)
                {
                    head = t;
                    tail = t;
                    allcount++;
                    count++;
                    return null;
                }
                else
                {
                    tail.next = t;
                    tail = t;
                    allcount++;
                    count++;
                    if (allcount > size)
                    {

                        Bitmap temp = head.i;
                        head.next.prev = null;
                        head = head.next;
                        count--;
                        return temp;
                    }
                }
                return null;
            }

            /// <summary>
            /// 弹栈画纸
            /// </summary>
            /// <param name="t"></param>
            /// <returns></returns>
            public Bitmap Pop(Bitmap t)
            {
                if (tail == null) return null;
                Bitmap temp = tail.i;
                if (head == tail)
                {
                    head = tail = null;
                    allcount--;
                    count--;
                }
                else
                {
                    tail = tail.prev;
                    tail.next = null;
                    allcount--;
                    count--;
                    if (t != null)
                    {
                        TElement tnew = new TElement(null, t, head);
                        head.prev = tnew;
                        head = tnew;
                        count++;
                    }
                }
                return temp;
            }

            /// <summary>
            /// 清空栈
            /// </summary>
            internal void clear()
            {
                TElement temp = head;
                while (temp != null)
                {
                    temp = head.next;
                    head.prev = null;
                    head.next = null;
                    head.i.Dispose();
                }
                head = null;
                tail = null;
            }
        }

这个是没有使用stack_and_queue数据结构实现撤销功能的控件的内存占用


下面这个是使用stack_and_queue数据结构的,在画的多的情况下内存占用依然比较低,栈的大小我设置为3

注明一下:

【里面的一个 把bitmap加载到内存,保证不占用文件的FileToBitmap方法的代码我是copy别人的

原帖地址http://blog.csdn.net/rztyfx/article/details/46674543

源码地址:http://pan.baidu.com/s/1eRwcflw

cs文件是控件源码

压缩文件是测试控件的demo文件

C#自定义控件 绘制框的更多相关文章

  1. (十六)c#Winform自定义控件-文本框哪里去了?-HZHControls

    官网 http://www.hzhcontrols.com 前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. GitHub:https://github.com/kww ...

  2. (六)c#Winform自定义控件-单选框

    前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. 开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control ...

  3. (二十八)c#Winform自定义控件-文本框(一)

    前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. 开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control ...

  4. (二十九)c#Winform自定义控件-文本框(二)

    前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. 开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control ...

  5. (三十)c#Winform自定义控件-文本框(三)

    前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. 开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control ...

  6. (三十一)c#Winform自定义控件-文本框(四)

    前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. 开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control ...

  7. (十八)c#Winform自定义控件-提示框

    前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. 开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control ...

  8. (八十二)c#Winform自定义控件-穿梭框

    前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. GitHub:https://github.com/kwwwvagaa/NetWinformControl 码云:ht ...

  9. c# 自定义控件-提示框(弹框)

    分带取消按钮和不带取消按钮的 调用方法: frmMessageBox frm = new frmMessageBox("提示", "数据连接失败,请重试!", ...

随机推荐

  1. centos7下只需两个命令升级php版本

    我的php5.4 升级到5.6 sudo yum clean allsudo yum install -y php56w Resolving Dependencies --> Running t ...

  2. twig 截取字符串

    <p>{{content|slice(0,100)}}</p> slice()截取content变量值,从0到100

  3. linux中添加PHP的mongoDB支持扩展

    最近使用ThinkPHP连接mongoDB数据库进行增删改查,在使用之前,需要PHP本身支持对mongoDB的连接,下面是我安装PHP的mongoDB扩展的方法 wget -c http://pecl ...

  4. 【LeetCode】:二叉搜索树

    相关概念: 一棵二叉搜索树(BST)是以一棵二叉树来组织的,可以用链表数据结构来表示,其中,每一个结点就是一个对象,一般地,包含数据内容key和指向孩子(也可能是父母)的指针属性.如果某个孩子结点不存 ...

  5. 【七】MongoDB管理之分片集群介绍

    分片是横跨多台主机存储数据记录的过程,它是MongoDB针对日益增长的数据需求而采用的解决方案.随着数据的快速增长,单台服务器已经无法满足读写高吞吐量的需求.分片通过水平扩展的方式解决了这个问题.通过 ...

  6. java入门了解13

    小知识点: 网络编程:主要解决计算机间数据传输 不需要html页面可以达到数据传输:QQ,微信 网页编程:继续Html页面基础上数据交互:OA,天猫... java方向:web方向,annrod常用S ...

  7. Sqoop- sqoop将mysql数据表导入到hive报错

    sqoop将mysql数据表导入到hive报错 [root@ip---- lib]# sqoop import --connect jdbc:mysql://54.223.175.12:3308/gx ...

  8. Linux下查看Python安装了哪些脚本模块

    Linux下查看Python安装了哪些脚本模块 1.什么是rpm ? rpm 即RedHat Package Management,是RedHat的发明之一 .现在包括OpenLinux.fedora ...

  9. 仿联想商城laravel实战---5、无刷新的增删改查(动态页面更新的三种方式(html))

    仿联想商城laravel实战---5.无刷新的增删改查(动态页面更新的三种方式(html)) 一.总结 一句话总结: 直接js增加删除修改html 控制器直接返回处理好的页面 用双向绑定插件比如vue ...

  10. cookie的默认有效目录

    php的setcookie是设置cookie操作的函数. 基本参数百度就有一堆答案.其中第四个参数是cookie的有效目录.这个参数是可选的,如果没有设置这个参数.默认 的有效范围是当前目录及其子目录 ...