利用XtraDiagram.DiagramControl進行流程圖形的繪製和控制

来源:https://www.cnblogs.com/wuhuacong/archive/2022/06/23/16404257.html
-Advertisement-
Play Games

DevExpress提供了一個比較強大的圖形繪製工具,可以用於繪製各種圖形,如流程圖、組織機構圖等等,本篇隨筆介紹XtraDiagram.DiagramControl的使用,以及利用代碼對其屬性進行控制,以及利用圖形模具的自定義操作,實現一些簡單流程圖形的繪製和處理。 ...


DevExpress提供了一個比較強大的圖形繪製工具,可以用於繪製各種圖形,如流程圖、組織機構圖等等,本篇隨筆介紹XtraDiagram.DiagramControl的使用,以及利用代碼對其屬性進行控制,以及利用圖形模具的自定義操作,實現一些簡單流程圖形的繪製和處理。

DiagramControl是類似Visio的繪圖控制項,以前我2006年的就接觸使用Visio的二次開發,當時開始還是利用VB6 + VIsio2003進行二次開發的,後來把它改良為C# + Visio進行二次開發,DiagramControl的對象模型很類似Visio的相關對象模型,如對於工具欄的形狀,稱之為模具(Stencil),Visio也是稱之為Stencil, DiagramControl裡面的很多介面名稱依舊採用Stencil進行命名,因此估計也是借鑒了很多Visio的對象設計知識,如果您對Visio二次開發感興趣,可以參考我的隨筆文章《Visio二次開發》,裡面有很多相關的內容。

而如果想瞭解這個控制項的相關知識和使用,參考官網的案例和說明應該是比較好的教程(https://docs.devexpress.com/WindowsForms/118290/controls-and-libraries/diagrams/getting-started )。

1、DiagramControl控制項的使用

DiagramControl是一個界面控制項,類似Visio SDK裡面的DrawingControl的存在,可以通過它進行圖形的繪製,各種視窗的顯示和隱藏,以及跟蹤各種事件的處理。

DiagramControl控制項拖動到窗體中後,會自動增加一些屬性視窗,上排的繪圖工具中的按鈕是我添加的,用來測試該控制項的一些屬性的控制。

 

1)屬性視窗的顯示和隱藏(摺疊)

這個通過控制diagramControl1.OptionsView.PropertiesPanelVisibility 屬性就可以實現對這個屬性視窗的控制了。

 裡面顯示一些系統位置和內容信息,以及一些自定義信息的視窗,後面我會介紹如何自定義處理這些模具的屬性。

通過按鈕處理的代碼,我們可以實現對這個視窗的顯示或者隱藏處理。

//切換屬性視窗的顯示或關閉
var status = diagramControl1.OptionsView.PropertiesPanelVisibility;
diagramControl1.OptionsView.PropertiesPanelVisibility = (status == PropertiesPanelVisibility.Visible ? PropertiesPanelVisibility.Collapsed : PropertiesPanelVisibility.Visible);

2)模具形狀視窗的顯示或隱藏

模具形狀的視窗,它是放在一個面板裡面,我們只需要通過控制該面板的顯示或者隱藏就可以了,如下代碼所示。

 

//切換模具形狀視窗的顯示或關閉
var status = diagramToolboxDockPanel1.Visibility;
diagramToolboxDockPanel1.Visibility = (status == DevExpress.XtraBars.Docking.DockVisibility.Visible ? DevExpress.XtraBars.Docking.DockVisibility.Hidden : DevExpress.XtraBars.Docking.DockVisibility.Visible);

或者通過控制項的Toolbar屬性進行控制,一樣的效果。

//切換模具形狀視窗的顯示或關閉
var status = this.diagramControl1.OptionsView.ToolboxVisibility;
this.diagramControl1.OptionsView.ToolboxVisibility = status == ToolboxVisibility.Closed ? ToolboxVisibility.Full : ToolboxVisibility.Closed;

 

3)放大縮小視窗的顯示或者隱藏

同樣我們也可以控制放大縮小視窗的顯示或者隱藏,它也是圖形繪製的一個常見的視窗。我們只需要判斷或者設置diagramControl1.OptionsView.ShowPanAndZoomPanel 屬性就可以了,如下代碼所示。

//切換放大縮小視窗的顯示或關閉
var status = diagramControl1.OptionsView.ShowPanAndZoomPanel;
diagramControl1.OptionsView.ShowPanAndZoomPanel = !status;

4)其他屬性的處理

另外,我們可以通過控制一些屬性,實現對標尺、網格、只讀視圖等模式進行控制。

//是否顯示標尺
this.diagramControl1.OptionsView.ShowRulers = this.chkRuler.Checked;
//是否顯示網格
this.diagramControl1.OptionsView.ShowGrid = this.chkGrid.Checked;
//是否只讀視圖
this.diagramControl1.OptionsProtection.IsReadOnly = this.chkReadOnly.Checked;

 

2、繪圖的處理事件

在繪製圖形的時候,一般來說我們可能需要切換點選模式或者連接線模式,因此可以通過它的屬性ActiveTool進行設置。在點選模式下,可以對圖形進行拖動、放大縮小、旋轉等處理,連接線模式下,則會加亮連接點,便於自動繪製連接線。

private void btnPointerMode_Click(object sender, EventArgs e)
{
    diagramControl1.OptionsBehavior.ActiveTool = diagramControl1.OptionsBehavior.PointerTool;
}

private void btnConnectorMode_Click(object sender, EventArgs e)
{
    diagramControl1.OptionsBehavior.ActiveTool = diagramControl1.OptionsBehavior.ConnectorTool;
}

當然,我們也可以通過對滑鼠行為的分析來進行控制,如果滑鼠懸停或者放置在圖形上,就自動切換模式為連接線模式,否則為點選模式,那麼只需要判斷滑鼠的移動行為即可自動處理,如下代碼所示。

        /// <summary>
        /// 實現對圖形自動切換到連接點模式
        /// </summary>
        private void diagramControl1_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
                return;

            DiagramItem item = diagramControl1.CalcHitItem(e.Location);
            if (item == null)
            {
                diagramControl1.OptionsBehavior.ActiveTool = diagramControl1.OptionsBehavior.PointerTool;
                return;
            }
            else if (item is DiagramConnector)
            {
                diagramControl1.OptionsBehavior.ActiveTool = diagramControl1.OptionsBehavior.ConnectorTool;
                return;
            }

            Rect itemBounds = new Rect(new Point(item.Position.X, item.Position.Y), new Size(item.Width, item.Height));
            PointFloat documentPoint = diagramControl1.PointToDocument(new PointFloat(e.Location));
            DiagramHitInfo[] hitInfo = diagramControl1.CalcHitInfo(documentPoint);
            if (itemBounds.Contains(new Point(documentPoint.X, documentPoint.Y)))
            {
                itemBounds.Inflate(-5, -5);
                if (!itemBounds.Contains(new Point(documentPoint.X, documentPoint.Y)))
                {
                    diagramControl1.OptionsBehavior.ActiveTool = diagramControl1.OptionsBehavior.ConnectorTool;
                    return;
                }
            }
            diagramControl1.OptionsBehavior.ActiveTool = diagramControl1.OptionsBehavior.PointerTool;
        }

另外圖形的保存xml、PNG、PDF處理和載入代碼如下所示。

/// <summary>
/// 保存XML和圖片文件
/// </summary>
private void SaveXml()
{
    var xml = Path.Combine(Application.StartupPath, "MyFlowShapes.xml");
    diagramControl1.SaveDocument(xml);

    var pngFile = Path.Combine(Application.StartupPath, "MyFlowShapes.png");
    diagramControl1.ExportDiagram(pngFile);
}
private void btnLoadXml_Click(object sender, EventArgs e)
{
    var xml = FileDialogHelper.OpenXml();
    if(!string.IsNullOrEmpty(xml))
    {
        diagramControl1.LoadDocument(xml);
    }
}

最終案例的效果如下所示。

3、註冊自定義的形狀

在實際的圖形繪製開發中,我們可以需要創建一些指定的形狀模具,那麼我們弄好後一般可以存放在XML中,然後進行載入到控制項上來,如下代碼就是註冊自定義的形狀的處理。

/// <summary>
/// 註冊自定義的形狀。
/// 自定義圖形是以XML文件形式進行保存,圖形需要按照規定XML格式進行繪製
/// </summary>
private void LoadShapes2()
{
    var projectName = "SmallExampleDemo.Examples.XtraDiagram";
    using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(projectName + ".CustomContainers.xml"))
    {
        var stencil = DiagramStencil.Create(MyStencilId, MyStencilName, stream, shapeName => shapeName);
        DiagramToolboxRegistrator.RegisterStencil(stencil);
    }
    diagramControl1.SelectedStencils = new StencilCollection(MyStencilId);//(MyStencilId, BasicShapes.StencilId);
}

 我們只需要設置選中的圖形就可以了,其他有需要的可以從More Shapes中選擇即可。

我們如果需要在屬性視窗中顯示自定義的屬性,那麼我們需要一些代碼開發才能實現。

 我們首先需要繼承一個DiagramShape的子類,然後實現自己自定義的屬性定義,如下代碼所示。

對自定義屬性的處理,需要在事件中實現

diagramControl1.CustomGetEditableItemProperties += DiagramControl_CustomGetEditableItemProperties;

通過對它進行判斷可以實現自定義屬性的顯示處理

void DiagramControl_CustomGetEditableItemProperties(object sender, DiagramCustomGetEditableItemPropertiesEventArgs e)
{
    if (e.Item is DiagramShapeEx)
    {
        e.Properties.Add(TypeDescriptor.GetProperties(typeof(DiagramShapeEx))["Status"]);
        e.Properties.Add(TypeDescriptor.GetProperties(typeof(DiagramShapeEx))["TypeName"]);
    }
}

 然後我們可以註冊創建自己的模具形狀集合,如下代碼所示。

/// <summary>
/// 創建自定義的模具
/// </summary>
/// <returns></returns>
DiagramStencil CreateCustomDrawShapesStencil()
{
    var stencilId = "CustomedFlowShape";
    var stencilName = "流程圖";
    var shapeSizeSmall = new Size(100, 37.5);
    var shapeSize = new Size(100, 75);

    DiagramControl.ItemTypeRegistrator.Register(typeof(DiagramShapeEx));
    var stencil = new DiagramStencil(stencilId, stencilName);            

    //流程類型
    stencil.RegisterTool(new FactoryItemTool("StartEnd", () => "流程開始", diagram => { 
        var shape = new DiagramShapeEx(BasicFlowchartShapes.StartEnd, "流程開始");
        shape.Appearance.BackColor = Color.Red;
        return shape;
    }, shapeSizeSmall));
    stencil.RegisterTool(new FactoryItemTool("Decision", () => "流程條件", diagram => { 
        var shape = new DiagramShapeEx(BasicFlowchartShapes.Decision, "流程條件");
        shape.Appearance.BackColor = Color.FromArgb(199, 115, 1);//Color.Red;
        return shape;
    }, shapeSize));

這兩個流程開始,流程條件,我們直接是從 BasicFlowchartShapes 集合中借用過來,構建自己的自定義對象的,預設創建的對象是方形的。

如果我們需要動態構建其他自定義類型,我們可以指定它的顏色等樣式,從而構建不同類型的圖形。

//迴圈添加相關流程節點
var procNames = new List<string> { "審批", "歸檔", "閱辦", "會簽", "領導批示分閱"};
//定義幾個初始化顏色順序
var colors = new List<Color> { Color.DeepSkyBlue, Color.ForestGreen, Color.Violet, Color.Yellow, Color.Blue, Color.Orange, Color.Indigo, Color.Purple, Color.Black, Color.Brown, Color.Pink };
int i = 0;
foreach (string name in procNames)
{
    var shapeId = string.Format("Process_{0}", i++);

    stencil.RegisterTool(new FactoryItemTool(shapeId, () => name, diagram =>
    {
        var shape = new DiagramShapeEx(name, Status.Inactive);
        var index = procNames.IndexOf(name);
        var color = colors[index % 10];//Color.Red;
        var fontColor =  (color == Color.Yellow) ? Color.Black : Color.White;

        //沒什麼作用
        //shape.ThemeStyleId = GetStyle(index); //從Accent1樣式開始  DiagramShapeStyleId.Styles[index];//                  
        shape.Appearance.BackColor = color;
        shape.Appearance.BorderSize = 3;
        shape.Appearance.Font = new Font("宋體", 12f, FontStyle.Bold);
        shape.Appearance.ForeColor = fontColor;
        return shape;
    }, shapeSize));
}

這樣就有不同顏色的圖形對象了。

 根據這些我們就可以繪製出自己的各種流程圖了,並且也可以根據資料庫的信息,進行動態繪製展示。

 

專註於代碼生成工具、.Net/.NetCore 框架架構及軟體開發,以及各種Vue.js的前端技術應用。著有Winform開發框架/混合式開發框架、微信開發框架、Bootstrap開發框架、ABP開發框架、SqlSugar開發框架等框架產品。
  轉載請註明出處:撰寫人:伍華聰  http://www.iqidi.com 
    

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 來源:https://www.51cto.com/article/628604.html 你是否還在大量控制台視窗中監控容器,還是對使用終端命令充滿熱情?而使用Docker的圖形用戶界面(GUI)工具,則可以更簡單的對容器進行管理,並提高效率。而且它們都是免費的。 1.Portainer Porta ...
  • Hi,大家好,我是Mic 一個工作3年的粉絲,早上6點給我微信發語音,把我直接嚇醒。 我以為什麼天大的事情,結果一問才知道。 面試官問了他一個問題沒答上來,問題是“Spring裡面,如果兩個id相同的bean會報錯嗎?如果會,在哪個階段報錯?” 下麵看看普通人和高手的回答! 普通人: 兩個id相同的 ...
  • 作為SpringData JPA系列內容的第二篇,此處以SpringBoot項目為基準,講一下集成SpringData JPA的相關要點,帶你快速的上手SpringData JPA,並用實例演示常見的DB操作場景,讓你分分鐘輕鬆玩轉JPA。 ...
  • 前言 不知道大家在工作無聊時,有沒有一種衝動:總想掏出手機,看看微博熱搜在討論什麼有趣的話題,但又不方便直接打開微博瀏 覽,今天就和大家分享一個有趣的小爬蟲,定時採集微博熱搜榜&熱評,下麵讓我們來看看具體的實現方法。 頁面分析 熱搜頁 熱榜首頁:https://s.weibo.com/top/sum ...
  • Zookeeper3.7源碼剖析 能力目標 能基於Maven導入最新版Zookeeper源碼 能說出Zookeeper單機啟動流程 理解Zookeeper預設通信中4個線程的作用 掌握Zookeeper業務處理源碼處理流程 能夠在Zookeeper源碼中Debug測試通信過程 1 Zookeeper ...
  • 系列文章彙總 前言: 最近看到ABP官網的一本電子書,感覺寫的很好,翻譯出來,一起學習下 Implementing Domain Driven Design 實現領域驅動設計 - 使用ABP框架 - 什麼是領域驅動設計? 實現領域驅動設計 - 使用ABP框架 - 解決方案概覽 實現領域驅動設計 - ...
  • 應用程式服務 應用程式服務是一種無狀態的服務,它實現應用程式的用例。應用程式服務通常獲取和返回dto。它由表示層使用。它使用並協調領域對象(實體、存儲庫等)來實現用例 應用程式服務的常見原則如下: 實現特定於當前用例的應用程式邏輯。不要在應用程式服務內部實現核心領域邏輯。我們將回到應用程式領域邏輯之 ...
  • 提示:文章寫完後,目錄可以自動生成,如何生成可參考右邊的幫助文檔 @(MstnVBA學習--Vol1.代碼畫點線--20220623) 前言 2022年6月23日,小白筆記,複習之前的MstnVBA代碼,因為目前還做不到完全自己背誦或編寫出來,雖然簡單,溫故知新~ Mstn中沒有單獨的圓的概念,圓實 ...
一周排行
    -Advertisement-
    Play Games
  • 經常看到有群友調侃“為什麼搞Java的總在學習JVM調優?那是因為Java爛!我們.NET就不需要搞這些!”真的是這樣嗎?今天我就用一個案例來分析一下。 昨天,一位學生問了我一個問題:他建了一個預設的ASP.NET Core Web API的項目,也就是那個WeatherForecast的預設項目模 ...
  • 很多軟體工程師都認為MD5是一種加密演算法,然而這種觀點是不對的。作為一個 1992 年第一次被公開的演算法,到今天為止已經被髮現了一些致命的漏洞。本文討論MD5在密碼保存方面的一些問題。 ...
  • Maven可以使我們在構建項目時需要用到很多第三方類jar包,如下一些常用jar包 而maven的出現可以讓我們避免手動導入jar包出現的某些問題,它可以自動下載那須所需要的jar包 我們只需要在創建的maven項目自動生成的pom.xml中輸入如下代碼 <dependencies> <!--ser ...
  • 來源:https://developer.aliyun.com/article/694020 非同步調用幾乎是處理高併發Web應用性能問題的萬金油,那麼什麼是“非同步調用”? “非同步調用”對應的是“同步調用”,同步調用指程式按照定義順序依次執行,每一行程式都必須等待上一行程式執行完成之後才能執行;非同步調 ...
  • 1.面向對象 面向對象編程是在面向過程編程的基礎上發展來的,它比面向過程編程具有更強的靈活性和擴展性,所以可以先瞭解下什麼是面向過程編程: 面向過程編程的核心是過程,就是分析出實現需求所需要的步驟,通過函數一步一步實現這些步驟,接著依次調用即可,再簡單理解就是程式 從上到下一步步執行,從頭到尾的解決 ...
  • 10瓶毒藥其中只有一瓶有毒至少需要幾隻老鼠可以找到有毒的那瓶 身似浮雲,心如飛絮,氣若游絲。 用二分查找和二進位位運算的思想都可以把死亡的老鼠降到最低。 其中,二進位位運算就是每一隻老鼠代表一個二進位0或1,0就代表老鼠存活,1代表老鼠死亡;根據數學運算 23 = 8、24 = 16,那麼至少需要四 ...
  • 一、Kafka存在哪些方面的優勢 1. 多生產者 可以無縫地支持多個生產者,不管客戶端在使用單個主題還是多個主題。 2. 多消費者 支持多個消費者從一個單獨的消息流上讀取數據,而且消費者之間互不影響。 3. 基於磁碟的數據存儲 支持消費者非實時地讀取消息,由於消息被提交到磁碟,根據設置的規則進行保存 ...
  • 大家好,我是陶朱公Boy。 前言 上一篇文章《關於狀態機的技術選型,最後一個真心好》我跟大家聊了一下關於”狀態機“的話題。從眾多技術選型中我也推薦了一款阿裡開源的狀態機—“cola-statemachine”。 於是就有小伙伴私信我,自己項目也考慮引入這款狀態機,但網上資料實在太少,能不能系統的介紹 ...
  • 使用腳本自動跑實驗(Ubuntu),將實驗結果記錄在文件中,併在實驗結束之後將結果通過郵件發送到郵箱,最後在windows端自動解析成excel表格。 ...
  • 話說在前面,我不是小黑子~ 我是超級大黑子😏 表弟大周末的跑來我家,沒事幹天天騷擾我,搞得我都不能跟小姐姐好好聊天了,於是為了打發表弟,我決定用Python做一個小游戲來消耗一下他的精力,我思來想去,決定把他變成小黑子,於是做了一個坤坤打籃球的游戲,沒想到他還挺愛玩的~ 終於解放了,於是我把游戲寫 ...