BS版图形系统 - 属性浏览器

C#bs 下的VML图形封装控件 这是一款VML编写的图形控件,支持VS2005,可以显示柱状、饼状、线状等各种图形格式,希望有所帮助!! 立即下载

BS版图形系统 - 属性浏览器


** QQ: 282397369 **

原理示教项目基本没跑,6月初确定动手。
两条线同时进展:管理系统和图形系统。
管理系统有正常前后端即可,图形系统还是主要的业务展示场合,一般的管理系统并不涵盖这些功能,所以干脆从头开发。

经过半个月的摸索尝试,最终选定TypeScript
作为图形工具,首先就要解决属性修改需求,即PropertyGrid。网上也有现成的PropertyGrid,但用起来代价太大,那就自己来做一个,也算是BS系统入个门。在以前用uniGUI的基础上,半个月跌跌撞撞,边做边发现,借鉴VCL的思路来实现TypeScript中的控件类库。当然,不会全搬VCL过来,太大,择其有用的就OK。

现在PropertyGrid的效果:
在这里插入图片描述
按VCL思路来实现,最终调用方式感觉也还是之前的效果,不过用多了,发现用vs code来开发,比C++效率还要高,更快。
唯一不爽的是,进行界面设计的时候,没有可视化界面,只能从实际效果中一点点找问题。

export class PropertyGrid extends TContainer {
    private tvPropertyItems: TTreeItem = new TTreeItem("DrGraphProperty");
    private selectedObjects: TObject[] = []
    private collapsedItems: string[] = ["Pen.Gradient", "Brush.Gradient"]
    cbAllObjects: TComboBox;
    gridPanel: TScrollBox;
    gridControl: TScrollPanel_Grid;

    txtEditor: TEdit;       
    cbEditor: TComboBox;  
    
    constructor(parent: TContainer | null) {
        super(parent);
        this.tvPropertyItems.collapsed = false;
        this.SetBounds(0, 0, 300, 500);
        this.cbAllObjects = new TComboBox(this);
        this.cbAllObjects.Align = NAlign.Top;
        this.cbAllObjects.EditStyle = NEditStyle.EmphasizeFirst;

        this.gridPanel = new TScrollBox(this);
        this.gridPanel.Align = NAlign.Client;
        this.gridPanel.horzScrollBar.Visible = false;  
        this.gridPanel.vertScrollBar.Visible = false;
        this.gridControl = new TScrollPanel_Grid(this.gridPanel); 
        this.gridControl.RowHeight = 30;
        this.gridPanel.AttachPanel(this.gridControl);

        this.cbAllObjects.Parent = this;
        this.cbAllObjects.AddEvent(NControlEvent.OnChange, this.onChangeSelectObject, this);  
        this.gridPanel.AddEvent(NControlEvent.OnCellClick, this.onCellClick, this);   

        this.txtEditor = new TEdit(this.gridControl);
        this.txtEditor.AllowDoDescendantFlag = false;  
        this.txtEditor.SetBounds(0, 0, 10, 10);
        this.txtEditor.Visible = false;
        this.txtEditor.AddEvent(NControlEvent.OnKillFocus, this.onAutoHideEditor, this);  

        this.cbEditor = new TComboBox(this.gridControl);
        this.cbEditor.AllowDoDescendantFlag = false;
        this.cbEditor.SetBounds(0, 0, 10, 10);
        this.cbEditor.Visible = false;
        this.cbEditor.AddEvent(NControlEvent.OnKillFocus, this.onAutoHideEditor, this); // 失去焦点即隐藏

        this.txtEditor.AddEvent(NControlEvent.OnChange, this.modifyPropertyValue, this);
        this.cbEditor.AddEvent(NControlEvent.OnChange, this.modifyPropertyValue, this);
        this.cbEditor.AddEvent(NControlEvent.OnDblClick, this.onDblClick_cbEditor, this);
    }

    private onAutoHideEditor(msg: TMessage) {
        this.txtEditor.Visible = false;
        this.cbEditor.Visible = false;
    }

    onCellClick(msgCell: TMessage_Cell) {  
        let treeItem: TTreeItem | null = null;
        let index: number = 0;
        [treeItem, index] = this.destPropertyItem(msgCell.row + 1, this.tvPropertyItems, index);
        this.tvPropertyItems.selected = treeItem;
        if (!treeItem)
            return;
        let propertyItem: TPropertyItem | null = <TPropertyItem>(treeItem.object); // treeItem >>> PropertyItem
        if (!propertyItem)
            return;
        if (msgCell.col == 0 && propertyItem.type == NProperty.Object) {
            treeItem.collapsed = !treeItem.collapsed;
            if (treeItem.collapsed) {
                if (this.collapsedItems.indexOf(treeItem.Path) == -1)
                    this.collapsedItems.push(treeItem.Path);
            }
            else {
                let index = this.collapsedItems.indexOf(treeItem.Path);
                if (index != -1)
                    this.collapsedItems.splice(index, 1);
            }
            this.RefreshDisplay();  
        } else if (msgCell.col == 2) { 
            let rect = msgCell.relRect; 
            let destEditor: TControl = this.txtEditor; 
            if (DrGraph.HelperObject.IS_IN_RANGE(propertyItem.type, NProperty.Boolean, NProperty.DateTime))
                destEditor = this.cbEditor;
            destEditor.SetBounds(rect.left, rect.top, rect.width, rect.height);
            destEditor.Visible = true;
            this.Root!.focusedControl = destEditor;

            if (destEditor == this.txtEditor) { 
                this.txtEditor.Text = propertyItem.value.toString();
                this.txtEditor.ReadOnly = (propertyItem.type == NProperty.Object);
                this.txtEditor.isDebugging = true;
            }

            if (destEditor == this.cbEditor) { 
                this.cbEditor.Text = propertyItem.value.toString();
                this.cbEditor.EditStyle = NEditStyle.Normal;
                this.cbEditor.listPanel.RowHeight = 30;
                this.cbEditor.choosePanel.vertScrollBar.Height = this.cbEditor.listPanel.Height;

                this.cbEditor.Items.Clear();
                if (propertyItem.type == NProperty.Boolean) {
                    this.cbEditor.Items.Add("true");
                    this.cbEditor.Items.Add("false");
                }
                if (propertyItem.type == NProperty.Enum) {
                    let enums = Object.getOwnPropertyNames(propertyItem.enumtype);
                    let len = enums.length;
                    enums.splice(0, len / 2);
                    enums.forEach((value) => { this.cbEditor.Items.Add(value); })
                    this.cbEditor.Text = propertyItem.enumtype[propertyItem.value];
                }
                if (propertyItem.type == NProperty.Color) {
                    this.cbEditor.EditStyle = NEditStyle.Color;
                    TColor.FillColorStrings(this.cbEditor.Items);
                }
            }
        }
    }

    onChangeSelectObject(eventInfo: TMessage) {
        let index = this.cbAllObjects.ItemIndex;
        let object = this.cbAllObjects.Items.ObjectAt(index);
        this.SelectObject(object);
    }

    onDblClick_cbEditor(eventInfo: TMessage) {
        this.cbEditor.ItemIndex = (this.cbEditor.ItemIndex + 1) % this.cbEditor.Items.Length;
        this.RefreshDisplay();
    }
    
    private buildPropertyItems(parentTvItem: TTreeItem, object: TObject | null) {
        if (object == null) return;
        let pItems: TPropertyItem[] = [];
        object.BuildPropertyList(pItems);
        pItems.forEach((item, idx) => {
            let subItem = parentTvItem.Add(item.name, item);
            if (item.type == NProperty.Object) {
                let subObject: TObject = <TObject>(item.value);
                this.buildPropertyItems(subItem, subObject);
            }
        })
    }

    AddObject(object: TObject) {  
        if (!object) return;
        let objectName = object.Name + " " + object.ClassName();
        this.cbAllObjects.Items.Add(objectName, object);
    }

    SelectObject(object: TObject | null) {
        if (!this.Visible) return;
        this.tvPropertyItems.Clear();
        this.selectedObjects = []
        if (object)
            this.selectedObjects.push(object);
        this.buildPropertyItems(this.tvPropertyItems, object);
        this.cbAllObjects.ItemIndex = this.cbAllObjects.Items.IndexOf(object);
        this.gridControl.Strings = []
        this.FillGrid(this.gridControl.Strings, this.gridControl.delimiter, this.tvPropertyItems);
        this.gridPanel.vertScrollBar.Max = this.gridControl.RowCount;
        this.gridPanel.RefreshScrollBar();
        this.txtEditor.Visible = false;
        this.cbEditor.Visible = false;
    }

    FillGrid(destStrings: string[], delimiter: string, parentTvItem: TTreeItem) {
        parentTvItem.items.forEach((item, idx) => {
            let level: number = item.Level - 1;
            let identation = "";
            for (let i = 0; i < level; ++i)
                identation += "  ";
            let propretyItem: TPropertyItem = <TPropertyItem>(item.object);
            let value = ((typeof propretyItem.value == "undefined") ? "" : propretyItem.value.toString());
            if (propretyItem.type == NProperty.Enum)
                value = propretyItem.enumtype[propretyItem.value];
            let pName = item.str;
            pName = propretyItem.description;
            if (propretyItem.type == NProperty.Color)
                pName += DrGraph.COLOR_SUFFIX;
            let str = delimiter + identation + pName + delimiter + value;
            if (propretyItem.type == NProperty.Object) {
                item.collapsed = item.collapsed || (this.collapsedItems.indexOf(item.Path) != -1);
                str = (item.collapsed ? "+" : "-") + str;
            }
            destStrings.push(str);

            if ((propretyItem.type == NProperty.Object) && (item.collapsed == false) &&
                this.collapsedItems.indexOf(item.Path) == -1)
                this.FillGrid(destStrings, delimiter, item);
        })
    }

    private destPropertyItem(row: number, currentTreeItem: TTreeItem, index: number): [TTreeItem | null, number] {
        let result: TTreeItem | null = null;
        if (currentTreeItem.collapsed == false) {
            currentTreeItem.items.forEach((item) => {
                let propretyItem: TPropertyItem = <TPropertyItem>(item.object);
                if (result == null && index < row) {
                    if (++index == row)
                        result = item;
                    else if (propretyItem && propretyItem.type == NProperty.Object && (item.collapsed == false)) {
                        [result, index] = this.destPropertyItem(row, item, index);
                    }
                }
            })
        }
        return [result, index];
    }

    modifyPropertyValue(e: TMessage_Change) {
        let propertyItem: TPropertyItem = this.tvPropertyItems.selected!.object;
        let destObject: TObject = propertyItem.object;
        let objectIndex = this.cbAllObjects.Items.IndexOf(destObject);
        if (propertyItem.name == "Name" && objectIndex != -1) {
            let index = -1;
            this.cbAllObjects.Items.items.forEach((item, idx) => {
                if (index == -1) {
                    let name = DrGraph.String.GetStringAt(item.str, " ");
                    if (name == e.currentValue)
                        index = idx;
                }
            })
            if (index != -1) {
                alert(`已有对象名为 ${e.currentValue}\n无法重命名,请检查确认!!!`);
                return;
            }
        }
        let currentValue = e.currentValue;
        if (propertyItem.type == NProperty.Enum) {
            let enums = Object.getOwnPropertyNames(propertyItem.enumtype);
            let len = enums.length;
            enums.splice(0, len / 2);
            let index = -1;
            enums.forEach((value, idx) => {
                if (index == -1 && value == e.currentValue)
                    index = idx;
            })
            currentValue = index;
        }
        destObject.ChangeProperty(propertyItem.name, currentValue);
      
        this.RefreshDisplay();
        if (propertyItem.name == "Name" && objectIndex != -1) {
            let originIndex = this.cbAllObjects.ItemIndex;
            if (originIndex != -1) {
                this.cbAllObjects.Items.items[originIndex].str = destObject.Name + " " + destObject.ClassName();
                this.cbAllObjects.ItemIndex = originIndex;
            }
        }
    }

    RefreshDisplay() {
        this.SelectObject(this.selectedObjects[0]);
    }
}

使用时,只需要创建一个PropertyGrid
propertyGrid: PropertyGrid = new PropertyGrid(this.objectManager);

然后,在生成新对象的时候,将其加入到propertyGrid中

    addChild(shape: any) {
        Array.isArray(shape) ?
            this.objects.push.apply(this.objects, shape) :
            this.objects.push.call(this.objects, shape);
        this.propertyGrid.AddObject(shape);
        return this;
    }

选择的时候,根据被选择对象情况确认一下,暂先处理单对象情况。

   DoSelectObjects() {
        if (this.selectedObjects.length == 1) {
            let propertyList: CustomTypes.TPropertyItem[] = []
            let selectObject = this.selectedObjects[0];
            this.propertyGrid.SelectObject(selectObject);
        } else
            this.propertyGrid.SelectObject(null);
    }

支持下一步开发足够,再边用边完善。

zedGraph(CS/BS图表控件) zedGraph(CS/BS图表控件) 程序例子<br/>你可以通过复制其中的代码使其运行在web页面上。 立即下载

相关推荐

医疗图像浏览器

Dicom图像浏览器C#源代码,可以浏览CT、DR、MR等设备产生的DICOM图像

什么是BS,BS和CS的区别有哪些:

BS即Browser/Server(浏览器/服务器)结构,就是只安装维护一个服务器(Server),而客户端采用浏览器(Browse)运行软件。B/S结构应用程序相对于传统的C/S结构应用程序是一个非常大的进步。 B/S结构的主要特点是分布性强、维护方便、开发简单且共享性强、总体拥有成本低。但数据安全性问题、对服务器要求过高、数据传输速度慢、软件的个性化特点明显降低,这些缺点是有目共睹的,难以实现...

weichaoer的博客 4万+

html5 bs画图工具

bs画图 ,在线绘图 支持html5

BS版图形系统 - OpenCV - 第4章笔记

BS版图形系统 - OpenCV - 第4章笔记4 深入研究直方图和滤波器4.1 技术要求4.2 生成CMake脚本文件4.3 创建图形用户界面4.4 绘制直方图4.5 图像颜色均衡4.6 Lomography效果4.7 卡通效果4.8 总结 QQ: 282397369 4 深入研究直方图和滤波器 4.1 技术要求 4.2 生成CMake脚本文件 4.3 创建图形用户界面 Show histogram Equalize histogram Lomography effect Cartoonize effe

drgraph的博客 220

Unity 数字孪生笔记1 工具介绍

前言 工欲善其事必先利其器 流程思考 数字孪生本质上一种基于实际物理数据的可视化方案,通过对接实际数据,在三维界面中展示孪生结果。 那么这个流程就很简单了。 整个流程分为三块:数据来源-》数据分析-》数据展示 输入数据 首先我们需要考虑我们能拿到什么。第一,实际物体的三维数据从哪里来,第二,实际数据怎么获取到。 模型数据 工业上常常会用到CAD模型,CAD模型具有精确、统一的特点,但是CAD不是三角面片,我们不能直接导出到Unity中,而且导入之后有很多不合理的地方,例如面片杂乱、面数过高等问题。针对这个

Thissky的专栏 1万+

SAP系统中PP模块全配置文档

配置路径IMG>SAP NetWeaver>常规设置>维护日历>工厂日历事务代码SCAL要求传输工厂代码描述日历代码日历描述起始日期星期一星期二星期三星期四星期五星期六星期日有效开始日期有效结束日期1000南微医学工厂MT南微医学工厂日历√√√√√√√201820502.4定义工厂配置路径IMG>生产>物料清单>常规数据>定义BOM状态事务代码OS23要求传输配置路径IMG>生产>主数据>资源>常规数据>标准值>定义参数。

yanzibing99的博客 1892

BS版图形系统 - 界面控件配置

BS版图形系统 - 界面控件配置界面控件考虑资源配置化XML资源配置加载下一步任务 QQ: 282397369 界面控件考虑 有了属性浏览器,下来就该处理工具栏了。 一个直观感觉,网页留给程序的空间,要比应用程序少。网页在浏览器这个程序中运行,不同的浏览器,提供相应的界面,占据标题、工具栏位置,甚至书签与侧栏。所以做网页程序的时候,尽量能将工作区整大一些。 当然,如何整应该是UI设计的事,技术层面还是关心如何实现的问题。 在属性浏览器的基础上,初步实现了一个VCL的JS框架。但新建控件,还是要写一堆代码来控

drgraph的博客 1270

CANoe/CANalyzer新手必看:从零配置到报文分析的完整流程(附B站官方教程实操)

本文为CANoe/CANalyzer新手提供从零配置到报文分析的完整流程指南,涵盖硬件连接、工程配置、报文捕获及信号级分析等关键步骤。通过详细的实操案例和B站官方教程,帮助工程师快速掌握汽车电子总线分析工具的核心应用,提升诊断效率与通信系统理解。

y7z8a的博客 771

R语言GPT结果可视化进阶之路(从入门到精通的7个关键步骤)

掌握R语言GPT结果可视化核心技巧,系统讲解从数据处理到动态图表生成的7个关键步骤。适用于科研分析、报告展示等场景,融合ggplot2与Shiny交互技术,提升数据表达力。方法实用高效,值得收藏。

codeink的博客 907

CCS20实战入门:第一个工程搭建示例

通过实际操作演示如何在ccs20中创建并配置首个开发项目,涵盖环境设置与基础调试步骤,帮助新手快速上手ccs20集成开发环境,提升嵌入式开发效率。

weixin_31185473的博客 884

解决Anaconda环境下catkin_make编译报错:Python路径冲突与empy模块缺失

本文详细分析了在Anaconda环境下使用catkin_make编译时出现的Python路径冲突与empy模块缺失问题,提供了快速解决方案和永久性环境配置方法。通过显式指定Python解释器路径或调整Anaconda配置,有效解决编译报错问题,适用于ROS开发与科学计算并行的场景。

weixin_28829629的博客 353

BS版图形系统 - 矩形

BS版图形系统 - 矩形 QQ: 282397369 Html5的Canvas,最基本的功能可以支持画矩形,其实也就那几个参数来回设置。 export class TRectangle extends TTwoPointMeta { cornerRadius: number = 0; // 圆角半径 Initial() { this.setClassType(CbwClassType.Rectangle); super.Initial(); }

drgraph的博客 389

CAPL实战:从零构建HEX文件解析器,赋能UDS刷写

本文详细介绍了如何使用CAPL从零构建HEX文件解析器,以支持UDS刷写操作。通过解析HEX文件格式、设计状态机、优化数据结构与算法,实现高效准确的固件数据处理,并提供了与UDS刷写流程对接的工程化实践建议。

weixin_28726391的博客 443

Webbrowser技巧

MSDN上关于WebBrowser控件使用方面的内容 http://msdn2.microsoft.com/zh-cn/library/w290k23d(VS.80).aspx 1. 获得浏览器信息:

godwiser的专栏 1029

【JCR一区级】鱼鹰算法OOA-CNN-LSTM-Attention故障诊断分类预测【含Matlab源码 5711期】

鱼鹰算法OOA-CNN-LSTM-Attention故障诊断分类预测 完整代码和数据,方可运行;数据可直接替换,适合小白!可提供运行操作视频!

订阅付费专栏Matlab(奶茶价版)或下载付费资源,可赠送奶茶价版付费专栏指定代码1份; 3601

《S32系列芯片——Boot & HSE详解》持续更新中...

专栏总目录,将详细介绍S32系列芯片的Boot功能,最终给出HSE基于IVT的Secure Boot方案!!!

车载系统攻城狮 4385

富客户端管理系统 - 原理示教

富客户端管理系统初探又一个起因技术思路 又一个起因 宅家也有好处。写了几篇博客,交了不少朋友。 机会也随之而来。因为在聊的过程中,真的会碰出火花。 这么多年,一直在做windows桌面应用程序开发,对网络管理系统[指用HTML、JavaScript、CSS…之类的技术展现网页]还不想涉猎,原因很简单,不想学,不愿学,老是感觉那些数据效果要来来回回的在客户端与服务端跑,累,慢。桌面应用程序就直观多了...

drgraph的博客 517

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

画图理解BS模式

XiaoZeng941101的博客 887

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

BS版图形系统 - 画线

BS版图形系统 - 画线 一晃两个月过去了,儿子也考了个喜欢的大学,重新,又稳定了下来。 我也重操旧业,编点小程序。时不时发个小博客,自娱自乐一下。 今天处理图元 - 线。 话不多说,直接上代码。 export class TLine extends TTwoPointMeta { beginArrow: TArrow = new TArrow; endArrow: TArrow = new TArrow; Initial() { this.setClassType(

drgraph的博客 774

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

bs和cs缩放图片

   以前写过这个内容,但是找不到了再写一次 由于cs和bs 显示图片原理不一样,所以不一样 (bs显示原理图片为生成图片输出到客户端,当然不包括客户端的绘图程序VML,SVG等,而cs程序界面本身就可以看作是一个画板) (bs显示图片除了image控件,直接输出http流也行,但是如果要用image控件,就必须依赖image.url也就是bs的image控件必须依赖一个存在的物理地址显示而不...

weixin_33744141的博客 132

js画图框架--mxgraph--入门

js画图框架--mxgraph--入门     备注:由于工作变动的原因,mxgraph文章没有及时更新,写的比较简陋,希望大家谅解。以后有时间了在更新。这些算是一个引子,希望大家有兴趣的朋友继续研究下去。 1. 下载     在http://www.mxgraph.com/mxgraph.html网站中,下边的Download Now 按钮下载。版本从mxgraph-1_0_0_0.z...

用技术点亮生命,用产品温暖人心,探讨coding真谛,感悟技术精神。 894
上一篇: 基于uniGUI进行人工辅助
下一篇: BS版图形系统 - 界面控件配置
DrGraph
博客等级 码龄14年 228粉丝 77原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值