C#上位机与三菱PLC的通信11---开发自己的通讯工具软件(WPF版)

本文主要是介绍C#上位机与三菱PLC的通信11---开发自己的通讯工具软件(WPF版),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1、先看颜值

2、开始干

1、创建项目

2、引入前面的通讯库

 创建目录将前面生成的通讯库dll文件复制到项目的目录

本项目引入dll文件

 

 3、创建命令基类

RelayCommand.cs代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;namespace MitsubishiMcToolWPF.Common
{/// <summary>/// 命令实现类/// </summary>public class RelayCommand : ICommand{public event EventHandler CanExecuteChanged;/// <summary>/// 要执行的操作/// </summary>private Action<object> executeActions;/// <summary>/// 是否可以执行的委托/// </summary>private Func<object, bool> canExecuteFunc;/// <summary>/// 构造函数 无参构造/// </summary>public RelayCommand() { }/// <summary>/// 通过执行的委托构造/// </summary>/// <param name="execute"></param>public RelayCommand(Action<object> execute) : this(execute, null){}/// <summary>/// 通过执行的操作与是否可执行的委托/// </summary>/// <param name="execute">要执行的操作</param>/// <param name="canExecute">是否可以被执行</param>public RelayCommand(Action<object> execute, Func<object, bool> canExecute){this.executeActions = execute;this.canExecuteFunc = canExecute;}/// <summary>/// 命令是否可以执行/// </summary>/// <param name="parameter"></param>/// <returns></returns>public bool CanExecute(object parameter){if (canExecuteFunc != null)return this.canExecuteFunc(parameter);elsereturn true;}/// <summary>/// 要执行的操作/// </summary>/// <param name="parameter"></param>public void Execute(object parameter){if (executeActions == null)return;this.executeActions(parameter);}/// <summary>/// 执行CanExecuteChanged事件/// </summary>public void OnCanExecuteChanged(){this.CanExecuteChanged?.Invoke(this, new EventArgs());}}
}

 4、创建PLC实体类

PLCMemoryModel.cs代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace MitsubishiMcToolWPF.Model
{/// <summary>/// PLC内存模型类/// </summary>public class PLCMemoryModel{/// <summary>/// 存储区/// </summary>public string Area { get; set; } = "";/// <summary>/// 地址/// </summary>public string Address { get; set; } = "";/// <summary>/// 数据类型/// </summary>public string DataType { get; set; } = "";/// <summary>/// 读取或写入数据/// </summary>public string Count { get; set; } = "";}
}

 5、添加资源字典,即样式文件

CommonResource.xaml完整代码

 <!--读取写入Button按钮样式--> <Style x:Key="ButtonStyle" TargetType="Button"><Setter Property="Background" Value="#3F85FF"></Setter><Setter Property="Foreground" Value="White"></Setter><Setter Property="FocusVisualStyle" Value="{x:Null}"></Setter><Setter Property="Margin" Value="5"></Setter><Setter Property="Height" Value="90"></Setter><Setter Property="FontSize" Value="16"></Setter><!--模板的样式--><Setter Property="Template"><Setter.Value><!--Button单选按钮样式--><ControlTemplate TargetType="Button"><Grid ><Border Background="{TemplateBinding Background}" CornerRadius="5" ><TextBlock Margin="10 5 10 5" Text="{TemplateBinding Content}" FontSize="{TemplateBinding FontSize}" HorizontalAlignment="Center" VerticalAlignment="Center"></TextBlock></Border></Grid><ControlTemplate.Triggers><!--鼠标放上去时的触发器--><Trigger Property="IsMouseOver" Value="True"><Setter Property="Background" Value="#1E5FD1" ></Setter></Trigger></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter></Style><!--连接断开按钮样式--><Style x:Key="ConnStyle" TargetType="Button"><Setter Property="Background" Value="#3F8666"></Setter><Setter Property="Foreground" Value="White"></Setter><Setter Property="FocusVisualStyle" Value="{x:Null}"></Setter><Setter Property="Margin" Value="5"></Setter><Setter Property="Height" Value="60"></Setter><Setter Property="FontSize" Value="16"></Setter><!--模板的样式--><Setter Property="Template"><Setter.Value><!--Button单选按钮样式--><ControlTemplate TargetType="Button"><Grid ><Border Background="{TemplateBinding Background}" CornerRadius="5" ><TextBlock Margin="10 5 10 5" Text="{TemplateBinding Content}" FontSize="{TemplateBinding FontSize}" HorizontalAlignment="Center" VerticalAlignment="Center"></TextBlock></Border></Grid><ControlTemplate.Triggers><!--鼠标放上去时的触发器--><Trigger Property="IsMouseOver" Value="True"><Setter Property="Background" Value="#1E5FD1" ></Setter></Trigger></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter></Style><!--TextBox默认样式--><Style TargetType="{x:Type TextBox}" x:Key="txtTextBoxStyle"><Setter Property="Width" Value="150"/><Setter Property="Height" Value="25"/><Setter Property="BorderBrush" Value="#FF105190"/><Setter Property="BorderThickness" Value="1"/><Setter Property="Margin" Value="2,0"/><Setter Property="VerticalContentAlignment" Value="Center"/><Setter Property="Background"><Setter.Value><LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1"><GradientStop Color="White" Offset="0"/><GradientStop Color="#FFE4E4E4" Offset="1"/></LinearGradientBrush></Setter.Value></Setter></Style><!--TextBlock默认样式--><Style TargetType="{x:Type TextBlock}" x:Key="txtTextBlockStyle"><Setter Property="Margin" Value="1"/><Setter Property="Height" Value="15"/></Style><!--页面下拉框样式--><LinearGradientBrush x:Key="ComboBox.Static.Background" EndPoint="0,1" StartPoint="0,0"><GradientStop Color="White" Offset="0"/><GradientStop Color="#FFE4E4E4" Offset="1"/></LinearGradientBrush><SolidColorBrush x:Key="ComboBox.Static.Border" Color="#FF105190"/><!--combox默认样式--><Style x:Key="cboStyle" TargetType="{x:Type ComboBox}"><Setter Property="Background" Value="{StaticResource ComboBox.Static.Background}"/><Setter Property="BorderBrush" Value="{StaticResource ComboBox.Static.Border}"/><Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}"/><Setter Property="Width" Value="150"/><Setter Property="Height" Value="25"/><Setter Property="BorderThickness" Value="1"/><Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/><Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/><Setter Property="Padding" Value="6,3,5,3"/><Setter Property="ScrollViewer.CanContentScroll" Value="true"/><Setter Property="ScrollViewer.PanningMode" Value="Both"/><Setter Property="Stylus.IsFlicksEnabled" Value="False"/></Style>

 

 6、创建viewmodel

viewmodel是视图模型,wpf采用的是mvvm的渲染模式,即控件绑定对象的属性,属性发生更改时,驱动控件的数据显示,而控件动作是由命令command执行

1、模型基类

ViewModelBase.cs代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using static MitsubishiMcToolWPF.MsgBoxWindow;namespace MitsubishiMcToolWPF.ViewModel
{/// <summary>/// 视图模型基类/// </summary>public class ViewModelBase : INotifyPropertyChanged{/// <summary>/// 属性值发生更改时触发/// </summary>public event PropertyChangedEventHandler PropertyChanged;/// <summary>/// 执行更改/// C#5.0中的新特性CallerMemberName/// </summary>/// <param name="propertyName"></param>protected void OnPropertyChanged([CallerMemberName] string propertyName = ""){if (PropertyChanged != null){PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));}}/// <summary>/// 成功消息提示/// </summary>/// <param name="message"></param>/// <param name="title"></param>/// <param name="buttons"></param>public void ShowMessage(string message, string title = "提示", CustomMessageBoxButton buttons = CustomMessageBoxButton.OK){Show(message, title, buttons, CustomMessageBoxIcon.Infomation);}/// <summary>/// 错误消息框/// </summary>/// <param name="message"></param>/// <param name="title"></param>/// <param name="buttons"></param>public void ShowError(string message, string title = "错误", CustomMessageBoxButton buttons = CustomMessageBoxButton.OK){Show(message, title, buttons, CustomMessageBoxIcon.Error);}/// <summary>/// 询问消息框/// </summary>/// <param name="message"></param>/// <param name="title"></param>/// <param name="buttons"></param>/// <returns></returns>public CustomMessageBoxResult ShowQuestion(string message, string title = "询问", CustomMessageBoxButton buttons = CustomMessageBoxButton.OKCancel){return Show(message, title, buttons, CustomMessageBoxIcon.Question);}}
}

 2、主页模型mainviewmodel

MainViewModel.cs代码

 

using Mitsubishi.Communication.MC.Mitsubishi;
using MitsubishiMcToolWPF.Common;
using MitsubishiMcToolWPF.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;namespace MitsubishiMcToolWPF.ViewModel
{/// <summary>/// 视图模型/// </summary>public class MainViewModel : ViewModelBase{/// <summary>/// mctcp对象/// </summary>A3E mctcp;#region 属性PLCMemoryModel readPLCModel = SetInitModel();/// <summary>/// 读取PLC/// </summary>public PLCMemoryModel ReadPLCModel{get { return readPLCModel; }set{readPLCModel = ReadPLCModel;OnPropertyChanged();//属性通知}}PLCMemoryModel writePLCModel = SetInitModel();/// <summary>/// 写入PLC/// </summary>public PLCMemoryModel WritePLCModel{get { return writePLCModel; }set{writePLCModel = WritePLCModel;OnPropertyChanged();}}/// <summary>/// 初始化页面参数/// </summary>/// <returns></returns>private static PLCMemoryModel SetInitModel(){PLCMemoryModel model = new PLCMemoryModel();model.Area = "D";model.DataType = "short";model.Address = "100";model.Count = "1";return model;}private string hostName = "192.168.1.7";/// <summary>/// PLC地址/// </summary>public string HostName{get{return hostName;}set{hostName = value;}}private string hostPort = "6000";/// <summary>/// PLC端口/// </summary>public string HostPort{get { return hostPort; }set{hostPort = value;}}/// <summary>/// 存储区下拉框数据源/// </summary>public List<string> CboCustTypes{get{return new List<string>() { "D", "X", "Y", "M", "R", "S", "TS" };}}/// <summary>/// 数据类型/// </summary>public List<string> CboCustDatas{get{return new List<string>() { "short", "float", "bool" };}}private string readWords = "";/// <summary>/// 读数结果/// </summary>public string ReadWords{get { return readWords; }set{readWords = value;OnPropertyChanged();}}private string writeWords = "";/// <summary>/// 写入数据/// </summary>public string WriteWords{get { return writeWords; }set{writeWords = value;OnPropertyChanged();}}private string connectWords = "当前未连接";/// <summary>/// 连接状态/// </summary>public string ConnectWords{get { return connectWords; }set{connectWords = value;OnPropertyChanged();}}#endregion#region 命令/// </summary>/// <summary>///连接按钮的命令 /// </summary>public ICommand ConnCommand{get{return new RelayCommand(o =>{var name = HostName;var port = HostPort;mctcp = new A3E(name, short.Parse(port));// 创建连接 var result = mctcp.Connect();// 开始连接PLCif (!result.IsSuccessed){ShowError(result.Message, "错误");return;}ConnectWords = "PLC已连接";ShowMessage("PLC连接成功", "提示");});}}/// </summary>/// <summary>///断开按钮的命令 /// </summary>public ICommand CloseCommand{get{return new RelayCommand(o =>{if (mctcp == null){ShowError("PLC没有连接,不能断开", "错误");return;}mctcp = null;ConnectWords = "PLC已断开";});}}/// </summary>/// <summary>/// 读取按钮的命令 /// </summary>public ICommand ReadCommand{get{return new RelayCommand(o =>{ReadWords = "";var d = ReadPLCModel;if (mctcp == null){ShowError("PLC未连接,不能读取数据", "错误");return;}//内存地址string plcAddr = ReadPLCModel.Area + ReadPLCModel.Address;//读取数量short readCount = short.Parse(ReadPLCModel.Count);//数据类型string dataType = ReadPLCModel.DataType;switch (dataType){case "short":var datas2 = mctcp.Read<short>(plcAddr, readCount);if (!datas2.IsSuccessed){ShowMessage(datas2.Message, "提示");return;}ReadWords = string.Join(",", datas2.Datas);break;case "float":var datas3 = mctcp.Read<float>(plcAddr, readCount);if (!datas3.IsSuccessed){ShowMessage(datas3.Message, "提示");return;}ReadWords = string.Join(",", datas3.Datas);break;case "bool":var datas4 = mctcp.Read<bool>(plcAddr, readCount);if (!datas4.IsSuccessed){ShowMessage(datas4.Message, "提示");return;}ReadWords = string.Join(",", datas4.Datas);break;}});}}/// </summary>/// <summary>/// 写入按钮的命令处理/// </summary>public ICommand WriteCommand{get{return new RelayCommand(o =>{if (mctcp == null){ShowError("PLC未连接,不能写入数据", "错误");return;}var d = WritePLCModel;//内存地址string plcAddr = WritePLCModel.Area + WritePLCModel.Address;//写入数量 ushort writeCount = ushort.Parse(WritePLCModel.Count);//数据类型string dataType = WritePLCModel.DataType;//实际数量string objWriteVals = WriteWords;ushort objWCount = (ushort)objWriteVals.Split(',').Length;//实际数量与要求数量不一致,不允许操作if (writeCount != objWCount){ShowError("写入值的数量不正确!");return;}List<string> vals = objWriteVals.Split(',').ToList();switch (dataType){case "short"://实际数值转换成list集合 short类型List<short> objshort = new List<short>();vals.ForEach((x) =>{objshort.Add(short.Parse(x));});var finish2 = mctcp.Write<short>(objshort, plcAddr);if (finish2.IsSuccessed){ShowMessage("写入成功", "提示");}break;case "float"://实际数值转换成list集合 floatList<float> objfloat = new List<float>();vals.ForEach((x) =>{objfloat.Add(float.Parse(x));});var finish3 = mctcp.Write<float>(objfloat, plcAddr);if (finish3.IsSuccessed){ShowMessage("写入成功", "提示");}break;case "bool"://实际数值转换成list集合boolList<bool> objbool = new List<bool>();vals.ForEach((x) =>{if (x == "1"){objbool.Add(true);}else{objbool.Add(false);}});var finish4 = mctcp.Write<bool>(objbool, plcAddr);if (finish4.IsSuccessed){ShowMessage("写入成功", "提示");}break;}});}}#endregion}
}

7、主界面布局

MainWindow.xaml完整代码

<Window x:Class="MitsubishiMcToolWPF.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:MitsubishiMcToolWPF.ViewModel"mc:Ignorable="d"   FontSize="13" FontFamily="Microsoft YaHei"  ResizeMode="CanMinimize" Title="三菱PLC通讯工具" FontWeight="ExtraLight" WindowStartupLocation="CenterScreen"  Height="450" Width="880" Name="mainWin"  ><Window.DataContext><local:MainViewModel/></Window.DataContext><Grid   ShowGridLines="true"><Grid.RowDefinitions><RowDefinition Height="62"/><RowDefinition/></Grid.RowDefinitions><!--第一行标题--><Grid Grid.Row="0" Background="BlanchedAlmond"><Grid.ColumnDefinitions><ColumnDefinition Width="100" /><ColumnDefinition /></Grid.ColumnDefinitions><Image Grid.Column="0" Source="/imgs/log1.png"  Width="60" Height="60" Margin="20,0" /><TextBlock Grid.Column="1"   Text="三菱MC协议通讯调试助手(Qna-3E模式)" FontSize="23" VerticalAlignment="Center"  FontWeight="Bold" /></Grid><!--第二行信息--><Grid Grid.Row="1" Margin="0 10 0 0"><Grid.ColumnDefinitions><ColumnDefinition Width="200"/><ColumnDefinition Width="4"/><ColumnDefinition/></Grid.ColumnDefinitions><!--第一列PLC参数--><StackPanel Grid.Column="0" Margin="20"><TextBlock Text="PLC地址"/><TextBox   Height="30" VerticalContentAlignment="Center" Padding="5,0" Margin="0,10" Text="{Binding HostName}"  /><TextBlock Text="端口号" Margin="0,10,0,0"/><TextBox  Height="30" VerticalContentAlignment="Center" Padding="5,0" Margin="0,10" Text="{Binding HostPort}"  /><Button Content="连接" Margin="0,30,0,0" Height="30"   Command="{Binding ConnCommand}"  Style="{StaticResource ConnStyle}" /><Button Content="断开" Margin="0,10" Height="30"  Command="{Binding CloseCommand}"  Style="{StaticResource ConnStyle}"/><TextBlock  Text="{Binding ConnectWords,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"  Margin="0,10,0,0"  Foreground="Blue"/></StackPanel><!--第二列分隔线--><GridSplitter Grid.Column="1" Background="#4490AC" Width="2" Height="450" Margin="0 -11 0 0"></GridSplitter><!--第三列操作区--><Grid Grid.Column="2"><Grid.RowDefinitions><RowDefinition Height="60"/><RowDefinition Height="80"/><RowDefinition Height="30"/><RowDefinition Height="60"/><RowDefinition Height="80"/></Grid.RowDefinitions><Grid.ColumnDefinitions><ColumnDefinition/><ColumnDefinition/></Grid.ColumnDefinitions><StackPanel Orientation="Horizontal" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Margin="10"><TextBlock     Text="存储区:"  Style="{StaticResource  txtTextBlockStyle}" Margin="0 0 0 0" ></TextBlock><ComboBox  ItemsSource="{Binding CboCustTypes}" SelectedValue="{Binding  ReadPLCModel.Area}"  Width="70"  Style="{StaticResource cboStyle}"></ComboBox><TextBlock   Text="数据类型:"  Style="{StaticResource  txtTextBlockStyle}" ></TextBlock><ComboBox     ItemsSource="{Binding CboCustDatas}" SelectedValue="{Binding ReadPLCModel.DataType}"  Width="70"  Style="{StaticResource cboStyle}"></ComboBox><TextBlock   Text="地址:" Style="{StaticResource  txtTextBlockStyle}" ></TextBlock><TextBox    Text="{Binding ReadPLCModel.Address}"  Width="100"  Style="{StaticResource  txtTextBoxStyle}" /><TextBlock   Text="数量:" Style="{StaticResource  txtTextBlockStyle}" ></TextBlock><TextBox    Text="{Binding ReadPLCModel.Count}"  Width="60" Style="{StaticResource  txtTextBoxStyle}"  /><Button Content="读取" Height="30" Width="100"  Command="{Binding ReadCommand}" CommandParameter="{Binding ElementName=loginWin}" Style="{StaticResource ButtonStyle}"  /></StackPanel><StackPanel Orientation="Vertical" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2"  Margin="10"><TextBlock Text="读取结果(多个数据之间用逗号隔开)"  Style="{StaticResource  txtTextBlockStyle}" Margin="0 3 0 9"></TextBlock><TextBox   Text="{Binding ReadWords,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"  Width="616" Style="{StaticResource  txtTextBoxStyle}"  Margin="-23,0,0,0"   /></StackPanel><StackPanel Orientation="Horizontal"  Grid.Row="2"  Grid.Column="0" Grid.ColumnSpan="2" Background="#4490AC" Width="706" Height="2" Margin="-1,0,0,0"></StackPanel><StackPanel Orientation="Horizontal" Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2"  Margin="10"><TextBlock     Text="存储区:" Style="{StaticResource  txtTextBlockStyle}" Margin="0 0 0 0"></TextBlock><ComboBox    ItemsSource="{Binding CboCustTypes}" SelectedValue="{Binding WritePLCModel.Area }"  Width="70"  Style="{StaticResource cboStyle}"></ComboBox><TextBlock   Text="数据类型:" Style="{StaticResource  txtTextBlockStyle}" ></TextBlock><ComboBox     ItemsSource="{Binding CboCustDatas}" SelectedValue="{Binding WritePLCModel.DataType }"  Width="70"  Style="{StaticResource cboStyle}"></ComboBox><TextBlock   Text="地址:" Style="{StaticResource  txtTextBlockStyle}" ></TextBlock><TextBox   Text="{Binding  WritePLCModel.Address }"  Width="100"  Style="{StaticResource  txtTextBoxStyle}"  /><TextBlock   Text="数量:" Style="{StaticResource  txtTextBlockStyle}" ></TextBlock><TextBox    Text="{Binding WritePLCModel.Count}"  Width="60"   Style="{StaticResource  txtTextBoxStyle}"  /><Button Content="写入" Height="30" Width="100"   Command="{Binding WriteCommand}" CommandParameter="{Binding ElementName=loginWin}" Style="{StaticResource ButtonStyle}" /></StackPanel><StackPanel Orientation="Vertical" Grid.Row="4" Grid.Column="0" Grid.ColumnSpan="2"  Margin="10"><TextBlock   Text="写入数据(多个数据之间用逗号隔开)" Style="{StaticResource  txtTextBlockStyle}"  Margin="0 3 0 9" ></TextBlock><TextBox    Text="{Binding WriteWords ,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"  Width="616" Style="{StaticResource  txtTextBoxStyle}"  Margin="-23,0,0,0"  /></StackPanel></Grid></Grid></Grid>
</Window>

 

 8、启动MC服务器

 9、异常错误处理

 

10、操作测试

1、连接PLC

2、读取数据,short,float,bool

 

3、写入数据,short,float

 写入short

写入float

 

3、小结

 

走过路过不要错过,点赞关注收藏又圈粉,共同致富。

欢迎抄袭,复制,分享,转载,学习,截图..............

欢迎抄袭,复制,分享,转载,学习,截图..............

这篇关于C#上位机与三菱PLC的通信11---开发自己的通讯工具软件(WPF版)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/743350

相关文章

C#实现获取电脑中的端口号和硬件信息

《C#实现获取电脑中的端口号和硬件信息》这篇文章主要为大家详细介绍了C#实现获取电脑中的端口号和硬件信息的相关方法,文中的示例代码讲解详细,有需要的小伙伴可以参考一下... 我们经常在使用一个串口软件的时候,发现软件中的端口号并不是普通的COM1,而是带有硬件信息的。那么如果我们使用C#编写软件时候,如

C#中图片如何自适应pictureBox大小

《C#中图片如何自适应pictureBox大小》文章描述了如何在C#中实现图片自适应pictureBox大小,并展示修改前后的效果,修改步骤包括两步,作者分享了个人经验,希望对大家有所帮助... 目录C#图片自适应pictureBox大小编程修改步骤总结C#图片自适应pictureBox大小上图中“z轴

使用C#代码计算数学表达式实例

《使用C#代码计算数学表达式实例》这段文字主要讲述了如何使用C#语言来计算数学表达式,该程序通过使用Dictionary保存变量,定义了运算符优先级,并实现了EvaluateExpression方法来... 目录C#代码计算数学表达式该方法很长,因此我将分段描述下面的代码片段显示了下一步以下代码显示该方法如

C#实现WinForm控件焦点的获取与失去

《C#实现WinForm控件焦点的获取与失去》在一个数据输入表单中,当用户从一个文本框切换到另一个文本框时,需要准确地判断焦点的转移,以便进行数据验证、提示信息显示等操作,本文将探讨Winform控件... 目录前言获取焦点改变TabIndex属性值调用Focus方法失去焦点总结最后前言在一个数据输入表单

基于C#实现PDF文件合并工具

《基于C#实现PDF文件合并工具》这篇文章主要为大家详细介绍了如何基于C#实现一个简单的PDF文件合并工具,文中的示例代码简洁易懂,有需要的小伙伴可以跟随小编一起学习一下... 界面主要用于发票PDF文件的合并。经常出差要报销的很有用。代码using System;using System.Col

Java中的Opencv简介与开发环境部署方法

《Java中的Opencv简介与开发环境部署方法》OpenCV是一个开源的计算机视觉和图像处理库,提供了丰富的图像处理算法和工具,它支持多种图像处理和计算机视觉算法,可以用于物体识别与跟踪、图像分割与... 目录1.Opencv简介Opencv的应用2.Java使用OpenCV进行图像操作opencv安装j

通过C#获取PDF中指定文本或所有文本的字体信息

《通过C#获取PDF中指定文本或所有文本的字体信息》在设计和出版行业中,字体的选择和使用对最终作品的质量有着重要影响,然而,有时我们可能会遇到包含未知字体的PDF文件,这使得我们无法准确地复制或修改文... 目录引言C# 获取PDF中指定文本的字体信息C# 获取PDF文档中用到的所有字体信息引言在设计和出

C#读取本地网络配置信息全攻略分享

《C#读取本地网络配置信息全攻略分享》在当今数字化时代,网络已深度融入我们生活与工作的方方面面,对于软件开发而言,掌握本地计算机的网络配置信息显得尤为关键,而在C#编程的世界里,我们又该如何巧妙地读取... 目录一、引言二、C# 读取本地网络配置信息的基础准备2.1 引入关键命名空间2.2 理解核心类与方法

基于Qt开发一个简单的OFD阅读器

《基于Qt开发一个简单的OFD阅读器》这篇文章主要为大家详细介绍了如何使用Qt框架开发一个功能强大且性能优异的OFD阅读器,文中的示例代码讲解详细,有需要的小伙伴可以参考一下... 目录摘要引言一、OFD文件格式解析二、文档结构解析三、页面渲染四、用户交互五、性能优化六、示例代码七、未来发展方向八、结论摘要

最好用的WPF加载动画功能

《最好用的WPF加载动画功能》当开发应用程序时,提供良好的用户体验(UX)是至关重要的,加载动画作为一种有效的沟通工具,它不仅能告知用户系统正在工作,还能够通过视觉上的吸引力来增强整体用户体验,本文给... 目录前言需求分析高级用法综合案例总结最后前言当开发应用程序时,提供良好的用户体验(UX)是至关重要