├── Docs
├── source
│ ├── _static
│ │ └── .gitxxx
│ ├── _images
│ │ ├── osda.png
│ │ └── framework.png
│ ├── license.rst
│ ├── guides.rst
│ ├── index.rst
│ ├── getting_started.rst
│ ├── contribute.rst
│ ├── api.rst
│ └── conf.py
├── README.md
├── Makefile
└── make.bat
├── msvc
├── VS2017.Framework
│ ├── Models
│ │ └── .gitxxx
│ ├── Views
│ │ └── .gitxxx
│ ├── Interface
│ │ └── .gitxxx
│ ├── Properties
│ │ └── .gitxxx
│ ├── ViewModels
│ │ └── .gitxxx
│ ├── icon
│ │ ├── Max.png
│ │ ├── Min.png
│ │ ├── Red.png
│ │ ├── Close.png
│ │ ├── favicon.ico
│ │ ├── favicon.png
│ │ └── README.md
│ ├── App.config
│ └── ODSA.csproj
├── VS2019.Framework
│ ├── Models
│ │ └── .gitxxx
│ ├── Views
│ │ └── .gitxxx
│ ├── Interface
│ │ └── .gitxxx
│ ├── Properties
│ │ └── .gitxxx
│ ├── ViewModels
│ │ └── .gitxxx
│ ├── icon
│ │ ├── Max.png
│ │ ├── Min.png
│ │ ├── Red.png
│ │ ├── Close.png
│ │ ├── favicon.ico
│ │ ├── favicon.png
│ │ └── README.md
│ ├── App.config
│ ├── packages.config
│ └── OSDA.csproj
├── VS2019.Core
│ ├── icon
│ │ ├── Max.png
│ │ ├── Min.png
│ │ ├── Red.png
│ │ ├── Close.png
│ │ ├── favicon.ico
│ │ └── favicon.png
│ └── OSDA.csproj
├── OSDA2017.Framework.sln
├── OSDA2019.Core.sln
└── OSDA2019.Framework.sln
├── icon
├── Max.png
├── Min.png
├── Red.png
├── Close.png
├── favicon.ico
├── favicon.png
└── README.md
├── .gitee
├── PULL_REQUEST_TEMPLATE.zh-CN.md
├── ISSUE_GUIDELINES.md
└── ISSUE_TEMPLATE.zh-CN.md
├── .github
├── pull_request_template.md
└── ISSUE_TEMPLATE
│ ├── Feature_request.md
│ └── Bug_report.md
├── Properties
├── Settings.settings
├── Settings.Designer.cs
├── AssemblyInfo.cs
├── Resources.Designer.cs
└── Resources.resx
├── Setup
├── README.md
└── OSDA_Inno_Setup.iss
├── App.xaml.cs
├── ViewModels
├── WPFUpdateVM.cs
├── MainWindowBase.cs
└── MainWindowVM.cs
├── Views
├── WPFUpdate.xaml.cs
├── WPFUpdate.xaml
├── MainWindow.xaml.cs
└── MainWindow.xaml
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── Models
├── TimerM.cs
├── RecvM.cs
├── SendM.cs
├── HelpM.cs
└── SerialPortM.cs
├── CODE_OF_CONDUCT.md
├── Interface
└── ITextBoxAppend.cs
├── .gitignore
└── App.xaml
/Docs/source/_static/.gitxxx:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/msvc/VS2017.Framework/Models/.gitxxx:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/msvc/VS2017.Framework/Views/.gitxxx:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/msvc/VS2019.Framework/Models/.gitxxx:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/msvc/VS2019.Framework/Views/.gitxxx:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/msvc/VS2017.Framework/Interface/.gitxxx:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/msvc/VS2017.Framework/Properties/.gitxxx:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/msvc/VS2017.Framework/ViewModels/.gitxxx:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/msvc/VS2019.Framework/Interface/.gitxxx:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/msvc/VS2019.Framework/Properties/.gitxxx:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/msvc/VS2019.Framework/ViewModels/.gitxxx:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/icon/Max.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leven99/OSDA/HEAD/icon/Max.png
--------------------------------------------------------------------------------
/icon/Min.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leven99/OSDA/HEAD/icon/Min.png
--------------------------------------------------------------------------------
/icon/Red.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leven99/OSDA/HEAD/icon/Red.png
--------------------------------------------------------------------------------
/icon/Close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leven99/OSDA/HEAD/icon/Close.png
--------------------------------------------------------------------------------
/icon/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leven99/OSDA/HEAD/icon/favicon.ico
--------------------------------------------------------------------------------
/icon/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leven99/OSDA/HEAD/icon/favicon.png
--------------------------------------------------------------------------------
/.gitee/PULL_REQUEST_TEMPLATE.zh-CN.md:
--------------------------------------------------------------------------------
1 | ### 引用 Issue
2 |
3 | ### Request 描述
4 |
5 | ### 测试效果
6 |
--------------------------------------------------------------------------------
/.github/pull_request_template.md:
--------------------------------------------------------------------------------
1 | ### 引用 Issue
2 |
3 | ### Request 描述
4 |
5 | ### 测试效果
6 |
--------------------------------------------------------------------------------
/Docs/source/_images/osda.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leven99/OSDA/HEAD/Docs/source/_images/osda.png
--------------------------------------------------------------------------------
/msvc/VS2019.Core/icon/Max.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leven99/OSDA/HEAD/msvc/VS2019.Core/icon/Max.png
--------------------------------------------------------------------------------
/msvc/VS2019.Core/icon/Min.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leven99/OSDA/HEAD/msvc/VS2019.Core/icon/Min.png
--------------------------------------------------------------------------------
/msvc/VS2019.Core/icon/Red.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leven99/OSDA/HEAD/msvc/VS2019.Core/icon/Red.png
--------------------------------------------------------------------------------
/msvc/VS2019.Core/icon/Close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leven99/OSDA/HEAD/msvc/VS2019.Core/icon/Close.png
--------------------------------------------------------------------------------
/Docs/source/_images/framework.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leven99/OSDA/HEAD/Docs/source/_images/framework.png
--------------------------------------------------------------------------------
/msvc/VS2017.Framework/icon/Max.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leven99/OSDA/HEAD/msvc/VS2017.Framework/icon/Max.png
--------------------------------------------------------------------------------
/msvc/VS2017.Framework/icon/Min.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leven99/OSDA/HEAD/msvc/VS2017.Framework/icon/Min.png
--------------------------------------------------------------------------------
/msvc/VS2017.Framework/icon/Red.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leven99/OSDA/HEAD/msvc/VS2017.Framework/icon/Red.png
--------------------------------------------------------------------------------
/msvc/VS2019.Core/icon/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leven99/OSDA/HEAD/msvc/VS2019.Core/icon/favicon.ico
--------------------------------------------------------------------------------
/msvc/VS2019.Core/icon/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leven99/OSDA/HEAD/msvc/VS2019.Core/icon/favicon.png
--------------------------------------------------------------------------------
/msvc/VS2019.Framework/icon/Max.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leven99/OSDA/HEAD/msvc/VS2019.Framework/icon/Max.png
--------------------------------------------------------------------------------
/msvc/VS2019.Framework/icon/Min.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leven99/OSDA/HEAD/msvc/VS2019.Framework/icon/Min.png
--------------------------------------------------------------------------------
/msvc/VS2019.Framework/icon/Red.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leven99/OSDA/HEAD/msvc/VS2019.Framework/icon/Red.png
--------------------------------------------------------------------------------
/msvc/VS2017.Framework/icon/Close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leven99/OSDA/HEAD/msvc/VS2017.Framework/icon/Close.png
--------------------------------------------------------------------------------
/msvc/VS2019.Framework/icon/Close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leven99/OSDA/HEAD/msvc/VS2019.Framework/icon/Close.png
--------------------------------------------------------------------------------
/msvc/VS2017.Framework/icon/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leven99/OSDA/HEAD/msvc/VS2017.Framework/icon/favicon.ico
--------------------------------------------------------------------------------
/msvc/VS2017.Framework/icon/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leven99/OSDA/HEAD/msvc/VS2017.Framework/icon/favicon.png
--------------------------------------------------------------------------------
/msvc/VS2019.Framework/icon/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leven99/OSDA/HEAD/msvc/VS2019.Framework/icon/favicon.ico
--------------------------------------------------------------------------------
/msvc/VS2019.Framework/icon/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leven99/OSDA/HEAD/msvc/VS2019.Framework/icon/favicon.png
--------------------------------------------------------------------------------
/.gitee/ISSUE_GUIDELINES.md:
--------------------------------------------------------------------------------
1 | ## 在你开始之前......
2 |
3 | 对于 **Bug** 的 Issue,可参考 **# Bug report** 模板书写;
4 |
5 | 对于 **Feature** 的 Issue,可参考 **# Feature request** 模板书写;
6 |
--------------------------------------------------------------------------------
/.gitee/ISSUE_TEMPLATE.zh-CN.md:
--------------------------------------------------------------------------------
1 | # Bug report
2 | ### 问题描述
3 |
4 | ### 重现步骤
5 |
6 | ### 期望效果
7 |
8 | # Feature request
9 | ### 功能描述
10 |
11 | ### 功能目的
12 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/Feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: 'feature'
6 | assignees: ''
7 | ---
8 |
9 | ## 功能描述
10 |
11 | ## 功能目的
12 |
--------------------------------------------------------------------------------
/icon/README.md:
--------------------------------------------------------------------------------
1 | ## Favicon
2 |
3 | ### 图标作者
4 | BlackVariant (Patrick)
5 |
6 | ### 图标作者网站
7 | http://blackvariant.deviantart.com/art/Button-UI-Requests-12-520378397
8 |
9 | ### 图标使用说明
10 | Free for non-commercial use
--------------------------------------------------------------------------------
/msvc/VS2017.Framework/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/msvc/VS2019.Framework/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/Bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: 'bug'
6 | assignees: ''
7 | ---
8 |
9 | ## 问题描述
10 |
11 | ## 重现步骤
12 |
13 | ## 期望效果
14 |
15 | ## 实际效果
16 |
--------------------------------------------------------------------------------
/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/msvc/VS2017.Framework/icon/README.md:
--------------------------------------------------------------------------------
1 | ## Favicon
2 |
3 | ### 图标作者
4 | BlackVariant (Patrick)
5 |
6 | ### 图标作者网站
7 | http://blackvariant.deviantart.com/art/Button-UI-Requests-12-520378397
8 |
9 | ### 图标使用说明
10 | Free for non-commercial use
--------------------------------------------------------------------------------
/msvc/VS2019.Framework/icon/README.md:
--------------------------------------------------------------------------------
1 | ## Favicon
2 |
3 | ### 图标作者
4 | BlackVariant (Patrick)
5 |
6 | ### 图标作者网站
7 | http://blackvariant.deviantart.com/art/Button-UI-Requests-12-520378397
8 |
9 | ### 图标使用说明
10 | Free for non-commercial use
--------------------------------------------------------------------------------
/Docs/source/license.rst:
--------------------------------------------------------------------------------
1 | 许可
2 | ####
3 |
4 | OSDA 是一个以 MIT 协议授权许可的串行端口调试助手(许可证可以在 `Gitee`_ 或者 `Github`_ 仓库中找到。)。
5 |
6 | .. _Gitee :
7 | https://gitee.com/leven9/OSDA/blob/master/LICENSE
8 |
9 | .. _Github :
10 | https://github.com/leven99/OSDA/blob/master/LICENSE
--------------------------------------------------------------------------------
/Docs/source/guides.rst:
--------------------------------------------------------------------------------
1 | 设计
2 | ####
3 |
4 | 架构
5 | ****
6 |
7 | .. figure:: _images/framework.png
8 | :width: 750px
9 | :align: center
10 |
11 | UI设计
12 | ******
13 |
14 | OSDA 的 UI 设计分为 7 部分:
15 |
16 | - 菜单栏
17 | - 状态栏
18 | - 接收区
19 | - 发送区
20 | - 串口配置区
21 | - 信号状态区
22 | - 辅助区
--------------------------------------------------------------------------------
/Setup/README.md:
--------------------------------------------------------------------------------
1 | ## 软件打包
2 |
3 | 软件打包使用 Inno 工具,点击 [此处](http://www.jrsoftware.org/isinfo.php) 下载安装(Inno 官方网站)。
4 |
5 | ### 支持语言
6 |
7 | * 英文
8 | * 中文
9 |
10 | 中文语言包点击 [此处](http://www.jrsoftware.org/files/istrans/) (Inno 官方网站),选择 `Chinese (Simplified)` 文件下载,移动到 `$INNO_PATH/Languages/` 目录下即可。
11 |
--------------------------------------------------------------------------------
/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Configuration;
4 | using System.Data;
5 | using System.Linq;
6 | using System.Threading.Tasks;
7 | using System.Windows;
8 |
9 | namespace OSDA
10 | {
11 | ///
12 | /// App.xaml 的交互逻辑
13 | ///
14 | public partial class App : Application
15 | {
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/ViewModels/WPFUpdateVM.cs:
--------------------------------------------------------------------------------
1 | using OSDA.Models;
2 |
3 | namespace OSDA.ViewModels
4 | {
5 | internal class WPFUpdateViewModel : MainWindowBase
6 | {
7 | public HelpModel HelpModel { get; set; }
8 |
9 | public WPFUpdateViewModel()
10 | {
11 | HelpModel = new HelpModel();
12 | HelpModel.HelpDataContext();
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Docs/README.md:
--------------------------------------------------------------------------------
1 | ## 主题
2 |
3 | 默认主题为 `sphinx_ustack_theme` ,如果计算机没有安装,请执行以下命令安装主题:
4 |
5 | ```
6 | pip install sphinx_ustack_theme
7 | ```
8 |
9 | ## 文档生成
10 |
11 | 项目文档采用 `Sphinx` 生成,`reStructuredText` 书写。
12 |
13 | * For Windows. PowerShell
14 |
15 | ```bash
16 | PS> cd OSDA/Docs
17 | PS> .\make.bat html
18 | ```
19 |
20 | * For Linux
21 |
22 | ```bash
23 | $ makefile html
24 | ```
25 |
26 | ## 在线浏览
27 | OSDA 项目文档已生成在线版本,请 [点击此处](https://leven9.gitee.io/osdadoc/) 浏览。
--------------------------------------------------------------------------------
/msvc/VS2019.Framework/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Docs/Makefile:
--------------------------------------------------------------------------------
1 | # Minimal makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line, and also
5 | # from the environment for the first two.
6 | SPHINXOPTS ?=
7 | SPHINXBUILD ?= sphinx-build
8 | SOURCEDIR = source
9 | BUILDDIR = build
10 |
11 | # Put it first so that "make" without argument is like "make help".
12 | help:
13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
14 |
15 | .PHONY: help Makefile
16 |
17 | # Catch-all target: route all unknown targets to Sphinx using the new
18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
19 | %: Makefile
20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
21 |
--------------------------------------------------------------------------------
/Docs/source/index.rst:
--------------------------------------------------------------------------------
1 | OSDA Project Documentation
2 | ##########################
3 |
4 | 这个文档是由 OSDA(Git 存储库位于 `Gitee`_ 或者 `Github`_ 中) 项目的 Docs 目录,使用 `Sphinx`_ 自动生成的(主题为 `sphinx_ustack_theme`_ )。
5 |
6 | .. _Gitee :
7 | https://gitee.com/leven9/OSDA/
8 |
9 | .. _Github :
10 | https://github.com/leven99/OSDA/
11 |
12 | .. _Sphinx :
13 | http://www.sphinx-doc.org/en/master/
14 |
15 | .. _sphinx_ustack_theme :
16 | https://github.com/unitedstack/sphinx_rtd_theme
17 |
18 | .. figure:: _images/osda.png
19 | :width: 750px
20 | :align: center
21 |
22 | .. toctree::
23 | :maxdepth: 1
24 |
25 | getting_started.rst
26 | license.rst
27 | contribute.rst
28 | guides.rst
29 | api.rst
--------------------------------------------------------------------------------
/Docs/source/getting_started.rst:
--------------------------------------------------------------------------------
1 | 入门
2 | ####
3 |
4 | OSDA 仅支持 Windows7 Service Pack 1(SP1) 及以上版本(不支持 Windows XP)。Windows7 未安装 SP1 请 `点击这里`_ 据网站页面描述下载安装(Microsoft官方网站)。
5 |
6 | .. _点击这里 :
7 | https://support.microsoft.com/zh-cn/help/15090/windows-7-install-service-pack-1-sp1
8 |
9 | 开发环境
10 | ********
11 |
12 | 需要 Microsoft .NET Framework 4.6.1。未安装请 `点击此处`_ 根据网站描述下载安装(Microsoft官方网站)。
13 |
14 | .. _点击此处 :
15 | https://dotnet.microsoft.com/download/dotnet-framework/net461
16 |
17 | 开发工具
18 | *********
19 |
20 | 支持 Visual Studio 2017 和 Visual Studio 2019。
21 |
22 | 打包工具
23 | *********
24 |
25 | 打包工具使用 `Inno`_。关于 Inno 的详细介绍和使用方法参阅 `Inno官方网站`_。
26 |
27 | .. _Inno :
28 | http://www.jrsoftware.org/isinfo.php
29 |
30 | .. _Inno官方网站 :
31 | http://www.jrsoftware.org/isinfo.php
--------------------------------------------------------------------------------
/Docs/make.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 |
3 | pushd %~dp0
4 |
5 | REM Command file for Sphinx documentation
6 |
7 | if "%SPHINXBUILD%" == "" (
8 | set SPHINXBUILD=sphinx-build
9 | )
10 | set SOURCEDIR=source
11 | set BUILDDIR=build
12 |
13 | if "%1" == "" goto help
14 |
15 | %SPHINXBUILD% >NUL 2>NUL
16 | if errorlevel 9009 (
17 | echo.
18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
19 | echo.installed, then set the SPHINXBUILD environment variable to point
20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you
21 | echo.may add the Sphinx directory to PATH.
22 | echo.
23 | echo.If you don't have Sphinx installed, grab it from
24 | echo.http://sphinx-doc.org/
25 | exit /b 1
26 | )
27 |
28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
29 | goto end
30 |
31 | :help
32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
33 |
34 | :end
35 | popd
36 |
--------------------------------------------------------------------------------
/ViewModels/MainWindowBase.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel;
2 | using System.Globalization;
3 | using System.Runtime.CompilerServices;
4 |
5 | namespace OSDA.ViewModels
6 | {
7 | internal class MainWindowBase : INotifyPropertyChanged
8 | {
9 | public event PropertyChangedEventHandler PropertyChanged;
10 |
11 | ///
12 | /// 提供区域性信息
13 | ///
14 | internal CultureInfo CultureInfos = new CultureInfo(CultureInfo.CurrentUICulture.Name);
15 |
16 | ///
17 | /// 提供属性更改事件的方法
18 | ///
19 | ///
20 | internal void RaisePropertyChanged([CallerMemberName] string propertyName = null)
21 | {
22 | var handler = PropertyChanged;
23 |
24 | if (handler != null)
25 | {
26 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Views/WPFUpdate.xaml.cs:
--------------------------------------------------------------------------------
1 | using OSDA.ViewModels;
2 | using System.Diagnostics;
3 | using System.Windows;
4 |
5 | namespace OSDA.Views
6 | {
7 | ///
8 | /// WPFUpdate.xaml 的交互逻辑
9 | ///
10 | public partial class WPFUpdate : Window
11 | {
12 | internal WPFUpdateViewModel wPFUpdateViewModel = null;
13 |
14 | public WPFUpdate()
15 | {
16 | InitializeComponent();
17 |
18 | Height = 180;
19 | Width = Height / 0.625;
20 |
21 | wPFUpdateViewModel = new WPFUpdateViewModel();
22 | DataContext = wPFUpdateViewModel;
23 | }
24 |
25 | private void UpdateYesButton_Click(object sender, RoutedEventArgs e)
26 | {
27 | Process.Start("https://leven9.gitee.io/osdaweb/download.html");
28 |
29 | Close();
30 | }
31 |
32 | private void UpdateNoButton_Click(object sender, RoutedEventArgs e)
33 | {
34 | Close();
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | ## 如何贡献
2 |
3 | 非常感谢您阅读这篇文章,这个项目需要多的志愿开发者帮助,使这个项目(软件)更加运行稳定、流畅和功能完善。
4 |
5 | ### 创建议题
6 |
7 | 在向项目创建一个 `Issue` 时,请确保包含**标题和清晰的描述**。如果有需要,请提供尽可能多的相关信息,以及代码示例或可执行测试用例,以展示未发生的预期行为。
8 |
9 | ### 提交更改
10 |
11 | 在向项目发起一个 `Pull Request` 时,请您清楚的列出您完成的具体内容(关于 `Pull Request`的更多信息请 [点击此处](https://help.github.com/cn/articles/proposing-changes-to-your-work-with-pull-requests))。
12 |
13 | 请始终为您的 `Commit` 写一条清晰的日志信息。单行的日志信息适用于小的更改。但更大的更改应如下所示:
14 |
15 | ```bash
16 | $ git commit -a -s -m "A brief summary of the commit
17 | >
18 | > A paragraph describing what changed and its impact."
19 | ```
20 |
21 | 或(建议使用 `-S` 对您的 `commit` 进行 `GPG` 签名)
22 |
23 | ```bash
24 | $ git commit -a -S -m "A brief summary of the commit
25 | >
26 | > A paragraph describing what changed and its impact."
27 | ```
28 |
29 | 对于 `A brief summary of the commit` 请遵守针对互联网公民的简单提交约定(参考:[commitizen](https://github.com/commitizen/cz-cli))。
30 |
31 | ### 编码惯例
32 |
33 | * 所有的条件代码都需要 `{}`,且 `{` 是另起一行,而不是跟随在语句后面
34 | * 所有的视图(View)使用 `xaml`
35 | * 尽可能的避免在视图(View)中包含逻辑代码
36 |
37 | ♥♥♥ 非常感谢您对 OSDA 的贡献 ♥♥♥
--------------------------------------------------------------------------------
/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // 此代码由工具生成。
4 | // 运行时版本:4.0.30319.42000
5 | //
6 | // 对此文件的更改可能会导致不正确的行为,并且如果
7 | // 重新生成代码,这些更改将会丢失。
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace OSDA.Properties {
12 |
13 |
14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.2.0.0")]
16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
17 |
18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
19 |
20 | public static Settings Default {
21 | get {
22 | return defaultInstance;
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Docs/source/contribute.rst:
--------------------------------------------------------------------------------
1 | 贡献
2 | ####
3 |
4 | 创建议题
5 | ********
6 |
7 | 在向项目创建一个 Issue 时,请确保包含标题和清晰的描述。如果有需要,请提供尽可能多的相关信息,以及代码示例或可执行测试用例,以展示未发生的预期行为。
8 |
9 | 提交更改
10 | ********
11 |
12 | 在向项目发起一个 Pull Request 时,请您清楚的列出您完成的具体内容(关于 Pull Request的更多信息请 `点击此处`_)。
13 |
14 | .. _点击此处 :
15 | https://help.github.com/cn/articles/proposing-changes-to-your-work-with-pull-requests
16 |
17 | 请始终为您的 Commit 写一条清晰的日志信息。单行的日志信息适用于小的更改。但更大的更改应如下所示:
18 |
19 | .. code-block:: Bash
20 |
21 | $ git commit -a -s -m "A brief summary of the commit
22 | >
23 | > A paragraph describing what changed and its impact."
24 |
25 | 或(建议使用 -S 选项对您的 commit 进行 GPG 签名)
26 |
27 | .. code-block:: Bash
28 |
29 | $ git commit -a -S -m "A brief summary of the commit
30 | >
31 | > A paragraph describing what changed and its impact."
32 |
33 | 对于 A brief summary of the commit 请遵守针对互联网公民的简单提交约定(参考:`commitizen`_)。
34 |
35 | .. _commitizen :
36 | https://github.com/commitizen/cz-cli
37 |
38 | 编码管理
39 | ********
40 |
41 | - 所有的条件代码都需要 {},且 { 是另起一行,而不是跟随在语句后面
42 | - 所有的视图(View)使用 xaml
43 | - 尽可能的避免在视图(View)中包含逻辑代码
--------------------------------------------------------------------------------
/Docs/source/api.rst:
--------------------------------------------------------------------------------
1 | API参考
2 | ########
3 |
4 | ITextBoxAppend
5 | ***************
6 |
7 | .. attribute:: void Delete()
8 |
9 | 移除所有字符
10 |
11 | .. attribute:: void Delete(int startIndex, int length)
12 |
13 | 从 startIndex 开始移除 length 个字符
14 |
15 | .. attribute:: void Append(string value)
16 |
17 | 追加字符串 value
18 |
19 | .. attribute:: void Append(string value, int index)
20 |
21 | 将字符串 value 插入到 index 位置
22 |
23 | .. attribute:: string GetCurrentValue()
24 |
25 | 获取当前值
26 |
27 | INotifyPropertyChanged
28 | ***********************
29 |
30 | .. attribute:: public void RaisePropertyChanged([CallerMemberName] string propertyName = "")
31 |
32 | 提示属性已经更改
33 |
34 | .. code-block:: C#
35 |
36 | public ITextBoxAppend _RecvData;
37 | public ITextBoxAppend RecvData
38 | {
39 | get
40 | {
41 | return _RecvData;
42 | }
43 | set
44 | {
45 | if (_RecvData != value)
46 | {
47 | _RecvData = value;
48 | RaisePropertyChanged(nameof(RecvData));
49 | }
50 | }
51 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Cao Liwen
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Resources;
3 | using System.Runtime.CompilerServices;
4 | using System.Runtime.InteropServices;
5 | using System.Windows;
6 |
7 | // 有关程序集的一般信息由以下
8 | // 控制。更改这些特性值可修改
9 | // 与程序集关联的信息。
10 | [assembly: AssemblyTitle("OSDA")]
11 | [assembly: AssemblyDescription("The Open Source Serial Port Debug Assistant")]
12 | [assembly: AssemblyConfiguration("")]
13 | [assembly: AssemblyCompany("")]
14 | [assembly: AssemblyProduct("OSDA")]
15 | [assembly: AssemblyCopyright("Copyright (C) 2019 Cao Liwen")]
16 | [assembly: AssemblyTrademark("")]
17 | [assembly: AssemblyCulture("")]
18 |
19 | // 将 ComVisible 设置为 false 会使此程序集中的类型
20 | // 对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
21 | // 请将此类型的 ComVisible 特性设置为 true。
22 | [assembly: ComVisible(false)]
23 |
24 | // 若要开始生成可本地化的应用程序,请设置
25 | // .csproj 文件中的 CultureYouAreCodingWith
26 | // 例如,如果您在源文件中使用的是美国英语,
27 | // 使用的是美国英语,请将 设置为 en-US。 然后取消
28 | // 对以下 NeutralResourceLanguage 特性的注释。 更新
29 | // 以下行中的“en-US”以匹配项目文件中的 UICulture 设置。
30 |
31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
32 |
33 | [assembly: ThemeInfo(
34 | // 主题特定资源词典所处位置(未在页面中找到资源时使用,或应用程序资源字典中找到时使用)
35 | ResourceDictionaryLocation.None,
36 | // 常规资源词典所处位置(未在页面中找到资源时使用,或应用程序或任何主题专用资源字典中找到时使用)
37 | ResourceDictionaryLocation.SourceAssembly
38 | )]
39 |
40 |
41 | // 程序集的版本信息由下列四个值组成:
42 | // 主版本
43 | // 次版本
44 | // 生成号
45 | // 修订号
46 | // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号方法是按如下所示使用“*”: :
47 | // [assembly: AssemblyVersion("1.0.*")]
48 | [assembly: AssemblyVersion("3.5.0.29")]
49 | [assembly: AssemblyFileVersion("3.5.0.29")]
50 | [assembly: NeutralResourcesLanguage("zh-Hans")]
51 |
--------------------------------------------------------------------------------
/msvc/OSDA2017.Framework.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.28307.572
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ODSA", "VS2017.Framework\ODSA.csproj", "{71C6AC13-4E18-44E7-AFBC-97BED2BDAB7E}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Debug|x64 = Debug|x64
12 | Debug|x86 = Debug|x86
13 | Release|Any CPU = Release|Any CPU
14 | Release|x64 = Release|x64
15 | Release|x86 = Release|x86
16 | EndGlobalSection
17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
18 | {71C6AC13-4E18-44E7-AFBC-97BED2BDAB7E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
19 | {71C6AC13-4E18-44E7-AFBC-97BED2BDAB7E}.Debug|Any CPU.Build.0 = Debug|Any CPU
20 | {71C6AC13-4E18-44E7-AFBC-97BED2BDAB7E}.Debug|x64.ActiveCfg = Debug|x64
21 | {71C6AC13-4E18-44E7-AFBC-97BED2BDAB7E}.Debug|x64.Build.0 = Debug|x64
22 | {71C6AC13-4E18-44E7-AFBC-97BED2BDAB7E}.Debug|x86.ActiveCfg = Debug|x86
23 | {71C6AC13-4E18-44E7-AFBC-97BED2BDAB7E}.Debug|x86.Build.0 = Debug|x86
24 | {71C6AC13-4E18-44E7-AFBC-97BED2BDAB7E}.Release|Any CPU.ActiveCfg = Release|Any CPU
25 | {71C6AC13-4E18-44E7-AFBC-97BED2BDAB7E}.Release|Any CPU.Build.0 = Release|Any CPU
26 | {71C6AC13-4E18-44E7-AFBC-97BED2BDAB7E}.Release|x64.ActiveCfg = Release|x64
27 | {71C6AC13-4E18-44E7-AFBC-97BED2BDAB7E}.Release|x64.Build.0 = Release|x64
28 | {71C6AC13-4E18-44E7-AFBC-97BED2BDAB7E}.Release|x86.ActiveCfg = Release|x86
29 | {71C6AC13-4E18-44E7-AFBC-97BED2BDAB7E}.Release|x86.Build.0 = Release|x86
30 | EndGlobalSection
31 | GlobalSection(SolutionProperties) = preSolution
32 | HideSolutionNode = FALSE
33 | EndGlobalSection
34 | GlobalSection(ExtensibilityGlobals) = postSolution
35 | SolutionGuid = {BD1BD510-5EED-4292-9402-2FD84F6B951D}
36 | EndGlobalSection
37 | EndGlobal
38 |
--------------------------------------------------------------------------------
/msvc/OSDA2019.Core.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.29403.142
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OSDA", "VS2019.Core\OSDA.csproj", "{4626E3E4-8C98-4840-8656-F445C87168BD}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Debug|x64 = Debug|x64
12 | Debug|x86 = Debug|x86
13 | Release|Any CPU = Release|Any CPU
14 | Release|x64 = Release|x64
15 | Release|x86 = Release|x86
16 | EndGlobalSection
17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
18 | {4626E3E4-8C98-4840-8656-F445C87168BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
19 | {4626E3E4-8C98-4840-8656-F445C87168BD}.Debug|Any CPU.Build.0 = Debug|Any CPU
20 | {4626E3E4-8C98-4840-8656-F445C87168BD}.Debug|x64.ActiveCfg = Debug|x64
21 | {4626E3E4-8C98-4840-8656-F445C87168BD}.Debug|x64.Build.0 = Debug|x64
22 | {4626E3E4-8C98-4840-8656-F445C87168BD}.Debug|x86.ActiveCfg = Debug|x86
23 | {4626E3E4-8C98-4840-8656-F445C87168BD}.Debug|x86.Build.0 = Debug|x86
24 | {4626E3E4-8C98-4840-8656-F445C87168BD}.Release|Any CPU.ActiveCfg = Release|Any CPU
25 | {4626E3E4-8C98-4840-8656-F445C87168BD}.Release|Any CPU.Build.0 = Release|Any CPU
26 | {4626E3E4-8C98-4840-8656-F445C87168BD}.Release|x64.ActiveCfg = Release|x64
27 | {4626E3E4-8C98-4840-8656-F445C87168BD}.Release|x64.Build.0 = Release|x64
28 | {4626E3E4-8C98-4840-8656-F445C87168BD}.Release|x86.ActiveCfg = Release|x86
29 | {4626E3E4-8C98-4840-8656-F445C87168BD}.Release|x86.Build.0 = Release|x86
30 | EndGlobalSection
31 | GlobalSection(SolutionProperties) = preSolution
32 | HideSolutionNode = FALSE
33 | EndGlobalSection
34 | GlobalSection(ExtensibilityGlobals) = postSolution
35 | SolutionGuid = {F95CD414-EC14-4BF2-9C29-8765A6B1424A}
36 | EndGlobalSection
37 | EndGlobal
38 |
--------------------------------------------------------------------------------
/msvc/OSDA2019.Framework.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.29215.179
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OSDA", "VS2019.Framework\OSDA.csproj", "{4626E3E4-8C98-4840-8656-F445C87168BD}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Debug|x64 = Debug|x64
12 | Debug|x86 = Debug|x86
13 | Release|Any CPU = Release|Any CPU
14 | Release|x64 = Release|x64
15 | Release|x86 = Release|x86
16 | EndGlobalSection
17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
18 | {4626E3E4-8C98-4840-8656-F445C87168BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
19 | {4626E3E4-8C98-4840-8656-F445C87168BD}.Debug|Any CPU.Build.0 = Debug|Any CPU
20 | {4626E3E4-8C98-4840-8656-F445C87168BD}.Debug|x64.ActiveCfg = Debug|x64
21 | {4626E3E4-8C98-4840-8656-F445C87168BD}.Debug|x64.Build.0 = Debug|x64
22 | {4626E3E4-8C98-4840-8656-F445C87168BD}.Debug|x86.ActiveCfg = Debug|x86
23 | {4626E3E4-8C98-4840-8656-F445C87168BD}.Debug|x86.Build.0 = Debug|x86
24 | {4626E3E4-8C98-4840-8656-F445C87168BD}.Release|Any CPU.ActiveCfg = Release|Any CPU
25 | {4626E3E4-8C98-4840-8656-F445C87168BD}.Release|Any CPU.Build.0 = Release|Any CPU
26 | {4626E3E4-8C98-4840-8656-F445C87168BD}.Release|x64.ActiveCfg = Release|x64
27 | {4626E3E4-8C98-4840-8656-F445C87168BD}.Release|x64.Build.0 = Release|x64
28 | {4626E3E4-8C98-4840-8656-F445C87168BD}.Release|x86.ActiveCfg = Release|x86
29 | {4626E3E4-8C98-4840-8656-F445C87168BD}.Release|x86.Build.0 = Release|x86
30 | EndGlobalSection
31 | GlobalSection(SolutionProperties) = preSolution
32 | HideSolutionNode = FALSE
33 | EndGlobalSection
34 | GlobalSection(ExtensibilityGlobals) = postSolution
35 | SolutionGuid = {47B04B72-685D-44E0-9C03-677ED03900FA}
36 | EndGlobalSection
37 | EndGlobal
38 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## OSDA - The Open Serial Debug Assistant
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | 
10 |
11 | ## 架构
12 |
13 | 软件支持 WPF [Microsoft .NET Framework 4.6.1](https://dotnet.microsoft.com/download/dotnet-framework/net461) 和 WPF [Microsoft .NET Core 3.1]( https://dotnet.microsoft.com/download/dotnet-core/3.1 ) 两种框架,使用 MVVM 模型开发。
14 |
15 | 
16 |
17 | ## 功能
18 |
19 | - [x] 基础功能(打开、关闭、接收、发送、清接收区、清发送区和清空计数)
20 | - [x] 十六进制(HEX)接收,十六进制(HEX)发送
21 | - [x] 自动发送
22 | - [x] 保存接收数据(可自定义保存位置)
23 | - [x] 发送文件
24 | - [x] 编码方式(ASCII,UTF-8,UTF-16,UTF-32)
25 | - [x] 流控制(握手协议、控制协议)
26 | - [x] 暂停接收
27 | - [x] 发送新行(三种换行符)
28 | - [x] 信号控制(RTS,STR)
29 | - [x] 信号检测(DCD,CTS,DSR)
30 | - [x] 在线更新
31 | - [x] 精简视图(只保留接收区和发送区)
32 | - [ ] 全球化和本地化
33 |
34 | #### 串口属性
35 |
36 | * 串行端口传输前后的默认编码方式为 UTF-8
37 | * 串行端口输入缓冲区大小配置为 2MB
38 | * 串行端口输出缓冲区大小配置为 1MB
39 | * 串行端口默认流控制为 None(无控制流)
40 | * 串行端口信号控制 Rts 和 Dtr 默认均未启用
41 |
42 | ## 安装
43 |
44 | #### 先决条件
45 |
46 | 1. 仅支持 `Windows7 Service Pack 1(SP1)` 及以上版本(不支持 `Windows XP`)。`Windows7` 未安装 `SP1` 请 [点击此处](https://support.microsoft.com/zh-cn/help/15090/windows-7-install-service-pack-1-sp1) 根据网站页面描述下载安装(Microsoft官方网站)。
47 |
48 | 2. 已安装 `Microsoft .NET Framework 4.6.1` 。未安装请 [点击此处](https://dotnet.microsoft.com/download/dotnet-framework/net461) 根据网站描述下载安装(Microsoft官方网站)。
49 |
50 | #### For Windows
51 |
52 | 下载最新的 [OSDA 安装程序](https://leven9.gitee.io/osdaweb/download.html)。可以选择从 `Gitee` 或 `Github` 站点下载。
53 |
54 | ## 编译
55 |
56 | #### For Windows
57 |
58 | - [x] VS2017(仅支持 .Framework 框架)
59 | - [x] VS2019(支持 .Framework 和 .Core 两种框架)
60 |
61 | ```bash
62 | $ git clone https://gitee.com/leven9/OSDA.git
63 | $ cd OSDA/msvc
64 | ```
65 | * 对于 VS2017 ,双击 `OSDA2017.Framework.sln`
66 | * 对于 VS2019 ` .Framework` 框架,双击 `OSDA2019.Framework.sln`
67 | * 对于 VS2019 `.Core` 框架,双击 `OSDA2019.Core.sln`
68 |
69 | ## 贡献
70 |
71 | 请参阅项目的贡献者指南(贡献者指南可以在 [GitHub](https://github.com/leven99/OSDA/blob/master/CONTRIBUTING.md) 或 [Gitee](https://gitee.com/leven9/OSDA/blob/master/CONTRIBUTING.md) 中找到)。
72 |
73 | ## License
74 |
75 | 软件采用 MIT License 授权(授权许可证可以在 [Github](https://github.com/leven99/OSDA) 或 [Gitee](https://gitee.com/leven9/OSDA) 中找到)。
--------------------------------------------------------------------------------
/Views/WPFUpdate.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
36 |
41 |
45 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // 此代码由工具生成。
4 | // 运行时版本:4.0.30319.42000
5 | //
6 | // 对此文件的更改可能会导致不正确的行为,并且如果
7 | // 重新生成代码,这些更改将会丢失。
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace OSDA.Properties {
12 | using System;
13 |
14 |
15 | ///
16 | /// 一个强类型的资源类,用于查找本地化的字符串等。
17 | ///
18 | // 此类是由 StronglyTypedResourceBuilder
19 | // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
20 | // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
21 | // (以 /str 作为命令选项),或重新生成 VS 项目。
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources() {
33 | }
34 |
35 | ///
36 | /// 返回此类使用的缓存的 ResourceManager 实例。
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | internal static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("OSDA.Properties.Resources", typeof(Resources).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// 重写当前线程的 CurrentUICulture 属性
51 | /// 重写当前线程的 CurrentUICulture 属性。
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | internal static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/Models/TimerM.cs:
--------------------------------------------------------------------------------
1 | using OSDA.ViewModels;
2 | using System;
3 | using System.Timers;
4 |
5 | namespace OSDA.Models
6 | {
7 | internal class TimerModel : MainWindowBase
8 | {
9 | #region 字段
10 | private static Timer SystemTimer = null; /* 该对象持续存在于整个应用程序运行期间 */
11 | #endregion
12 |
13 | ///
14 | /// 菜单栏 - 时间戳
15 | ///
16 | private bool _TimeStampEnable;
17 | public bool TimeStampEnable
18 | {
19 | get
20 | {
21 | return _TimeStampEnable;
22 | }
23 | set
24 | {
25 | if (_TimeStampEnable != value)
26 | {
27 | _TimeStampEnable = value;
28 | RaisePropertyChanged(nameof(TimeStampEnable));
29 | }
30 | }
31 | }
32 |
33 | ///
34 | /// 状态栏 - 系统时间
35 | ///
36 | private string _SystemTime;
37 | public string SystemTime
38 | {
39 | get
40 | {
41 | return _SystemTime;
42 | }
43 | set
44 | {
45 | if (_SystemTime != value)
46 | {
47 | _SystemTime = value;
48 | RaisePropertyChanged(nameof(SystemTime));
49 | }
50 | }
51 | }
52 |
53 | public void InitSystemClockTimer()
54 | {
55 | SystemTimer = new Timer
56 | {
57 | Interval = 1000
58 | };
59 |
60 | SystemTimer.Elapsed += SystemTimer_Elapsed;
61 | SystemTimer.AutoReset = true;
62 | SystemTimer.Enabled = true;
63 | }
64 |
65 | private void SystemTimer_Elapsed(object sender, ElapsedEventArgs e)
66 | {
67 | SystemTime = SystemTimeData();
68 | }
69 |
70 | private string SystemTimeData()
71 | {
72 | DateTime _DateTime = DateTime.Now;
73 |
74 | return string.Format(CultureInfos, "{0}年{1}月{2}日 {3}:{4}:{5}",
75 | _DateTime.Year.ToString("0000", CultureInfos),
76 | _DateTime.Month.ToString("00", CultureInfos),
77 | _DateTime.Day.ToString("00", CultureInfos),
78 | _DateTime.Hour.ToString("00", CultureInfos),
79 | _DateTime.Minute.ToString("00", CultureInfos),
80 | _DateTime.Second.ToString("00", CultureInfos));
81 | }
82 |
83 | public void TimerDataContext()
84 | {
85 | TimeStampEnable = false;
86 |
87 | SystemTime = string.Format(CultureInfos, "2019年08月31日 12:13:15");
88 | InitSystemClockTimer();
89 | }
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/Setup/OSDA_Inno_Setup.iss:
--------------------------------------------------------------------------------
1 | ; Script generated by the Inno Setup Script Wizard.
2 | ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
3 |
4 | #define MyAppName "OSDA"
5 | #define MyAppVersion "3.5.0"
6 | #define MyVersionInfoVersion "3.5.0.29"
7 | #define MyAppExeName "OSDA.exe"
8 | #define MyAppCopyright "Copyright (C) 2019 Cao Liwen"
9 | #define MyAppPublisher "Cao Liwen"
10 |
11 | ; x64(64bit) and x86(32 bit)
12 | #define x_64
13 |
14 | ; Visual Studio 2017 and Visual Studio 2019
15 | ;#define VS2017
16 |
17 | [Setup]
18 | AppId={{CD6994CA-F69D-4B27-A1EC-1E34684AE73A}
19 | AppName={#MyAppName}
20 | AppVersion={#MyAppVersion}
21 | AppVerName={#MyAppName} {#MyAppVersion}
22 | VersionInfoVersion={#MyVersionInfoVersion}
23 | AppPublisher={#MyAppPublisher}
24 | AppCopyright={#MyAppCopyright}
25 | DefaultDirName={commonpf}\{#MyAppName}
26 | DefaultGroupName=OSDA
27 | DisableProgramGroupPage=auto
28 | OutputDir=.\
29 | SetupIconFile=..\icon\favicon.ico
30 | #ifdef x_64
31 | ArchitecturesInstallIn64BitMode=x64
32 | OutputBaseFilename=OSDA_Windows_Framework_V{#MyAppVersion}_x64
33 | #else
34 | OutputBaseFilename=OSDA_Windows_Framework_V{#MyAppVersion}_x86
35 | #endif
36 | Compression=lzma
37 | SolidCompression=yes
38 | WizardStyle=modern
39 |
40 | [Languages]
41 | Name: "english"; MessagesFile: "compiler:Default.isl"
42 | Name: "chinesesimplified"; MessagesFile: "compiler:Languages\ChineseSimplified.isl"
43 |
44 | [Tasks]
45 | Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
46 |
47 | [Files]
48 | Source: "..\LICENSE"; DestDir: "{app}"; Flags: ignoreversion
49 |
50 | ; Visual Studio 2017
51 | #ifdef VS2017
52 | #ifdef x_64
53 | Source: "..\msvc\VS2017.Framework\bin\x64\Release\OSDA.exe"; DestDir: "{app}"; Flags: ignoreversion
54 | Source: "..\msvc\VS2017.Framework\bin\x64\Release\OSDA.exe.config"; DestDir: "{app}"; Flags: ignoreversion
55 | #else
56 | Source: "..\msvc\VS2017.Framework\bin\x86\Release\OSDA.exe"; DestDir: "{app}"; Flags: ignoreversion
57 | Source: "..\msvc\VS2017.Framework\bin\x86\Release\OSDA.exe.config"; DestDir: "{app}"; Flags: ignoreversion
58 | #endif
59 |
60 | ; Visual Studio 2019
61 | #else
62 | #ifdef x_64
63 | Source: "..\msvc\VS2019.Framework\bin\x64\Release\OSDA.exe"; DestDir: "{app}"; Flags: ignoreversion
64 | Source: "..\msvc\VS2019.Framework\bin\x64\Release\OSDA.exe.config"; DestDir: "{app}"; Flags: ignoreversion
65 | #else
66 | Source: "..\msvc\VS2019.Framework\bin\x86\Release\OSDA.exe"; DestDir: "{app}"; Flags: ignoreversion
67 | Source: "..\msvc\VS2019.Framework\bin\x86\Release\OSDA.exe.config"; DestDir: "{app}"; Flags: ignoreversion
68 | #endif
69 | #endif
70 |
71 | [Icons]
72 | Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
73 | Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}"
74 | Name: "{commondesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
75 |
76 | [Run]
77 | Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent
--------------------------------------------------------------------------------
/Docs/source/conf.py:
--------------------------------------------------------------------------------
1 | # Configuration file for the Sphinx documentation builder.
2 | #
3 | # This file only contains a selection of the most common options. For a full
4 | # list see the documentation:
5 | # http://www.sphinx-doc.org/en/master/config
6 |
7 | # -- Path setup --------------------------------------------------------------
8 |
9 | # If extensions (or modules to document with autodoc) are in another directory,
10 | # add these directories to sys.path here. If the directory is relative to the
11 | # documentation root, use os.path.abspath to make it absolute, like shown here.
12 | import os
13 | import sys
14 |
15 | # -- Project information -----------------------------------------------------
16 |
17 | project = u'OSDA Project'
18 | copyright = u'2019, OSDA Project members and individual contributors'
19 | author = u'The OSDA Project'
20 |
21 | # The short X.Y version
22 | version = '3.5.0'
23 | # The full version, including alpha/beta/rc tags
24 | release = '3.5.0'
25 |
26 | # -- General configuration ---------------------------------------------------
27 |
28 | # Add any Sphinx extension module names here, as strings. They can be
29 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
30 | # ones.
31 | extensions = [
32 | ]
33 |
34 | # Add any paths that contain templates here, relative to this directory.
35 | templates_path = ['_templates']
36 |
37 | # The suffix(es) of source filenames.
38 | # You can specify multiple suffix as a list of string:
39 | source_suffix = '.rst'
40 |
41 | # List of patterns, relative to source directory, that match files and
42 | # directories to ignore when looking for source files.
43 | # This pattern also affects html_static_path and html_extra_path.
44 | exclude_patterns = [ ]
45 |
46 | # The name of the Pygments (syntax highlighting) style to use.
47 | pygments_style = None
48 |
49 | # -- Options for HTML output -------------------------------------------------
50 |
51 | # The theme to use for HTML and HTML Help pages. See the documentation for
52 | # a list of builtin themes.
53 | import sphinx_ustack_theme
54 | html_theme = 'sphinx_ustack_theme'
55 |
56 | # The name of an image file (within the static path) to use as favicon of the
57 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
58 | # pixels large.
59 | html_favicon = '../../icon/favicon.ico'
60 |
61 | # Add any paths that contain custom static files (such as style sheets) here,
62 | # relative to this directory. They are copied after the builtin static files,
63 | # so a file named "default.css" will overwrite the builtin "default.css".
64 | html_static_path = ['_static']
65 |
66 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
67 | # using the given strftime format.
68 | html_last_updated_fmt = '%b %d, %Y'
69 |
70 | # If true, links to the reST sources are added to the pages.
71 | html_show_sourcelink = False
72 |
73 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
74 | html_show_sphinx = True
75 |
76 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
77 | html_show_copyright = True
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to make participation in our project and
7 | our community a harassment-free experience for everyone, regardless of age, body
8 | size, disability, ethnicity, sex characteristics, gender identity and expression,
9 | level of experience, education, socio-economic status, nationality, personal
10 | appearance, race, religion, or sexual identity and orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behavior that contributes to creating a positive environment
15 | include:
16 |
17 | * Using welcoming and inclusive language
18 | * Being respectful of differing viewpoints and experiences
19 | * Gracefully accepting constructive criticism
20 | * Focusing on what is best for the community
21 | * Showing empathy towards other community members
22 |
23 | Examples of unacceptable behavior by participants include:
24 |
25 | * The use of sexualized language or imagery and unwelcome sexual attention or
26 | advances
27 | * Trolling, insulting/derogatory comments, and personal or political attacks
28 | * Public or private harassment
29 | * Publishing others' private information, such as a physical or electronic
30 | address, without explicit permission
31 | * Other conduct which could reasonably be considered inappropriate in a
32 | professional setting
33 |
34 | ## Our Responsibilities
35 |
36 | Project maintainers are responsible for clarifying the standards of acceptable
37 | behavior and are expected to take appropriate and fair corrective action in
38 | response to any instances of unacceptable behavior.
39 |
40 | Project maintainers have the right and responsibility to remove, edit, or
41 | reject comments, commits, code, wiki edits, issues, and other contributions
42 | that are not aligned to this Code of Conduct, or to ban temporarily or
43 | permanently any contributor for other behaviors that they deem inappropriate,
44 | threatening, offensive, or harmful.
45 |
46 | ## Scope
47 |
48 | This Code of Conduct applies within all project spaces, and it also applies when
49 | an individual is representing the project or its community in public spaces.
50 | Examples of representing a project or community include using an official
51 | project e-mail address, posting via an official social media account, or acting
52 | as an appointed representative at an online or offline event. Representation of
53 | a project may be further defined and clarified by project maintainers.
54 |
55 | ## Enforcement
56 |
57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
58 | reported by contacting the project team at . All
59 | complaints will be reviewed and investigated and will result in a response that
60 | is deemed necessary and appropriate to the circumstances. The project team is
61 | obligated to maintain confidentiality with regard to the reporter of an incident.
62 | Further details of specific enforcement policies may be posted separately.
63 |
64 | Project maintainers who do not follow or enforce the Code of Conduct in good
65 | faith may face temporary or permanent repercussions as determined by other
66 | members of the project's leadership.
67 |
68 | ## Attribution
69 |
70 | This Code of Conduct is adapted from the [Contributor Covenant][https://www.contributor-covenant.org], version 1.4,
71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
72 |
73 | For answers to common questions about this code of conduct, see
74 | https://www.contributor-covenant.org/faq
--------------------------------------------------------------------------------
/Interface/ITextBoxAppend.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text;
3 |
4 | namespace OSDA.Interfaces
5 | {
6 | public interface ITextBoxAppend
7 | {
8 | ///
9 | /// 移除所有字符
10 | ///
11 | void Delete();
12 |
13 | ///
14 | /// 从startIndex开始移除length个字符
15 | ///
16 | ///
17 | ///
18 | void Delete(int startIndex, int length);
19 |
20 | ///
21 | /// 追加字符串
22 | ///
23 | ///
24 | void Append(string value);
25 |
26 | ///
27 | /// 将字符串插入到指定位置
28 | ///
29 | ///
30 | ///
31 | void Append(string value, int index);
32 |
33 | ///
34 | /// 获取当前值
35 | ///
36 | ///
37 | string GetCurrentValue();
38 |
39 | ///
40 | /// 移除所有字符事件的处理方法
41 | ///
42 | event EventHandler BufferClearingHandler;
43 |
44 | ///
45 | /// 追加字符串事件的处理方法
46 | ///
47 | event EventHandler BufferAppendedHandler;
48 | }
49 |
50 | #region 接口实现
51 | public class IClassTextBoxAppend : ITextBoxAppend
52 | {
53 | readonly StringBuilder stringBuilder = new StringBuilder();
54 |
55 | readonly BufferClearingHandlerEventArgs bufferClearingHandlerEventArgs =
56 | new BufferClearingHandlerEventArgs();
57 |
58 | readonly BufferAppendedHandlerEventArgs bufferAppendedHandlerEventArgs =
59 | new BufferAppendedHandlerEventArgs();
60 |
61 | public void Delete()
62 | {
63 | stringBuilder.Clear();
64 |
65 | System.Windows.Application.Current.Dispatcher.Invoke(() =>
66 | {
67 | BufferClearingHandler(this, bufferClearingHandlerEventArgs);
68 | });
69 | }
70 |
71 | public void Delete(int startIndex, int length)
72 | {
73 | stringBuilder.Remove(startIndex, length);
74 | }
75 |
76 | public void Append(string value)
77 | {
78 | stringBuilder.Append(value);
79 |
80 | bufferAppendedHandlerEventArgs.AppendedText = value;
81 |
82 | System.Windows.Application.Current.Dispatcher.Invoke(() =>
83 | {
84 | BufferAppendedHandler(this, bufferAppendedHandlerEventArgs);
85 | });
86 | }
87 |
88 | public void Append(string value, int index)
89 | {
90 | if (index == stringBuilder.Length)
91 | {
92 | stringBuilder.Append(value);
93 | }
94 | else
95 | {
96 | stringBuilder.Insert(index, value);
97 | }
98 | }
99 |
100 | public string GetCurrentValue()
101 | {
102 | return stringBuilder.ToString();
103 | }
104 |
105 | public event EventHandler BufferClearingHandler;
106 |
107 | public event EventHandler BufferAppendedHandler;
108 | }
109 |
110 | public class BufferClearingHandlerEventArgs : EventArgs
111 | {
112 | public string ClearingText { get; set; }
113 | }
114 |
115 | public class BufferAppendedHandlerEventArgs : EventArgs
116 | {
117 | public string AppendedText { get; set; }
118 | }
119 | #endregion
120 | }
121 |
--------------------------------------------------------------------------------
/Models/RecvM.cs:
--------------------------------------------------------------------------------
1 | using OSDA.Interfaces;
2 | using OSDA.ViewModels;
3 |
4 | namespace OSDA.Models
5 | {
6 | internal class RecvModel : MainWindowBase
7 | {
8 | #region 接收区 - Header
9 | ///
10 | /// 接收区Header中的接收计数
11 | ///
12 | private int _RecvDataCount;
13 | public int RecvDataCount
14 | {
15 | get
16 | {
17 | return _RecvDataCount;
18 | }
19 | set
20 | {
21 | if (_RecvDataCount != value)
22 | {
23 | _RecvDataCount = value;
24 | RaisePropertyChanged(nameof(RecvDataCount));
25 | }
26 | }
27 | }
28 |
29 | ///
30 | /// 接收区Header中的 [保存中/已停止] 字符串
31 | ///
32 | private string _RecvAutoSave;
33 | public string RecvAutoSave
34 | {
35 | get
36 | {
37 | return _RecvAutoSave;
38 | }
39 | set
40 | {
41 | if (_RecvAutoSave != value)
42 | {
43 | _RecvAutoSave = value;
44 | RaisePropertyChanged(nameof(RecvAutoSave));
45 | }
46 | }
47 | }
48 |
49 | ///
50 | /// 接收区Header中的 [允许/暂停] 字符串
51 | ///
52 | private string _RecvEnable;
53 | public string RecvEnable
54 | {
55 | get
56 | {
57 | return _RecvEnable;
58 | }
59 | set
60 | {
61 | if (_RecvEnable != value)
62 | {
63 | _RecvEnable = value;
64 | RaisePropertyChanged(nameof(RecvEnable));
65 | }
66 | }
67 | }
68 | #endregion
69 |
70 | ///
71 | /// 接收区 - 允许/暂停 接收数据
72 | ///
73 | private bool _EnableRecv;
74 | public bool EnableRecv
75 | {
76 | get
77 | {
78 | return _EnableRecv;
79 | }
80 | set
81 | {
82 | if(_EnableRecv != value)
83 | {
84 | _EnableRecv = value;
85 | RaisePropertyChanged(nameof(EnableRecv));
86 | }
87 | }
88 | }
89 |
90 | private ITextBoxAppend _RecvData;
91 | public ITextBoxAppend RecvData
92 | {
93 | get
94 | {
95 | return _RecvData;
96 | }
97 | set
98 | {
99 | if (_RecvData != value)
100 | {
101 | _RecvData = value;
102 | RaisePropertyChanged(nameof(RecvData));
103 | }
104 | }
105 | }
106 |
107 | ///
108 | /// 辅助区 - 十六进制接收
109 | ///
110 | private bool _HexRecv;
111 | public bool HexRecv
112 | {
113 | get
114 | {
115 | return _HexRecv;
116 | }
117 | set
118 | {
119 | if (_HexRecv != value)
120 | {
121 | _HexRecv = value;
122 | RaisePropertyChanged(nameof(HexRecv));
123 | }
124 | }
125 | }
126 |
127 | public void RecvDataContext()
128 | {
129 | RecvData = new IClassTextBoxAppend();
130 |
131 | RecvDataCount = 0;
132 | RecvAutoSave = string.Format(CultureInfos, "已停止");
133 | RecvEnable = string.Format(CultureInfos, " 提示:双击文本框更改接收状态 ");
134 |
135 | EnableRecv = true;
136 | HexRecv = false;
137 | }
138 | }
139 | }
140 |
--------------------------------------------------------------------------------
/msvc/VS2019.Core/OSDA.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | WinExe
4 | netcoreapp3.1
5 | true
6 | icon\favicon.ico
7 | AnyCPU;x64;x86
8 | Cao Liwen
9 | The Open Source Serial Port Debug Assistant
10 | Copyright (C) 2019 Cao Liwen
11 | zh-Hans
12 | 3.3.0.23
13 | 3.3.0.23
14 |
15 | 3.3.0.23
16 |
17 |
18 |
19 | all
20 | runtime; build; native; contentfiles; analyzers; buildtransitive
21 |
22 |
23 |
24 |
25 |
26 | MSBuild:Compile
27 | Designer
28 | App.xaml
29 |
30 |
31 | MSBuild:Compile
32 | Designer
33 | Views\MainWindow.xaml
34 |
35 |
36 | MSBuild:Compile
37 | Designer
38 | Views\WPFUpdate.xaml
39 |
40 |
41 | App.xaml
42 | Code
43 | App.xaml.cs
44 |
45 |
46 | MainWindow.xaml
47 | Code
48 | Views\MainWindow.xaml.cs
49 |
50 |
51 | WPFUpdate.xaml
52 | Code
53 | Views\WPFUpdate.xaml.cs
54 |
55 |
56 | Interface\ITextBoxAppend.cs
57 |
58 |
59 | ViewModels\MainWindowBase.cs
60 |
61 |
62 | ViewModels\MainWindowVM.cs
63 |
64 |
65 | ViewModels\WPFUpdateVM.cs
66 |
67 |
68 | Models\TimerM.cs
69 |
70 |
71 | Models\HelpM.cs
72 |
73 |
74 | Models\RecvM.cs
75 |
76 |
77 | Models\SendM.cs
78 |
79 |
80 | Models\SerialPortM.cs
81 |
82 |
83 |
84 |
85 | icon\favicon.ico
86 |
87 |
88 | icon\Close.png
89 |
90 |
91 | icon\favicon.png
92 |
93 |
94 | icon\Max.png
95 |
96 |
97 | icon\Min.png
98 |
99 |
100 | icon\Red.png
101 |
102 |
103 |
104 |
--------------------------------------------------------------------------------
/Models/SendM.cs:
--------------------------------------------------------------------------------
1 | using OSDA.ViewModels;
2 |
3 | namespace OSDA.Models
4 | {
5 | internal class SendModel : MainWindowBase
6 | {
7 | ///
8 | /// 发送区Header中的发送计数
9 | ///
10 | private int _SendDataCount;
11 | public int SendDataCount
12 | {
13 | get
14 | {
15 | return _SendDataCount;
16 | }
17 | set
18 | {
19 | if (_SendDataCount != value)
20 | {
21 | _SendDataCount = value;
22 | RaisePropertyChanged(nameof(SendDataCount));
23 | }
24 | }
25 | }
26 |
27 | private string _SendData;
28 | public string SendData
29 | {
30 | get
31 | {
32 | return _SendData;
33 | }
34 | set
35 | {
36 | if (_SendData != value)
37 | {
38 | _SendData = value;
39 | RaisePropertyChanged(nameof(SendData));
40 | }
41 | }
42 | }
43 |
44 | ///
45 | /// 辅助区 - 自送发送的时间间隔
46 | ///
47 | private string _AutoSendNum;
48 | public string AutoSendNum
49 | {
50 | get
51 | {
52 | return _AutoSendNum;
53 | }
54 | set
55 | {
56 | if (_AutoSendNum != value)
57 | {
58 | _AutoSendNum = value;
59 | RaisePropertyChanged(nameof(AutoSendNum));
60 | }
61 | }
62 | }
63 |
64 | #region 菜单栏 - 选项 - 发送换行
65 | private bool _NonesEnable;
66 | public bool NonesEnable
67 | {
68 | get
69 | {
70 | return _NonesEnable;
71 | }
72 | set
73 | {
74 | if (_NonesEnable != value)
75 | {
76 | _NonesEnable = value;
77 | RaisePropertyChanged(nameof(NonesEnable));
78 | }
79 | }
80 | }
81 |
82 | private bool _CrEnable;
83 | public bool CrEnable
84 | {
85 | get
86 | {
87 | return _CrEnable;
88 | }
89 | set
90 | {
91 | if (_CrEnable != value)
92 | {
93 | _CrEnable = value;
94 | RaisePropertyChanged(nameof(CrEnable));
95 | }
96 | }
97 | }
98 |
99 | private bool _LfEnable;
100 | public bool LfEnable
101 | {
102 | get
103 | {
104 | return _LfEnable;
105 | }
106 | set
107 | {
108 | if (_LfEnable != value)
109 | {
110 | _LfEnable = value;
111 | RaisePropertyChanged(nameof(LfEnable));
112 | }
113 | }
114 | }
115 |
116 | private bool _CrLfEnable;
117 | public bool CrLfEnable
118 | {
119 | get
120 | {
121 | return _CrLfEnable;
122 | }
123 | set
124 | {
125 | if (_CrLfEnable != value)
126 | {
127 | _CrLfEnable = value;
128 | RaisePropertyChanged(nameof(CrLfEnable));
129 | }
130 | }
131 | }
132 | #endregion
133 |
134 | public void SendDataContext()
135 | {
136 | SendData = string.Empty;
137 | SendDataCount = 0;
138 |
139 | AutoSendNum = "1000";
140 |
141 | /* 发送换行 */
142 | NonesEnable = true;
143 | CrEnable = false;
144 | LfEnable = false;
145 | CrLfEnable = false;
146 | }
147 | }
148 | }
149 |
--------------------------------------------------------------------------------
/Models/HelpM.cs:
--------------------------------------------------------------------------------
1 | using OSDA.ViewModels;
2 | using System;
3 | using System.Runtime.Serialization;
4 |
5 | namespace OSDA.Models
6 | {
7 | [DataContract]
8 | internal sealed class GitRelease
9 | {
10 | private Version _version = null;
11 |
12 | public Uri GiteeURI { get; set; }
13 | public Uri GithubURI { get; set; }
14 |
15 | [DataMember(Name = "tag_name")]
16 | public string TagName { get; set; }
17 |
18 | public Version GetVersion()
19 | {
20 | if (_version != null)
21 | {
22 | return _version;
23 | }
24 |
25 | string version = TagName;
26 |
27 | if (version.StartsWith("v", StringComparison.CurrentCulture))
28 | {
29 | version = version.Substring(1);
30 | }
31 |
32 | return (_version = Version.Parse(version));
33 | }
34 |
35 | public GitRelease()
36 | {
37 | GiteeURI = new Uri("https://gitee.com/api/v5/repos/leven9/OSDA/releases/latest");
38 | GithubURI = new Uri("https://api.github.com/repos/leven99/OSDA/releases/latest");
39 | }
40 | }
41 |
42 | internal class HelpModel : MainWindowBase
43 | {
44 | ///
45 | /// 本地软件的版本号
46 | ///
47 | public string VerInfoNumber { get; set; }
48 |
49 | ///
50 | /// 菜单栏 - 帮助 - 本地版本信息
51 | ///
52 | private string _VerInfo;
53 | public string VerInfo
54 | {
55 | get
56 | {
57 | return _VerInfo;
58 | }
59 | set
60 | {
61 | if(_VerInfo != value)
62 | {
63 | _VerInfo = value;
64 | RaisePropertyChanged(nameof(VerInfo));
65 | }
66 | }
67 | }
68 |
69 | ///
70 | /// 服务器软件的版本信息
71 | ///
72 | public string UpdateInfo { get; set; }
73 |
74 | #region 菜单栏 - 视图 - 精简视图
75 | ///
76 | /// 菜单栏 - 视图 - 精简视图
77 | ///
78 | private bool _ReducedEnable;
79 | public bool ReducedEnable
80 | {
81 | get
82 | {
83 | return _ReducedEnable;
84 | }
85 | set
86 | {
87 | if (_ReducedEnable != value)
88 | {
89 | _ReducedEnable = value;
90 | RaisePropertyChanged(nameof(ReducedEnable));
91 | }
92 | }
93 | }
94 |
95 | ///
96 | /// 精简视图 - 视图可见性
97 | ///
98 | private string _ViewVisibility;
99 | public string ViewVisibility
100 | {
101 | get
102 | {
103 | return _ViewVisibility;
104 | }
105 | set
106 | {
107 | if (_ViewVisibility != value)
108 | {
109 | _ViewVisibility = value;
110 | RaisePropertyChanged(nameof(ViewVisibility));
111 | }
112 | }
113 | }
114 | #endregion
115 |
116 | #region 状态栏 - 发送文件进度条可见性
117 | private string _StatusBarProgressBarVisibility;
118 | public string StatusBarProgressBarVisibility
119 | {
120 | get
121 | {
122 | return _StatusBarProgressBarVisibility;
123 | }
124 | set
125 | {
126 | if (_StatusBarProgressBarVisibility != value)
127 | {
128 | _StatusBarProgressBarVisibility = value;
129 | RaisePropertyChanged(nameof(StatusBarProgressBarVisibility));
130 | }
131 | }
132 | }
133 |
134 | private double _StatusBarProgressBarValue;
135 | public double StatusBarProgressBarValue
136 | {
137 | get
138 | {
139 | return _StatusBarProgressBarValue;
140 | }
141 | set
142 | {
143 | if (_StatusBarProgressBarValue != value)
144 | {
145 | _StatusBarProgressBarValue = value;
146 | RaisePropertyChanged(nameof(StatusBarProgressBarValue));
147 | }
148 | }
149 | }
150 |
151 | private bool _StatusBarProgressBarIsIndeterminate;
152 | public bool StatusBarProgressBarIsIndeterminate
153 | {
154 | get
155 | {
156 | return _StatusBarProgressBarIsIndeterminate;
157 | }
158 | set
159 | {
160 | if (_StatusBarProgressBarIsIndeterminate != value)
161 | {
162 | _StatusBarProgressBarIsIndeterminate = value;
163 | RaisePropertyChanged(nameof(StatusBarProgressBarIsIndeterminate));
164 | }
165 | }
166 | }
167 | #endregion
168 |
169 | public void HelpDataContext()
170 | {
171 | VerInfoNumber = "3.5.0";
172 | VerInfo = "OSDA v" + VerInfoNumber;
173 |
174 | UpdateInfo = string.Format(CultureInfos, "OSDA发现新版本le........");
175 |
176 | ReducedEnable = false;
177 | ViewVisibility = "Visible";
178 |
179 | StatusBarProgressBarVisibility = "Collapsed";
180 | StatusBarProgressBarValue = 0;
181 | StatusBarProgressBarIsIndeterminate = false;
182 | }
183 | }
184 | }
185 |
--------------------------------------------------------------------------------
/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | text/microsoft-resx
107 |
108 |
109 | 2.0
110 |
111 |
112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
113 |
114 |
115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Build results
17 | [Dd]ebug/
18 | [Dd]ebugPublic/
19 | [Rr]elease/
20 | [Rr]eleases/
21 | x64/
22 | x86/
23 | [Aa][Rr][Mm]/
24 | [Aa][Rr][Mm]64/
25 | bld/
26 | [Bb]in/
27 | [Oo]bj/
28 | [Ll]og/
29 |
30 | # Sphinx Build
31 | build/
32 |
33 | # Visual Studio 2015/2017 cache/options directory
34 | .vs/
35 | # Uncomment if you have tasks that create the project's static files in wwwroot
36 | #wwwroot/
37 |
38 | # Visual Studio 2017 auto generated files
39 | Generated\ Files/
40 |
41 | # MSTest test Results
42 | [Tt]est[Rr]esult*/
43 | [Bb]uild[Ll]og.*
44 |
45 | # NUNIT
46 | *.VisualState.xml
47 | TestResult.xml
48 |
49 | # Build Results of an ATL Project
50 | [Dd]ebugPS/
51 | [Rr]eleasePS/
52 | dlldata.c
53 |
54 | # Benchmark Results
55 | BenchmarkDotNet.Artifacts/
56 |
57 | # .NET Core
58 | project.lock.json
59 | project.fragment.lock.json
60 | artifacts/
61 |
62 | # StyleCop
63 | StyleCopReport.xml
64 |
65 | # Files built by Visual Studio
66 | *_i.c
67 | *_p.c
68 | *_h.h
69 | *.ilk
70 | *.meta
71 | *.obj
72 | *.iobj
73 | *.pch
74 | *.pdb
75 | *.ipdb
76 | *.pgc
77 | *.pgd
78 | *.rsp
79 | *.sbr
80 | *.tlb
81 | *.tli
82 | *.tlh
83 | *.tmp
84 | *.tmp_proj
85 | *_wpftmp.csproj
86 | *.log
87 | *.vspscc
88 | *.vssscc
89 | .builds
90 | *.pidb
91 | *.svclog
92 | *.scc
93 |
94 | # Chutzpah Test files
95 | _Chutzpah*
96 |
97 | # Visual C++ cache files
98 | ipch/
99 | *.aps
100 | *.ncb
101 | *.opendb
102 | *.opensdf
103 | *.sdf
104 | *.cachefile
105 | *.VC.db
106 | *.VC.VC.opendb
107 |
108 | # Visual Studio profiler
109 | *.psess
110 | *.vsp
111 | *.vspx
112 | *.sap
113 |
114 | # Visual Studio Trace Files
115 | *.e2e
116 |
117 | # TFS 2012 Local Workspace
118 | $tf/
119 |
120 | # Guidance Automation Toolkit
121 | *.gpState
122 |
123 | # ReSharper is a .NET coding add-in
124 | _ReSharper*/
125 | *.[Rr]e[Ss]harper
126 | *.DotSettings.user
127 |
128 | # JustCode is a .NET coding add-in
129 | .JustCode
130 |
131 | # TeamCity is a build add-in
132 | _TeamCity*
133 |
134 | # DotCover is a Code Coverage Tool
135 | *.dotCover
136 |
137 | # AxoCover is a Code Coverage Tool
138 | .axoCover/*
139 | !.axoCover/settings.json
140 |
141 | # Visual Studio code coverage results
142 | *.coverage
143 | *.coveragexml
144 |
145 | # NCrunch
146 | _NCrunch_*
147 | .*crunch*.local.xml
148 | nCrunchTemp_*
149 |
150 | # MightyMoose
151 | *.mm.*
152 | AutoTest.Net/
153 |
154 | # Web workbench (sass)
155 | .sass-cache/
156 |
157 | # Installshield output folder
158 | [Ee]xpress/
159 |
160 | # DocProject is a documentation generator add-in
161 | DocProject/buildhelp/
162 | DocProject/Help/*.HxT
163 | DocProject/Help/*.HxC
164 | DocProject/Help/*.hhc
165 | DocProject/Help/*.hhk
166 | DocProject/Help/*.hhp
167 | DocProject/Help/Html2
168 | DocProject/Help/html
169 |
170 | # Click-Once directory
171 | publish/
172 |
173 | # Publish Web Output
174 | *.[Pp]ublish.xml
175 | *.azurePubxml
176 | # Note: Comment the next line if you want to checkin your web deploy settings,
177 | # but database connection strings (with potential passwords) will be unencrypted
178 | *.pubxml
179 | *.publishproj
180 |
181 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
182 | # checkin your Azure Web App publish settings, but sensitive information contained
183 | # in these scripts will be unencrypted
184 | PublishScripts/
185 |
186 | # NuGet Packages
187 | *.nupkg
188 | # The packages folder can be ignored because of Package Restore
189 | **/[Pp]ackages/*
190 | # except build/, which is used as an MSBuild target.
191 | !**/[Pp]ackages/build/
192 | # Uncomment if necessary however generally it will be regenerated when needed
193 | #!**/[Pp]ackages/repositories.config
194 | # NuGet v3's project.json files produces more ignorable files
195 | *.nuget.props
196 | *.nuget.targets
197 |
198 | # Microsoft Azure Build Output
199 | csx/
200 | *.build.csdef
201 |
202 | # Microsoft Azure Emulator
203 | ecf/
204 | rcf/
205 |
206 | # Windows Store app package directories and files
207 | AppPackages/
208 | BundleArtifacts/
209 | Package.StoreAssociation.xml
210 | _pkginfo.txt
211 | *.appx
212 |
213 | # Visual Studio cache files
214 | # files ending in .cache can be ignored
215 | *.[Cc]ache
216 | # but keep track of directories ending in .cache
217 | !?*.[Cc]ache/
218 |
219 | # Others
220 | ClientBin/
221 | ~$*
222 | *~
223 | *.dbmdl
224 | *.dbproj.schemaview
225 | *.jfm
226 | *.pfx
227 | *.publishsettings
228 | orleans.codegen.cs
229 |
230 | # Including strong name files can present a security risk
231 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
232 | #*.snk
233 |
234 | # Since there are multiple workflows, uncomment next line to ignore bower_components
235 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
236 | #bower_components/
237 | # ASP.NET Core default setup: bower directory is configured as wwwroot/lib/ and bower restore is true
238 | **/wwwroot/lib/
239 |
240 | # RIA/Silverlight projects
241 | Generated_Code/
242 |
243 | # Backup & report files from converting an old project file
244 | # to a newer Visual Studio version. Backup files are not needed,
245 | # because we have git ;-)
246 | _UpgradeReport_Files/
247 | Backup*/
248 | UpgradeLog*.XML
249 | UpgradeLog*.htm
250 | ServiceFabricBackup/
251 | *.rptproj.bak
252 |
253 | # SQL Server files
254 | *.mdf
255 | *.ldf
256 | *.ndf
257 |
258 | # Business Intelligence projects
259 | *.rdl.data
260 | *.bim.layout
261 | *.bim_*.settings
262 | *.rptproj.rsuser
263 |
264 | # Microsoft Fakes
265 | FakesAssemblies/
266 |
267 | # GhostDoc plugin setting file
268 | *.GhostDoc.xml
269 |
270 | # Node.js Tools for Visual Studio
271 | .ntvs_analysis.dat
272 | node_modules/
273 |
274 | # Visual Studio 6 build log
275 | *.plg
276 |
277 | # Visual Studio 6 workspace options file
278 | *.opt
279 |
280 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
281 | *.vbw
282 |
283 | # Visual Studio LightSwitch build output
284 | **/*.HTMLClient/GeneratedArtifacts
285 | **/*.DesktopClient/GeneratedArtifacts
286 | **/*.DesktopClient/ModelManifest.xml
287 | **/*.Server/GeneratedArtifacts
288 | **/*.Server/ModelManifest.xml
289 | _Pvt_Extensions
290 |
291 | # Paket dependency manager
292 | .paket/paket.exe
293 | paket-files/
294 |
295 | # FAKE - F# Make
296 | .fake/
297 |
298 | # JetBrains Rider
299 | .idea/
300 | *.sln.iml
301 |
302 | # CodeRush personal settings
303 | .cr/personal
304 |
305 | # Python Tools for Visual Studio (PTVS)
306 | __pycache__/
307 | *.pyc
308 |
309 | # Cake - Uncomment if you are using it
310 | # tools/**
311 | # !tools/packages.config
312 |
313 | # Tabs Studio
314 | *.tss
315 |
316 | # Telerik's JustMock configuration file
317 | *.jmconfig
318 |
319 | # BizTalk build output
320 | *.btp.cs
321 | *.btm.cs
322 | *.odx.cs
323 | *.xsd.cs
324 |
325 | # OpenCover UI analysis results
326 | OpenCover/
327 |
328 | # Azure Stream Analytics local run output
329 | ASALocalRun/
330 |
331 | # MSBuild Binary and Structured Log
332 | *.binlog
333 |
334 | # NVidia Nsight GPU debugger configuration file
335 | *.nvuser
336 |
337 | # MFractors (Xamarin productivity tool) working folder
338 | .mfractor/
339 |
340 | # Local History for Visual Studio
341 | .localhistory/
342 |
343 | # BeatPulse healthcheck temp database
344 | healthchecksdb
345 |
--------------------------------------------------------------------------------
/App.xaml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
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 |
50 |
55 |
56 |
57 |
60 |
61 |
62 |
68 |
74 |
75 |
76 |
80 |
90 |
91 |
92 |
93 |
97 |
104 |
105 |
106 |
111 |
116 |
117 |
118 |
122 |
128 |
133 |
134 |
135 |
139 |
140 |
141 |
142 |
--------------------------------------------------------------------------------
/msvc/VS2017.Framework/ODSA.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {71C6AC13-4E18-44E7-AFBC-97BED2BDAB7E}
8 | WinExe
9 | OSDA
10 | OSDA
11 | v4.6.1
12 | 512
13 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
14 | 4
15 | true
16 | true
17 | false
18 | publish\
19 | true
20 | Disk
21 | false
22 | Foreground
23 | 7
24 | Days
25 | false
26 | false
27 | true
28 | 0
29 | 1.0.0.%2a
30 | false
31 | true
32 |
33 |
34 | AnyCPU
35 | true
36 | full
37 | false
38 | bin\Debug\
39 | DEBUG;TRACE
40 | prompt
41 | 4
42 | 7.1
43 |
44 |
45 | AnyCPU
46 | pdbonly
47 | true
48 | bin\Release\
49 | TRACE
50 | prompt
51 | 4
52 | 7.1
53 |
54 |
55 | true
56 | bin\x64\Debug\
57 | DEBUG;TRACE
58 | full
59 | x64
60 | prompt
61 | MinimumRecommendedRules.ruleset
62 | true
63 | 7.1
64 |
65 |
66 | bin\x64\Release\
67 | TRACE
68 | true
69 | pdbonly
70 | x64
71 | prompt
72 | MinimumRecommendedRules.ruleset
73 | true
74 | 7.1
75 |
76 |
77 | true
78 | bin\x86\Debug\
79 | DEBUG;TRACE
80 | full
81 | x86
82 | prompt
83 | MinimumRecommendedRules.ruleset
84 | true
85 | 7.1
86 |
87 |
88 | bin\x86\Release\
89 | TRACE
90 | true
91 | pdbonly
92 | x86
93 | prompt
94 | MinimumRecommendedRules.ruleset
95 | true
96 | 7.1
97 |
98 |
99 | icon\favicon.ico
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 | 4.0
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 | MSBuild:Compile
122 | Designer
123 |
124 |
125 | ViewModels\MainWindowVM.cs
126 |
127 |
128 | ViewModels\MainWindowBase.cs
129 |
130 |
131 | ViewModels\WPFUpdateVM.cs
132 |
133 |
134 | Models\TimerM.cs
135 |
136 |
137 | Models\HelpM.cs
138 |
139 |
140 | Models\RecvM.cs
141 |
142 |
143 | Models\SendM.cs
144 |
145 |
146 | Models\SerialPortM.cs
147 |
148 |
149 | Interface\ITextBoxAppend.cs
150 |
151 |
152 | MSBuild:Compile
153 | Designer
154 | Views\MainWindow.xaml
155 |
156 |
157 | MSBuild:Compile
158 | Designer
159 | Views\WPFUpdate.xaml
160 |
161 |
162 | MainWindow.xaml
163 | Code
164 | Views\MainWindow.xaml.cs
165 |
166 |
167 | WPFUpdate.xaml
168 | Code
169 | Views\WPFUpdate.xaml.cs
170 |
171 |
172 | App.xaml
173 | Code
174 |
175 |
176 |
177 |
178 | Code
179 | Properties\AssemblyInfo.cs
180 |
181 |
182 | True
183 | True
184 | Resources.resx
185 | Properties\Resources.Designer.cs
186 |
187 |
188 | True
189 | Settings.settings
190 | True
191 | Properties\Settings.Designer.cs
192 |
193 |
194 | ResXFileCodeGenerator
195 | Resources.Designer.cs
196 | Properties\Resources.resx
197 |
198 |
199 | SettingsSingleFileGenerator
200 | Settings.Designer.cs
201 | Properties\Settings.settings
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 | icon\favicon.ico
210 |
211 |
212 | icon\Close.png
213 |
214 |
215 | icon\favicon.png
216 |
217 |
218 | icon\Max.png
219 |
220 |
221 | icon\Min.png
222 |
223 |
224 | icon\Red.png
225 |
226 |
227 |
228 |
229 | False
230 | Microsoft .NET Framework 4.6.1 %28x86 和 x64%29
231 | true
232 |
233 |
234 | False
235 | .NET Framework 3.5 SP1
236 | false
237 |
238 |
239 |
240 |
--------------------------------------------------------------------------------
/Views/MainWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using OSDA.Interfaces;
2 | using OSDA.ViewModels;
3 | using System;
4 | using System.Diagnostics;
5 | using System.Text.RegularExpressions;
6 | using System.Windows;
7 | using System.Windows.Controls;
8 | using System.Windows.Input;
9 |
10 | namespace OSDA.Views
11 | {
12 | public partial class MainWindow : Window, IDisposable
13 | {
14 | internal MainWindowViewModel mainWindowViewModel = null;
15 |
16 | public MainWindow()
17 | {
18 | InitializeComponent();
19 |
20 | Height = 532;
21 | Width = Height / 0.625;
22 |
23 | mainWindowViewModel = new MainWindowViewModel();
24 | DataContext = mainWindowViewModel;
25 | }
26 |
27 | #region Menu Mouse Support
28 | ///
29 | /// 鼠标移动
30 | ///
31 | ///
32 | ///
33 | private void MouseMove_Click(object sender, System.Windows.Input.MouseEventArgs e)
34 | {
35 | if (e.LeftButton == MouseButtonState.Pressed)
36 | {
37 | DragMove();
38 | }
39 | }
40 | #endregion
41 |
42 | #region 菜单栏
43 |
44 | #region 文件
45 | ///
46 | /// 退出
47 | ///
48 | ///
49 | ///
50 | private void ExitMenuItem_Click(object sender, RoutedEventArgs e)
51 | {
52 | mainWindowViewModel.ExitWindow();
53 |
54 | Close();
55 | }
56 | #endregion
57 |
58 | #region 工具
59 | ///
60 | /// 计算器
61 | ///
62 | ///
63 | ///
64 | private void CalcMenuItem_Click(object sender, RoutedEventArgs e)
65 | {
66 | Process.Start("calc.exe");
67 | }
68 | #endregion
69 |
70 | #region 选项
71 |
72 | #region 字节编码
73 | private void ASCIIMenuItem_Click(object sender, RoutedEventArgs e)
74 | {
75 | mainWindowViewModel.ASCIIEnable();
76 | }
77 |
78 | private void UTF8MenuItem_Click(object sender, RoutedEventArgs e)
79 | {
80 | mainWindowViewModel.UTF8Enable();
81 | }
82 |
83 | private void UTF16MenuItem_Click(object sender, RoutedEventArgs e)
84 | {
85 | mainWindowViewModel.UTF16Enable();
86 | }
87 |
88 | private void UTF32MenuItem_Click(object sender, RoutedEventArgs e)
89 | {
90 | mainWindowViewModel.UTF32Enable();
91 | }
92 | #endregion
93 |
94 | private void RtsEnableMenuItem_Click(object sender, RoutedEventArgs e)
95 | {
96 | mainWindowViewModel.RtsEnable();
97 | }
98 |
99 | private void DtrEnableMenuItem_Click(object sender, RoutedEventArgs e)
100 | {
101 | mainWindowViewModel.DtrEnable();
102 | }
103 |
104 | #region 流控制
105 | private void NoneMenuItem_Click(object sender, RoutedEventArgs e)
106 | {
107 | mainWindowViewModel.NoneEnable();
108 | }
109 |
110 | private void RequestToSendMenuItem_Click(object sender, RoutedEventArgs e)
111 | {
112 | mainWindowViewModel.RequestToSendEnable();
113 | }
114 |
115 | private void XOnXOffMenuItem_Click(object sender, RoutedEventArgs e)
116 | {
117 | mainWindowViewModel.XOnXOffEnable();
118 | }
119 |
120 | private void RequestToSendXOnXOffMenuItem_Click(object sender, RoutedEventArgs e)
121 | {
122 | mainWindowViewModel.RequestToSendXOnXOffEnable();
123 | }
124 | #endregion
125 |
126 | private void TimeStampMenuItem_Click(object sender, RoutedEventArgs e)
127 | {
128 | mainWindowViewModel.TimeStampEnable();
129 | }
130 |
131 | #region 发送换行
132 | private void NonesMenuItem_Click(object sender, RoutedEventArgs e)
133 | {
134 | mainWindowViewModel.NonesEnable();
135 | }
136 |
137 | private void CrMenuItem_Click(object sender, RoutedEventArgs e)
138 | {
139 | mainWindowViewModel.CrEnable();
140 | }
141 |
142 | private void LfMenuItem_Click(object sender, RoutedEventArgs e)
143 | {
144 | mainWindowViewModel.LfEnable();
145 | }
146 |
147 | private void CrLfMenuItem_Click(object sender, RoutedEventArgs e)
148 | {
149 | mainWindowViewModel.CrLfEnable();
150 | }
151 | #endregion
152 |
153 | #endregion
154 |
155 | #region 视图
156 | ///
157 | /// 精简视图
158 | ///
159 | ///
160 | ///
161 | private void EveryMenuItem_Click(object sender, RoutedEventArgs e)
162 | {
163 | mainWindowViewModel.ReducedEnable();
164 | }
165 | #endregion
166 |
167 | #region 帮助
168 | ///
169 | /// 检查更新
170 | ///
171 | ///
172 | ///
173 | private void VerUpMenuItem_Click(object sender, RoutedEventArgs e)
174 | {
175 | mainWindowViewModel.UpdateAsync();
176 | }
177 |
178 | ///
179 | /// Gitee 存储库
180 | ///
181 | ///
182 | ///
183 | private void RPMenuItem_Click(object sender, RoutedEventArgs e)
184 | {
185 | Process.Start("https://gitee.com/leven9/OSDA");
186 | }
187 |
188 | ///
189 | /// 报告问题
190 | ///
191 | ///
192 | ///
193 | private void IssueMenuItem_Click(object sender, RoutedEventArgs e)
194 | {
195 | Process.Start("https://gitee.com/leven9/OSDA/issues");
196 | }
197 | #endregion
198 |
199 | ///
200 | /// 最小化
201 | ///
202 | ///
203 | ///
204 | private void MinButton_Click(object sender, RoutedEventArgs e)
205 | {
206 | WindowState = WindowState.Minimized;
207 | }
208 |
209 | ///
210 | /// 关闭
211 | ///
212 | ///
213 | ///
214 | private void CloseButton_Click(object sender, RoutedEventArgs e)
215 | {
216 | Close();
217 | Application.Current.Shutdown();
218 | }
219 | #endregion
220 |
221 | #region 打开/关闭串口
222 | private void OpenCloseSP(object sender, RoutedEventArgs e)
223 | {
224 | mainWindowViewModel.OpenSP();
225 | }
226 | #endregion
227 |
228 | #region 发送
229 | private async void Send(object sender, RoutedEventArgs e)
230 | {
231 | await mainWindowViewModel.SendAsync().ConfigureAwait(false);
232 | }
233 | #endregion
234 |
235 | #region 发送文件
236 | private async void SendFile(object sender, RoutedEventArgs e)
237 | {
238 | await mainWindowViewModel.SendFileAsync().ConfigureAwait(false);
239 | }
240 | #endregion
241 |
242 | #region 路径选择
243 | private void SaveRecvPath(object sender, RoutedEventArgs e)
244 | {
245 | mainWindowViewModel.SaveRecvPath();
246 | }
247 | #endregion
248 |
249 | #region 清接收区
250 | private void ClearReceData(object sender, RoutedEventArgs e)
251 | {
252 | mainWindowViewModel.ClearReceData();
253 | }
254 | #endregion
255 |
256 | #region 清发送区
257 | private void ClearSendData(object sender, RoutedEventArgs e)
258 | {
259 | mainWindowViewModel.ClearSendData();
260 | }
261 | #endregion
262 |
263 | #region 清空计数
264 | private void ClearCount(object sender, RoutedEventArgs e)
265 | {
266 | mainWindowViewModel.ClearCount();
267 | }
268 | #endregion
269 |
270 | #region TextBox Support
271 | ///
272 | /// 只允许输入0-9的数字
273 | ///
274 | ///
275 | ///
276 | private void AutoSendNumTextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
277 | {
278 | Regex re = new Regex("[^0-9]+");
279 |
280 | e.Handled = re.IsMatch(e.Text);
281 | }
282 | #endregion
283 |
284 | #region RecvTextBox Support
285 | ///
286 | /// Mouse Double(鼠标双击)
287 | ///
288 | ///
289 | ///
290 | private void RecvTextBox_MouseDoubleClick(object sender, MouseButtonEventArgs e)
291 | {
292 | mainWindowViewModel.EnableRecv();
293 | }
294 |
295 | ///
296 | /// ScrollToEnd
297 | ///
298 | ///
299 | ///
300 | private void RecvTextBox_TextChanged(object sender, TextChangedEventArgs e)
301 | {
302 | RecvTextBox.ScrollToEnd();
303 | }
304 | #endregion
305 |
306 | #region IDisposable Support
307 | private bool disposedValue = false; /* 冗余检测 */
308 |
309 | ///
310 | /// 释放组件所使用的非托管资源,并且有选择的释放托管资源(可以看作是Dispose()的安全实现)
311 | ///
312 | ///
313 | protected virtual void Dispose(bool disposing)
314 | {
315 | /* 检查是否已调用dispose */
316 | if (!disposedValue)
317 | {
318 | if (disposing)
319 | {
320 | /* 释放托管资源(如果需要) */
321 |
322 | /* 由于mainWindowViewModel对象拥有SerialPort,因此间接拥有SerialPort的非托管资源,所以需要实现IDisposable */
323 | mainWindowViewModel.Dispose();
324 | }
325 |
326 | /* 释放非托管资源(如果有的话) */
327 |
328 | disposedValue = true; /* 处理完毕 */
329 | }
330 | }
331 |
332 | ///
333 | /// 实现IDisposable,释放组件所使用的所有资源
334 | ///
335 | public void Dispose()
336 | {
337 | Dispose(true);
338 | GC.SuppressFinalize(this);/* this: OSDA.Views.MainWindow */
339 | }
340 | #endregion
341 | }
342 |
343 | #region RecvTextBox Append Text Support
344 | public static class MvvmTextBox
345 | {
346 | public static readonly DependencyProperty BufferProperty =
347 | DependencyProperty.RegisterAttached(
348 | "Buffer",
349 | typeof(ITextBoxAppend),
350 | typeof(MvvmTextBox),
351 | new UIPropertyMetadata(null, PropertyChangedCallback)
352 | );
353 |
354 | private static void PropertyChangedCallback(
355 | DependencyObject dependencyObject,
356 | DependencyPropertyChangedEventArgs depPropChangedEvArgs)
357 | {
358 | var textBox = (TextBox)dependencyObject;
359 | var textBuffer = (ITextBoxAppend)depPropChangedEvArgs.NewValue;
360 |
361 | var detectChanges = true;
362 |
363 | textBuffer.BufferClearingHandler += (sender, clearingText) =>
364 | {
365 | detectChanges = false;
366 | textBox.Clear();
367 | detectChanges = true;
368 | };
369 |
370 | textBox.Text = textBuffer.GetCurrentValue();
371 | textBuffer.BufferAppendedHandler += (sender, appendedText) =>
372 | {
373 | detectChanges = false;
374 | textBox.AppendText(appendedText.AppendedText);
375 | detectChanges = true;
376 | };
377 |
378 | textBox.TextChanged += (sender, args) =>
379 | {
380 | if (!detectChanges)
381 | return;
382 |
383 | foreach (var change in args.Changes)
384 | {
385 | if (change.AddedLength > 0)
386 | {
387 | var addedContent = textBox.Text.Substring(
388 | change.Offset, change.AddedLength);
389 |
390 | textBuffer.Append(addedContent, change.Offset);
391 | }
392 | else
393 | {
394 | textBuffer.Delete(change.Offset, change.RemovedLength);
395 | }
396 | }
397 |
398 | Debug.WriteLine(textBuffer.GetCurrentValue());
399 | };
400 | }
401 |
402 | public static void SetBuffer(UIElement element, bool value)
403 | {
404 | if(element != null)
405 | {
406 | element.SetValue(BufferProperty, value);
407 | }
408 | }
409 | public static ITextBoxAppend GetBuffer(UIElement element)
410 | {
411 | if(element == null)
412 | {
413 | return (ITextBoxAppend)null;
414 | }
415 |
416 | return (ITextBoxAppend)element.GetValue(BufferProperty);
417 | }
418 | }
419 | #endregion
420 | }
421 |
--------------------------------------------------------------------------------
/msvc/VS2019.Framework/OSDA.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | Debug
11 | AnyCPU
12 | {4626E3E4-8C98-4840-8656-F445C87168BD}
13 | WinExe
14 | OSDA
15 | OSDA
16 | v4.6.1
17 | 512
18 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
19 | 4
20 | true
21 | true
22 | false
23 |
24 |
25 | publish\
26 | true
27 | Disk
28 | false
29 | Foreground
30 | 7
31 | Days
32 | false
33 | false
34 | true
35 | 0
36 | 1.0.0.%2a
37 | false
38 | true
39 |
40 |
41 | AnyCPU
42 | true
43 | full
44 | false
45 | bin\Debug\
46 | DEBUG;TRACE
47 | prompt
48 | 4
49 |
50 |
51 | AnyCPU
52 | pdbonly
53 | true
54 | bin\Release\
55 | TRACE
56 | prompt
57 | 4
58 |
59 |
60 | true
61 | bin\x64\Debug\
62 | DEBUG;TRACE
63 | full
64 | x64
65 | prompt
66 | MinimumRecommendedRules.ruleset
67 | true
68 | false
69 |
70 |
71 | bin\x64\Release\
72 | TRACE
73 | true
74 | pdbonly
75 | x64
76 | prompt
77 | MinimumRecommendedRules.ruleset
78 | true
79 |
80 |
81 | true
82 | bin\x86\Debug\
83 | DEBUG;TRACE
84 | full
85 | x86
86 | prompt
87 | MinimumRecommendedRules.ruleset
88 | true
89 |
90 |
91 | bin\x86\Release\
92 | TRACE
93 | true
94 | pdbonly
95 | x86
96 | prompt
97 | MinimumRecommendedRules.ruleset
98 | true
99 |
100 |
101 | icon\favicon.ico
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 | 4.0
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 | MSBuild:Compile
124 | Designer
125 |
126 |
127 | ViewModels\MainWindowVM.cs
128 |
129 |
130 | ViewModels\MainWindowBase.cs
131 |
132 |
133 | ViewModels\WPFUpdateVM.cs
134 |
135 |
136 | Models\TimerM.cs
137 |
138 |
139 | Models\HelpM.cs
140 |
141 |
142 | Models\RecvM.cs
143 |
144 |
145 | Models\SendM.cs
146 |
147 |
148 | Models\SerialPortM.cs
149 |
150 |
151 | Interface\ITextBoxAppend.cs
152 |
153 |
154 | MSBuild:Compile
155 | Designer
156 | Views\MainWindow.xaml
157 |
158 |
159 | MSBuild:Compile
160 | Designer
161 | Views\WPFUpdate.xaml
162 |
163 |
164 | MainWindow.xaml
165 | Code
166 | Views\MainWindow.xaml.cs
167 |
168 |
169 | WPFUpdate.xaml
170 | Code
171 | Views\WPFUpdate.xaml.cs
172 |
173 |
174 | App.xaml
175 | Code
176 |
177 |
178 |
179 |
180 | Code
181 | Properties\AssemblyInfo.cs
182 |
183 |
184 | True
185 | True
186 | Resources.resx
187 | Properties\Resources.Designer.cs
188 |
189 |
190 | True
191 | Settings.settings
192 | True
193 | Properties\Settings.Designer.cs
194 |
195 |
196 | ResXFileCodeGenerator
197 | Resources.Designer.cs
198 | Properties\Resources.resx
199 |
200 |
201 | SettingsSingleFileGenerator
202 | Settings.Designer.cs
203 | Properties\Settings.settings
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 | icon\favicon.ico
213 |
214 |
215 | icon\Close.png
216 |
217 |
218 | icon\favicon.png
219 |
220 |
221 | icon\Max.png
222 |
223 |
224 | icon\Min.png
225 |
226 |
227 | icon\Red.png
228 |
229 |
230 |
231 |
232 | False
233 | Microsoft .NET Framework 4.6.1 %28x86 和 x64%29
234 | true
235 |
236 |
237 | False
238 | .NET Framework 3.5 SP1
239 | false
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 | 这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
--------------------------------------------------------------------------------
/Models/SerialPortM.cs:
--------------------------------------------------------------------------------
1 | using OSDA.ViewModels;
2 | using System.Collections.ObjectModel;
3 | using System.IO.Ports;
4 | using System.Windows.Media;
5 |
6 | namespace OSDA.Models
7 | {
8 | internal class SerialPortModel : MainWindowBase
9 | {
10 | public string[] PortItemsSource { get;set; }
11 | public Collection BaudRateItemsSource { get; set; }
12 | public Collection DataBitsItemsSource { get; set; }
13 | public Collection StopBitsItemsSource { get; set; }
14 | public Collection ParityItemsSource { get; set; }
15 |
16 | #region 串口配置区 - 串口属性
17 | private string _Port;
18 | public string Port
19 | {
20 | get
21 | {
22 | return _Port;
23 | }
24 | set
25 | {
26 | if (_Port != value)
27 | {
28 | _Port = value;
29 | RaisePropertyChanged(nameof(Port));
30 | }
31 | }
32 | }
33 |
34 | private int _BaudRate;
35 | public int BaudRate
36 | {
37 | get
38 | {
39 | return _BaudRate;
40 | }
41 | set
42 | {
43 | if (_BaudRate != value)
44 | {
45 | _BaudRate = value;
46 | RaisePropertyChanged(nameof(BaudRate));
47 | }
48 | }
49 | }
50 |
51 | private int _DataBits;
52 | public int DataBits
53 | {
54 | get
55 | {
56 | return _DataBits;
57 | }
58 | set
59 | {
60 | if (_DataBits != value)
61 | {
62 | _DataBits = value;
63 | RaisePropertyChanged(nameof(DataBits));
64 | }
65 | }
66 | }
67 |
68 | private StopBits _StopBits;
69 | public StopBits StopBits
70 | {
71 | get
72 | {
73 | return _StopBits;
74 | }
75 | set
76 | {
77 | if (_StopBits != value)
78 | {
79 | _StopBits = value;
80 | RaisePropertyChanged(nameof(StopBits));
81 | }
82 | }
83 | }
84 |
85 | private Parity _Parity;
86 | public Parity Parity
87 | {
88 | get
89 | {
90 | return _Parity;
91 | }
92 | set
93 | {
94 | if (_Parity != value)
95 | {
96 | _Parity = value;
97 | RaisePropertyChanged(nameof(Parity));
98 | }
99 | }
100 | }
101 | #endregion
102 |
103 | #region 串口配置区 - 打开/关闭
104 | private Brush _Brush;
105 | public Brush Brush
106 | {
107 | get
108 | {
109 | return _Brush;
110 | }
111 | set
112 | {
113 | if (_Brush != value)
114 | {
115 | _Brush = value;
116 | RaisePropertyChanged(nameof(Brush));
117 | }
118 | }
119 | }
120 |
121 | private string _OpenClose;
122 | public string OpenClose
123 | {
124 | get
125 | {
126 | return _OpenClose;
127 | }
128 | set
129 | {
130 | if (_OpenClose != value)
131 | {
132 | _OpenClose = value;
133 | RaisePropertyChanged(nameof(OpenClose));
134 | }
135 | }
136 | }
137 | #endregion
138 |
139 | #region 串口属性控件 - 启用/不启用
140 | private bool _PortEnable;
141 | public bool PortEnable
142 | {
143 | get
144 | {
145 | return _PortEnable;
146 | }
147 | set
148 | {
149 | if (_PortEnable != value)
150 | {
151 | _PortEnable = value;
152 | RaisePropertyChanged(nameof(PortEnable));
153 | }
154 | }
155 | }
156 |
157 | private bool _BaudRateEnable;
158 | public bool BaudRateEnable
159 | {
160 | get
161 | {
162 | return _BaudRateEnable;
163 | }
164 | set
165 | {
166 | if (_BaudRateEnable != value)
167 | {
168 | _BaudRateEnable = value;
169 | RaisePropertyChanged(nameof(BaudRateEnable));
170 | }
171 | }
172 | }
173 |
174 | private bool _DataBitsEnable;
175 | public bool DataBitsEnable
176 | {
177 | get
178 | {
179 | return _DataBitsEnable;
180 | }
181 | set
182 | {
183 | if (_DataBitsEnable != value)
184 | {
185 | _DataBitsEnable = value;
186 | RaisePropertyChanged(nameof(DataBitsEnable));
187 | }
188 | }
189 | }
190 |
191 | private bool _StopBitsEnable;
192 | public bool StopBitsEnable
193 | {
194 | get
195 | {
196 | return _StopBitsEnable;
197 | }
198 | set
199 | {
200 | if (_StopBitsEnable != value)
201 | {
202 | _StopBitsEnable = value;
203 | RaisePropertyChanged(nameof(StopBitsEnable));
204 | }
205 | }
206 | }
207 |
208 | private bool _ParityEnable;
209 | public bool ParityEnable
210 | {
211 | get
212 | {
213 | return _ParityEnable;
214 | }
215 | set
216 | {
217 | if (_ParityEnable != value)
218 | {
219 | _ParityEnable = value;
220 | RaisePropertyChanged(nameof(ParityEnable));
221 | }
222 | }
223 | }
224 | #endregion
225 |
226 | #region 菜单栏 - 选项 - 字节编码
227 | private bool _ASCIIEnable;
228 | public bool ASCIIEnable
229 | {
230 | get
231 | {
232 | return _ASCIIEnable;
233 | }
234 | set
235 | {
236 | if(_ASCIIEnable != value)
237 | {
238 | _ASCIIEnable = value;
239 | RaisePropertyChanged(nameof(ASCIIEnable));
240 | }
241 | }
242 | }
243 |
244 | private bool _UTF8Enable;
245 | public bool UTF8Enable
246 | {
247 | get
248 | {
249 | return _UTF8Enable;
250 | }
251 | set
252 | {
253 | if (_UTF8Enable != value)
254 | {
255 | _UTF8Enable = value;
256 | RaisePropertyChanged(nameof(UTF8Enable));
257 | }
258 | }
259 | }
260 |
261 | private bool _UTF16Enable;
262 | public bool UTF16Enable
263 | {
264 | get
265 | {
266 | return _UTF16Enable;
267 | }
268 | set
269 | {
270 | if (_UTF16Enable != value)
271 | {
272 | _UTF16Enable = value;
273 | RaisePropertyChanged(nameof(UTF16Enable));
274 | }
275 | }
276 | }
277 |
278 | private bool _UTF32Enable;
279 | public bool UTF32Enable
280 | {
281 | get
282 | {
283 | return _UTF32Enable;
284 | }
285 | set
286 | {
287 | if (_UTF32Enable != value)
288 | {
289 | _UTF32Enable = value;
290 | RaisePropertyChanged(nameof(UTF32Enable));
291 | }
292 | }
293 | }
294 | #endregion
295 |
296 | #region 菜单栏 - 选项 - DTR/RTS
297 | private bool _DtrEnable;
298 | public bool DtrEnable
299 | {
300 | get
301 | {
302 | return _DtrEnable;
303 | }
304 | set
305 | {
306 | if (_DtrEnable != value)
307 | {
308 | _DtrEnable = value;
309 | RaisePropertyChanged(nameof(DtrEnable));
310 | }
311 | }
312 | }
313 |
314 | private bool _RtsEnable;
315 | public bool RtsEnable
316 | {
317 | get
318 | {
319 | return _RtsEnable;
320 | }
321 | set
322 | {
323 | if (_RtsEnable != value)
324 | {
325 | _RtsEnable = value;
326 | RaisePropertyChanged(nameof(RtsEnable));
327 | }
328 | }
329 | }
330 | #endregion
331 |
332 | #region 菜单栏 - 选项 - 流控制
333 | private bool _NoneEnable;
334 | public bool NoneEnable
335 | {
336 | get
337 | {
338 | return _NoneEnable;
339 | }
340 | set
341 | {
342 | if(_NoneEnable != value)
343 | {
344 | _NoneEnable = value;
345 | RaisePropertyChanged(nameof(NoneEnable));
346 | }
347 | }
348 | }
349 |
350 | private bool _RequestToSendEnable;
351 | public bool RequestToSendEnable
352 | {
353 | get
354 | {
355 | return _RequestToSendEnable;
356 | }
357 | set
358 | {
359 | if (_RequestToSendEnable != value)
360 | {
361 | _RequestToSendEnable = value;
362 | RaisePropertyChanged(nameof(RequestToSendEnable));
363 | }
364 | }
365 | }
366 |
367 | private bool _XOnXOffEnable;
368 | public bool XOnXOffEnable
369 | {
370 | get
371 | {
372 | return _XOnXOffEnable;
373 | }
374 | set
375 | {
376 | if (_XOnXOffEnable != value)
377 | {
378 | _XOnXOffEnable = value;
379 | RaisePropertyChanged(nameof(XOnXOffEnable));
380 | }
381 | }
382 | }
383 |
384 | private bool _RequestToSendXOnXOffEnable;
385 | public bool RequestToSendXOnXOffEnable
386 | {
387 | get
388 | {
389 | return _RequestToSendXOnXOffEnable;
390 | }
391 | set
392 | {
393 | if (_RequestToSendXOnXOffEnable != value)
394 | {
395 | _RequestToSendXOnXOffEnable = value;
396 | RaisePropertyChanged(nameof(RequestToSendXOnXOffEnable));
397 | }
398 | }
399 | }
400 | #endregion
401 |
402 | #region 信号状态区 - 信号指示灯
403 | private Brush _DcdBrush;
404 | public Brush DcdBrush
405 | {
406 | get
407 | {
408 | return _DcdBrush;
409 | }
410 | set
411 | {
412 | if (_DcdBrush != value)
413 | {
414 | _DcdBrush = value;
415 | RaisePropertyChanged(nameof(DcdBrush));
416 | }
417 | }
418 | }
419 |
420 | private Brush _CtsBrush;
421 | public Brush CtsBrush
422 | {
423 | get
424 | {
425 | return _CtsBrush;
426 | }
427 | set
428 | {
429 | if (_CtsBrush != value)
430 | {
431 | _CtsBrush = value;
432 | RaisePropertyChanged(nameof(CtsBrush));
433 | }
434 | }
435 | }
436 |
437 | private Brush _DsrBrush;
438 | public Brush DsrBrush
439 | {
440 | get
441 | {
442 | return _DsrBrush;
443 | }
444 | set
445 | {
446 | if (_DsrBrush != value)
447 | {
448 | _DsrBrush = value;
449 | RaisePropertyChanged(nameof(DsrBrush));
450 | }
451 | }
452 | }
453 | #endregion
454 |
455 | public void SerialPortDataContext()
456 | {
457 | PortItemsSource = SerialPort.GetPortNames();
458 | BaudRateItemsSource = new Collection
459 | {
460 | 1200, 2400, 4800, 7200, 9600, 14400, 19200, 28800, 38400, 57600, 115200, 128000, 153600, 230400, 256000
461 | };
462 | DataBitsItemsSource = new Collection
463 | {
464 | 5, 6, 7, 8
465 | };
466 | StopBitsItemsSource = new Collection
467 | {
468 | StopBits.One, StopBits.Two, StopBits.OnePointFive
469 | };
470 | ParityItemsSource = new Collection
471 | {
472 | Parity.None, Parity.Odd, Parity.Even, Parity.Mark, Parity.Space
473 | };
474 |
475 | BaudRate = 9600;
476 | DataBits = 8;
477 | StopBits = StopBits.One;
478 | Parity = Parity.None;
479 |
480 | Brush = Brushes.Red;
481 | OpenClose = string.Format(CultureInfos, "打开串口");
482 |
483 | /* 串口属性控件 */
484 | PortEnable = true;
485 | BaudRateEnable = true;
486 | DataBitsEnable = true;
487 | StopBitsEnable = true;
488 | ParityEnable = true;
489 |
490 | /* 字节编码 */
491 | ASCIIEnable = false;
492 | UTF8Enable = true;
493 | UTF16Enable = false;
494 | UTF32Enable = false;
495 |
496 | DtrEnable = false;
497 | RtsEnable = false;
498 |
499 | /* 流控制 */
500 | NoneEnable = true;
501 | RequestToSendEnable = false;
502 | XOnXOffEnable = false;
503 | RequestToSendXOnXOffEnable = false;
504 |
505 | /* 信号状态 */
506 | DcdBrush = Brushes.Black;
507 | CtsBrush = Brushes.Black;
508 | DsrBrush = Brushes.Black;
509 | }
510 | }
511 | }
512 |
--------------------------------------------------------------------------------
/Views/MainWindow.xaml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
36 |
106 |
114 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
134 |
135 |
141 |
142 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
168 |
173 |
174 |
175 |
176 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
193 |
197 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
233 |
238 |
240 |
245 |
247 |
252 |
254 |
259 |
261 |
266 |
269 |
273 |
274 |
275 |
276 |
277 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
292 |
294 |
296 |
298 |
300 |
302 |
303 |
304 |
305 |
306 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
326 |
330 |
334 |
339 |
343 |
347 |
351 |
355 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
--------------------------------------------------------------------------------
/ViewModels/MainWindowVM.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Win32;
2 | using OSDA.Models;
3 | using OSDA.Views;
4 | using System;
5 | using System.Globalization;
6 | using System.IO;
7 | using System.IO.Ports;
8 | using System.Net.Http;
9 | using System.Runtime.Serialization.Json;
10 | using System.Text;
11 | using System.Threading;
12 | using System.Threading.Tasks;
13 | using System.Windows.Media;
14 | using System.Windows.Threading;
15 |
16 | namespace OSDA.ViewModels
17 | {
18 | internal class MainWindowViewModel : MainWindowBase, IDisposable
19 | {
20 | #region 字段
21 | internal SerialPort SerialPortBase = new SerialPort();
22 |
23 | internal GitRelease GitReleaseBase = new GitRelease();
24 |
25 | ///
26 | /// 保存接收,数据保存路径
27 | ///
28 | private volatile string DataRecvPath = string.Empty;
29 |
30 | ///
31 | /// 用于接收区数据超过32MB时,自动清空接收控件中的数据
32 | ///
33 | private volatile Int32 RecvDataDeleteCount = 1;
34 | #endregion
35 |
36 | public SerialPortModel SerialPortModel { get; set; }
37 | public SendModel SendModel { get; set; }
38 | public RecvModel RecvModel { get; set; }
39 | public TimerModel TimerModel { get; set; }
40 | public HelpModel HelpModel { get; set; }
41 |
42 | #region 状态栏- 信息描述
43 | private string _DepictInfo;
44 | public string DepictInfo
45 | {
46 | get { return _DepictInfo; }
47 | set
48 | {
49 | if (_DepictInfo != value)
50 | {
51 | _DepictInfo = value;
52 | RaisePropertyChanged(nameof(DepictInfo));
53 | }
54 | }
55 | }
56 | #endregion
57 |
58 | #region 菜单栏
59 |
60 | #region 文件
61 | internal void ExitWindow()
62 | {
63 | /* 仅当成功在SerialPort对象上调用Open()方法且最近一次没有调用Close()方法时,才返回True */
64 | if (SerialPortBase.IsOpen)
65 | {
66 | CloseSP();
67 | }
68 | }
69 | #endregion
70 |
71 | #region 选项
72 |
73 | #region 字节编码
74 | internal void ASCIIEnable()
75 | {
76 | SerialPortModel.UTF8Enable = false;
77 | SerialPortModel.UTF16Enable = false;
78 | SerialPortModel.UTF32Enable = false;
79 |
80 | SerialPortModel.ASCIIEnable = true;
81 |
82 | try
83 | {
84 | if(SerialPortModel.ASCIIEnable)
85 | {
86 | SerialPortBase.Encoding = System.Text.Encoding.ASCII;
87 | }
88 | }
89 | catch(ArgumentException e)
90 | {
91 | DepictInfo = e.Message.Replace("\r\n", "");
92 | }
93 | }
94 |
95 | internal void UTF8Enable()
96 | {
97 | SerialPortModel.ASCIIEnable = false;
98 | SerialPortModel.UTF16Enable = false;
99 | SerialPortModel.UTF32Enable = false;
100 |
101 | SerialPortModel.UTF8Enable = true;
102 |
103 | try
104 | {
105 | if (SerialPortModel.UTF8Enable)
106 | {
107 | SerialPortBase.Encoding = System.Text.Encoding.UTF8;
108 | }
109 | }
110 | catch (ArgumentException e)
111 | {
112 | DepictInfo = e.Message.Replace("\r\n", "");
113 | }
114 | }
115 |
116 | internal void UTF16Enable()
117 | {
118 | SerialPortModel.ASCIIEnable = false;
119 | SerialPortModel.UTF8Enable = false;
120 | SerialPortModel.UTF32Enable = false;
121 |
122 | SerialPortModel.UTF16Enable = true;
123 |
124 | try
125 | {
126 | if (SerialPortModel.UTF16Enable)
127 | {
128 | SerialPortBase.Encoding = System.Text.Encoding.Unicode;
129 | }
130 | }
131 | catch (ArgumentException e)
132 | {
133 | DepictInfo = e.Message.Replace("\r\n", "");
134 | }
135 | }
136 |
137 | internal void UTF32Enable()
138 | {
139 | SerialPortModel.ASCIIEnable = false;
140 | SerialPortModel.UTF8Enable = false;
141 | SerialPortModel.UTF16Enable = false;
142 |
143 | SerialPortModel.UTF32Enable = true;
144 |
145 | try
146 | {
147 | if (SerialPortModel.UTF32Enable)
148 | {
149 | SerialPortBase.Encoding = System.Text.Encoding.UTF32;
150 | }
151 | }
152 | catch (ArgumentException e)
153 | {
154 | DepictInfo = e.Message.Replace("\r\n", "");
155 | }
156 | }
157 | #endregion
158 |
159 | internal void RtsEnable()
160 | {
161 | SerialPortModel.RtsEnable = !(SerialPortModel.RtsEnable);
162 |
163 | try
164 | {
165 | if(SerialPortModel.RtsEnable)
166 | {
167 | SerialPortBase.RtsEnable = true;
168 | }
169 | else
170 | {
171 | SerialPortBase.RtsEnable = false;
172 | }
173 | }
174 | catch(InvalidOperationException e)
175 | {
176 | DepictInfo = e.Message.Replace("\r\n", "");
177 | }
178 | catch (IOException e)
179 | {
180 | DepictInfo = e.Message.Replace("\r\n", "");
181 | }
182 | }
183 |
184 | internal void DtrEnable()
185 | {
186 | SerialPortModel.DtrEnable = !(SerialPortModel.DtrEnable);
187 |
188 | try
189 | {
190 | if (SerialPortModel.DtrEnable)
191 | {
192 | SerialPortBase.DtrEnable = true;
193 | }
194 | else
195 | {
196 | SerialPortBase.DtrEnable = false;
197 | }
198 | }
199 | catch (InvalidOperationException e)
200 | {
201 | DepictInfo = e.Message.Replace("\r\n", "");
202 | }
203 | catch (IOException e)
204 | {
205 | DepictInfo = e.Message.Replace("\r\n", "");
206 | }
207 | }
208 |
209 | #region 流控制
210 | internal void NoneEnable()
211 | {
212 | SerialPortModel.XOnXOffEnable = false;
213 | SerialPortModel.RequestToSendEnable = false;
214 | SerialPortModel.RequestToSendXOnXOffEnable = false;
215 |
216 | SerialPortModel.NoneEnable = true;
217 |
218 | try
219 | {
220 | if(SerialPortModel.NoneEnable)
221 | {
222 | SerialPortBase.Handshake = Handshake.None;
223 | }
224 | }
225 | catch (IOException e)
226 | {
227 | DepictInfo = e.Message.Replace("\r\n", "");
228 | }
229 | catch (ArgumentOutOfRangeException e)
230 | {
231 | DepictInfo = e.Message.Replace("\r\n", "");
232 | }
233 | }
234 |
235 | internal void RequestToSendEnable()
236 | {
237 | SerialPortModel.NoneEnable = false;
238 | SerialPortModel.XOnXOffEnable = false;
239 | SerialPortModel.RequestToSendXOnXOffEnable = false;
240 |
241 | SerialPortModel.RequestToSendEnable = true;
242 |
243 | try
244 | {
245 | if (SerialPortModel.RequestToSendEnable)
246 | {
247 | SerialPortBase.Handshake = Handshake.RequestToSend;
248 | }
249 | }
250 | catch (IOException e)
251 | {
252 | DepictInfo = e.Message.Replace("\r\n", "");
253 | }
254 | catch (ArgumentOutOfRangeException e)
255 | {
256 | DepictInfo = e.Message.Replace("\r\n", "");
257 | }
258 | }
259 |
260 | internal void XOnXOffEnable()
261 | {
262 | SerialPortModel.NoneEnable = false;
263 | SerialPortModel.RequestToSendEnable = false;
264 | SerialPortModel.RequestToSendXOnXOffEnable = false;
265 |
266 | SerialPortModel.XOnXOffEnable = true;
267 |
268 | try
269 | {
270 | if (SerialPortModel.XOnXOffEnable)
271 | {
272 | SerialPortBase.Handshake = Handshake.XOnXOff;
273 | }
274 | }
275 | catch (IOException e)
276 | {
277 | DepictInfo = e.Message.Replace("\r\n", "");
278 | }
279 | catch (ArgumentOutOfRangeException e)
280 | {
281 | DepictInfo = e.Message.Replace("\r\n", "");
282 | }
283 | }
284 |
285 | internal void RequestToSendXOnXOffEnable()
286 | {
287 | SerialPortModel.NoneEnable = false;
288 | SerialPortModel.XOnXOffEnable = false;
289 | SerialPortModel.RequestToSendEnable = false;
290 |
291 | SerialPortModel.RequestToSendXOnXOffEnable = true;
292 |
293 | try
294 | {
295 | if (SerialPortModel.RequestToSendXOnXOffEnable)
296 | {
297 | SerialPortBase.Handshake = Handshake.RequestToSendXOnXOff;
298 | }
299 | }
300 | catch (IOException e)
301 | {
302 | DepictInfo = e.Message.Replace("\r\n", "");
303 | }
304 | catch (ArgumentOutOfRangeException e)
305 | {
306 | DepictInfo = e.Message.Replace("\r\n", "");
307 | }
308 | }
309 | #endregion
310 |
311 | internal void TimeStampEnable()
312 | {
313 | TimerModel.TimeStampEnable = !(TimerModel.TimeStampEnable);
314 | }
315 |
316 | #region 发送换行
317 | internal void NonesEnable()
318 | {
319 | SendModel.CrEnable = false;
320 | SendModel.LfEnable = false;
321 | SendModel.CrLfEnable = false;
322 |
323 | SendModel.NonesEnable = true;
324 | }
325 |
326 | internal void CrEnable()
327 | {
328 | SendModel.NonesEnable = false;
329 | SendModel.LfEnable = false;
330 | SendModel.CrLfEnable = false;
331 |
332 | SendModel.CrEnable = true;
333 | }
334 |
335 | internal void LfEnable()
336 | {
337 | SendModel.NonesEnable = false;
338 | SendModel.CrEnable = false;
339 | SendModel.CrLfEnable = false;
340 |
341 | SendModel.LfEnable = true;
342 | }
343 |
344 | internal void CrLfEnable()
345 | {
346 | SendModel.NonesEnable = false;
347 | SendModel.CrEnable = false;
348 | SendModel.LfEnable = false;
349 |
350 | SendModel.CrLfEnable = true;
351 | }
352 | #endregion
353 |
354 | #endregion
355 |
356 | #region 视图
357 | internal void ReducedEnable()
358 | {
359 | HelpModel.ReducedEnable = !HelpModel.ReducedEnable;
360 |
361 | if(HelpModel.ReducedEnable)
362 | {
363 | HelpModel.ViewVisibility = "Collapsed";
364 | }
365 | else
366 | {
367 | HelpModel.ViewVisibility = "Visible";
368 | }
369 | }
370 | #endregion
371 |
372 | #region 帮助
373 | internal async void UpdateAsync()
374 | {
375 | var _ReleaseDeserializer = new DataContractJsonSerializer(typeof(GitRelease));
376 |
377 | GitRelease _ReleaseGit = await DownloadJsonObjectAsync(
378 | GitReleaseBase.GithubURI, _ReleaseDeserializer, "github").ConfigureAwait(false);
379 |
380 | if (_ReleaseGit == default)
381 | {
382 | DepictInfo = string.Format(CultureInfos, "更换服务器......请稍后");
383 |
384 | _ReleaseGit = await DownloadJsonObjectAsync(
385 | GitReleaseBase.GiteeURI, _ReleaseDeserializer, "gitee").ConfigureAwait(false);
386 |
387 | if (_ReleaseGit == default)
388 | {
389 | DepictInfo = string.Format(CultureInfos, "请检查网络或稍后再试!");
390 |
391 | return;
392 | }
393 | }
394 |
395 | UpdateVersionCompareTo(_ReleaseGit.GetVersion());
396 | }
397 |
398 | private protected async Task DownloadJsonObjectAsync(Uri address, DataContractJsonSerializer serializer, string git)
399 | {
400 | if(serializer == null)
401 | {
402 | return default;
403 | }
404 |
405 | try
406 | {
407 | using (var _httpClient = new HttpClient())
408 | {
409 | _httpClient.DefaultRequestHeaders.Add("User-Agent", "Other");
410 | _httpClient.Timeout = TimeSpan.FromMilliseconds(3000);
411 |
412 | if (git == "github")
413 | {
414 | DepictInfo = string.Format(CultureInfos, "等待 GitHub.com 响应数据......");
415 | }
416 | else if (git == "gitee")
417 | {
418 | DepictInfo = string.Format(CultureInfos, "等待 Gitee.com 响应数据......");
419 | }
420 |
421 | var _resPonse = await _httpClient.GetAsync(address).ConfigureAwait(false);
422 | _resPonse.EnsureSuccessStatusCode();
423 |
424 | var _jsonData = await _resPonse.Content.ReadAsStringAsync().ConfigureAwait(false);
425 |
426 | using (var _jsonStream = new MemoryStream(Encoding.UTF8.GetBytes(_jsonData)))
427 | {
428 | return (T)serializer.ReadObject(_jsonStream);
429 | }
430 | }
431 | }
432 | catch(ArgumentException e)
433 | {
434 | DepictInfo = e.Message.Replace("\r\n", "");
435 |
436 | return default;
437 | }
438 | catch(HttpRequestException e)
439 | {
440 | DepictInfo = e.Message.Replace("\r\n", "");
441 |
442 | return default;
443 | }
444 | catch(TaskCanceledException e)
445 | {
446 | DepictInfo = e.Message.Replace("\r\n", "");
447 |
448 | return default;
449 | }
450 | }
451 |
452 | private void UpdateVersionCompareTo(Version NewVersion)
453 | {
454 | Version OldVersion = new Version(HelpModel.VerInfoNumber);
455 |
456 | if (NewVersion.CompareTo(OldVersion) > 0)
457 | {
458 | Thread wPFUpdateThread = new Thread(new ThreadStart(ThreadStartingWPFUpdate));
459 | wPFUpdateThread.SetApartmentState(ApartmentState.STA);
460 | wPFUpdateThread.IsBackground = true;
461 | wPFUpdateThread.Start();
462 | }
463 | else
464 | {
465 | DepictInfo = string.Format(CultureInfos, "OSDA v" + HelpModel.VerInfoNumber + " 已经是最新版le......");
466 | }
467 | }
468 |
469 | private void ThreadStartingWPFUpdate()
470 | {
471 | DepictInfo = string.Format(CultureInfos, "串行端口调试助手");
472 |
473 | WPFUpdate wPFUpdate = new WPFUpdate();
474 | wPFUpdate.Show();
475 | Dispatcher.Run();
476 | }
477 | #endregion
478 |
479 | #endregion
480 |
481 | #region 打开/关闭串口
482 | internal void OpenSP()
483 | {
484 | if (SerialPortBase.IsOpen)
485 | {
486 | CloseSP();
487 |
488 | return;
489 | }
490 |
491 | try
492 | {
493 | SerialPortBase.PortName = SerialPortModel.Port;
494 | SerialPortBase.BaudRate = SerialPortModel.BaudRate;
495 | SerialPortBase.DataBits = SerialPortModel.DataBits;
496 | SerialPortBase.StopBits = SerialPortModel.StopBits;
497 | SerialPortBase.Parity = SerialPortModel.Parity;
498 |
499 | SerialPortBase.WriteBufferSize = 1048576; /* 输出缓冲区的大小为1048576字节 = 1MB */
500 | SerialPortBase.ReadBufferSize = 2097152; /* 输入缓冲区的大小为2097152字节 = 2MB */
501 |
502 | /* 字节编码 */
503 | if (SerialPortModel.ASCIIEnable)
504 | {
505 | SerialPortBase.Encoding = System.Text.Encoding.ASCII;
506 | }
507 | else if (SerialPortModel.UTF8Enable)
508 | {
509 | SerialPortBase.Encoding = System.Text.Encoding.UTF8;
510 | }
511 | else if (SerialPortModel.UTF16Enable)
512 | {
513 | SerialPortBase.Encoding = System.Text.Encoding.Unicode;
514 | }
515 | else if (SerialPortModel.UTF32Enable)
516 | {
517 | SerialPortBase.Encoding = System.Text.Encoding.UTF32;
518 | }
519 |
520 | /* 发送请求(RTS)信号 */
521 | if (SerialPortModel.RtsEnable)
522 | {
523 | SerialPortBase.RtsEnable = true;
524 | }
525 | else
526 | {
527 | SerialPortBase.RtsEnable = false;
528 | }
529 |
530 | /* 数据终端就绪(DTR)信号 */
531 | if (SerialPortModel.DtrEnable)
532 | {
533 | SerialPortBase.DtrEnable = true;
534 | }
535 | else
536 | {
537 | SerialPortBase.DtrEnable = false;
538 | }
539 |
540 | /* 流控制 */
541 | if (SerialPortModel.NoneEnable)
542 | {
543 | SerialPortBase.Handshake = Handshake.None;
544 | }
545 | else if (SerialPortModel.RequestToSendEnable)
546 | {
547 | SerialPortBase.Handshake = Handshake.RequestToSend;
548 | }
549 | else if (SerialPortModel.XOnXOffEnable)
550 | {
551 | SerialPortBase.Handshake = Handshake.XOnXOff;
552 | }
553 | else if (SerialPortModel.RequestToSendXOnXOffEnable)
554 | {
555 | SerialPortBase.Handshake = Handshake.RequestToSendXOnXOff;
556 | }
557 |
558 | /* 数据接收事件 */
559 | SerialPortBase.DataReceived += new SerialDataReceivedEventHandler(SerialPortDataReceived);
560 |
561 | /* 信号状态事件 */
562 | SerialPortBase.PinChanged += new SerialPinChangedEventHandler(SerialPortPinChanged);
563 |
564 | SerialPortBase.Open();
565 |
566 | if (SerialPortBase.IsOpen)
567 | {
568 | SerialPortModel.Brush = Brushes.GreenYellow;
569 | SerialPortModel.OpenClose = string.Format(CultureInfos, "关闭串口");
570 | DepictInfo = string.Format(CultureInfos, "成功打开串行端口{0}、波特率{1}、数据位{2}、停止位{3}、校验位{4}",
571 | SerialPortBase.PortName,
572 | SerialPortBase.BaudRate.ToString(CultureInfos),
573 | SerialPortBase.DataBits.ToString(CultureInfos),
574 | SerialPortBase.StopBits.ToString(),
575 | SerialPortBase.Parity.ToString());
576 |
577 | SerialPortModel.PortEnable = false;
578 | SerialPortModel.BaudRateEnable = false;
579 | SerialPortModel.DataBitsEnable = false;
580 | SerialPortModel.StopBitsEnable = false;
581 | SerialPortModel.ParityEnable = false;
582 |
583 | if (RecvModel.EnableRecv)
584 | {
585 | RecvModel.RecvEnable = string.Format(CultureInfos, "允许");
586 | }
587 | else
588 | {
589 | RecvModel.RecvEnable = string.Format(CultureInfos, "暂停");
590 | }
591 | }
592 | else
593 | {
594 | DepictInfo = string.Format(CultureInfos, "串行端口打开失败");
595 | }
596 | }
597 | catch (UnauthorizedAccessException e)
598 | {
599 | DepictInfo = e.Message.Replace("\r\n", "");
600 | }
601 | catch (ArgumentOutOfRangeException e)
602 | {
603 | DepictInfo = e.Message.Replace("\r\n", "");
604 | }
605 | catch (ArgumentException e)
606 | {
607 | DepictInfo = string.Format(CultureInfos, "串行端口属性{0}为非法参数,请重新输入", e.ParamName);
608 | }
609 | catch (IOException e)
610 | {
611 | DepictInfo = e.Message.Replace("\r\n", "");
612 | }
613 | catch (InvalidOperationException e)
614 | {
615 | DepictInfo = e.Message.Replace("\r\n", "");
616 | }
617 | }
618 |
619 | private void CloseSP()
620 | {
621 | try
622 | {
623 | /*
624 | * 该方法调用Component.Dispose()方法,同时还会
625 | * 调用disposing参数设置为True的受保护的SerialPort.Dispose(Boolean)方法
626 | */
627 | SerialPortBase.Close(); /* 关闭SerialPort对象,并清除接收缓冲区和发送缓冲区 */
628 |
629 | SerialPortModel.Brush = Brushes.Red;
630 | SerialPortModel.OpenClose = string.Format(CultureInfos, "打开串口");
631 |
632 | DepictInfo = string.Format(CultureInfos, "串行端口关闭成功");
633 |
634 | SerialPortModel.PortEnable = true;
635 | SerialPortModel.BaudRateEnable = true;
636 | SerialPortModel.DataBitsEnable = true;
637 | SerialPortModel.StopBitsEnable = true;
638 | SerialPortModel.ParityEnable = true;
639 |
640 | RecvModel.RecvAutoSave = string.Format(CultureInfos, "已停止");
641 | }
642 | catch(IOException e)
643 | {
644 | DepictInfo = e.Message.Replace("\r\n", "");
645 | }
646 | }
647 | #endregion
648 |
649 | #region 辅助区
650 | private bool _SaveRecv;
651 | public bool SaveRecv
652 | {
653 | get
654 | {
655 | return _SaveRecv;
656 | }
657 | set
658 | {
659 | if (_SaveRecv != value)
660 | {
661 | _SaveRecv = value;
662 | RaisePropertyChanged(nameof(SaveRecv));
663 | }
664 |
665 | if (SaveRecv)
666 | {
667 | DepictInfo = string.Format(CultureInfos, "接收数据默认保存在程序基目录,可以点击路径选择操作更换");
668 | }
669 | else
670 | {
671 | DepictInfo = string.Format(CultureInfos, "串行端口调试助手");
672 | }
673 | }
674 | }
675 |
676 | private bool _HexSend;
677 | public bool HexSend
678 | {
679 | get
680 | {
681 | return _HexSend;
682 | }
683 | set
684 | {
685 | if (_HexSend != value)
686 | {
687 | _HexSend = value;
688 | RaisePropertyChanged(nameof(HexSend));
689 |
690 | if (HexSend == true)
691 | {
692 | DepictInfo = string.Format(CultureInfos, "请输入合法十六进制数据,且用空格隔开,比如A0 B1 C2 D3 E4 F5");
693 | }
694 | else
695 | {
696 | DepictInfo = string.Format(CultureInfos, "串行端口调试助手");
697 | }
698 | }
699 | }
700 | }
701 |
702 | private bool _AutoSend;
703 | public bool AutoSend
704 | {
705 | get
706 | {
707 | return _AutoSend;
708 | }
709 | set
710 | {
711 | if (_AutoSend != value)
712 | {
713 | _AutoSend = value;
714 | RaisePropertyChanged(nameof(AutoSend));
715 | }
716 |
717 | if (AutoSend == true)
718 | {
719 | if (String.IsNullOrWhiteSpace(SendModel.AutoSendNum))
720 | {
721 | DepictInfo = string.Format(CultureInfos, "请输入正确的发送时间间隔");
722 | return;
723 | }
724 |
725 | var _AutoSendNum = Convert.ToInt32(SendModel.AutoSendNum, CultureInfos);
726 |
727 | if (_AutoSendNum <= 0)
728 | {
729 | DepictInfo = string.Format(CultureInfos, "请输入正确的发送时间间隔");
730 | return;
731 | }
732 |
733 | StartAutoSendTimer(_AutoSendNum);
734 | }
735 | else
736 | {
737 | StopAutoSendTimer();
738 | DepictInfo = string.Format(CultureInfos, "串行端口调试助手");
739 | }
740 | }
741 | }
742 | #endregion
743 |
744 | #region 自动发送定时器实现
745 | private readonly DispatcherTimer AutoSendDispatcherTimer = new DispatcherTimer();
746 |
747 | private void InitAutoSendTimer()
748 | {
749 | AutoSendDispatcherTimer.IsEnabled = false;
750 | AutoSendDispatcherTimer.Tick += AutoSendDispatcherTimer_Tick;
751 | }
752 |
753 | private async void AutoSendDispatcherTimer_Tick(object sender, EventArgs e)
754 | {
755 | await SendAsync().ConfigureAwait(false);
756 | }
757 |
758 | private void StartAutoSendTimer(int interval)
759 | {
760 | AutoSendDispatcherTimer.IsEnabled = true;
761 | AutoSendDispatcherTimer.Interval = TimeSpan.FromMilliseconds(interval);
762 | AutoSendDispatcherTimer.Start();
763 | }
764 |
765 | private void StopAutoSendTimer()
766 | {
767 | AutoSendDispatcherTimer.IsEnabled = false;
768 | AutoSendDispatcherTimer.Stop();
769 | }
770 | #endregion
771 |
772 | #region 发送
773 | internal async Task SendAsync()
774 | {
775 | if (!SerialPortBase.IsOpen)
776 | {
777 | DepictInfo = string.Format(CultureInfos, "请先打开串行端口");
778 |
779 | return;
780 | }
781 |
782 | try
783 | {
784 | int SendCount = 0;
785 |
786 | if (HexSend)
787 | {
788 | string[] _sendData = SendModel.SendData.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
789 |
790 | byte[] sendData = new byte[_sendData.Length];
791 |
792 | foreach (var tmp in _sendData)
793 | {
794 | sendData[SendCount++] = byte.Parse(tmp, NumberStyles.AllowHexSpecifier, CultureInfos);
795 | }
796 |
797 | await SerialPortBase.BaseStream.WriteAsync(sendData, 0, SendCount).ConfigureAwait(false);
798 |
799 | }
800 | else
801 | {
802 | SendCount = SerialPortBase.Encoding.GetByteCount(SendModel.SendData);
803 | await SerialPortBase.BaseStream.WriteAsync(SerialPortBase.Encoding.GetBytes(SendModel.SendData), 0, SendCount)
804 | .ConfigureAwait(false);
805 | }
806 |
807 | if (SendModel.NonesEnable)
808 | {
809 | SendModel.SendDataCount += SendCount;
810 | }
811 | else if (SendModel.CrEnable)
812 | {
813 | await SerialPortBase.BaseStream.WriteAsync(SerialPortBase.Encoding.GetBytes("\r"), 0, 1)
814 | .ConfigureAwait(false);
815 | SendModel.SendDataCount += (SendCount + 1);
816 | }
817 | else if (SendModel.LfEnable)
818 | {
819 | await SerialPortBase.BaseStream.WriteAsync(SerialPortBase.Encoding.GetBytes("\n"), 0, 1)
820 | .ConfigureAwait(false);
821 | SendModel.SendDataCount += (SendCount + 1);
822 | }
823 | else if (SendModel.CrLfEnable)
824 | {
825 | await SerialPortBase.BaseStream.WriteAsync(SerialPortBase.Encoding.GetBytes("\r\n"), 0, 2)
826 | .ConfigureAwait(false);
827 | SendModel.SendDataCount += (SendCount + 2);
828 | }
829 | }
830 | catch (ArgumentException e)
831 | {
832 | DepictInfo = e.Message.Replace("\r\n", "");
833 | }
834 | catch (IOException e)
835 | {
836 | DepictInfo = e.Message.Replace("\r\n", "");
837 | }
838 | catch (OutOfMemoryException e)
839 | {
840 | DepictInfo = e.Message.Replace("\r\n", "");
841 | }
842 | catch (FormatException e)
843 | {
844 | DepictInfo = e.Message.Replace("\r\n", "");
845 | }
846 | catch(OverflowException)
847 | {
848 | DepictInfo = string.Format(CultureInfos, "请输入合法十六进制数据,且用空格隔开,比如A0 B1 C2 D3 E4 F5");
849 | }
850 | catch (IndexOutOfRangeException)
851 | {
852 | DepictInfo = string.Format(CultureInfos, "正在试图执行越界访问,请通过菜单栏<帮助>报告问题!");
853 | }
854 | catch (ObjectDisposedException)
855 | {
856 | DepictInfo = string.Format(CultureInfos, "正在对已释放的对象执行操作,请通过菜单栏<帮助>报告问题!");
857 | }
858 | catch (NotFiniteNumberException e)
859 | {
860 | DepictInfo = e.Message.Replace("\r\n", "");
861 | }
862 | }
863 | #endregion
864 |
865 | #region 发送文件
866 | internal async Task SendFileAsync()
867 | {
868 | if (!SerialPortBase.IsOpen)
869 | {
870 | DepictInfo = string.Format(CultureInfos, "请先打开串行端口");
871 |
872 | return;
873 | }
874 |
875 | try
876 | {
877 | OpenFileDialog SendDataOpenFileDialog = new OpenFileDialog
878 | {
879 | Title = string.Format(CultureInfos, "选择发送数据"),
880 | DefaultExt = "*.*",
881 | Filter = string.Format(CultureInfos, "所有类型|*.*")
882 | };
883 |
884 | if (SendDataOpenFileDialog.ShowDialog() == true)
885 | {
886 | var filePath = SendDataOpenFileDialog.FileName;
887 |
888 | if (filePath == null)
889 | {
890 | return;
891 | }
892 |
893 | HelpModel.StatusBarProgressBarVisibility = "Visible";
894 |
895 | var fileStream = SendDataOpenFileDialog.OpenFile();
896 |
897 | using (StreamReader reader = new StreamReader(fileStream))
898 | {
899 | var fileContent = reader.ReadToEnd();
900 | var SendCount = SerialPortBase.Encoding.GetByteCount(fileContent);
901 |
902 | DepictInfo = string.Format(CultureInfos, "文件正在发送......");
903 | HelpModel.StatusBarProgressBarIsIndeterminate = true;
904 |
905 | await SerialPortBase.BaseStream.WriteAsync(SerialPortBase.Encoding.GetBytes(fileContent), 0, SendCount)
906 | .ConfigureAwait(false);
907 |
908 | HelpModel.StatusBarProgressBarIsIndeterminate = false;
909 | DepictInfo = string.Format(CultureInfos, "文件发送完毕");
910 |
911 | SendModel.SendDataCount += SendCount;
912 | }
913 |
914 | HelpModel.StatusBarProgressBarVisibility = "Collapsed";
915 | }
916 | }
917 | catch(ArgumentException e)
918 | {
919 | DepictInfo = e.Message.Replace("\r\n", "");
920 | }
921 | catch(IOException e)
922 | {
923 | DepictInfo = e.Message.Replace("\r\n", "");
924 | }
925 | catch(OutOfMemoryException e)
926 | {
927 | DepictInfo = e.Message.Replace("\r\n", "");
928 | }
929 | catch(FormatException e)
930 | {
931 | DepictInfo = e.Message.Replace("\r\n", "");
932 | }
933 | catch (IndexOutOfRangeException)
934 | {
935 | DepictInfo = string.Format(CultureInfos, "正在试图执行越界访问,请通过菜单栏<帮助>报告问题!");
936 | }
937 | catch(ObjectDisposedException)
938 | {
939 | DepictInfo = string.Format(CultureInfos, "正在对已释放的对象执行操作,请通过菜单栏<帮助>报告问题!");
940 | }
941 | catch (NotFiniteNumberException e)
942 | {
943 | DepictInfo = e.Message.Replace("\r\n", "");
944 | }
945 | catch (InvalidOperationException e)
946 | {
947 | DepictInfo = e.Message.Replace("\r\n", "");
948 | }
949 | }
950 | #endregion
951 |
952 | #region 路径选择
953 | internal void SaveRecvPath()
954 | {
955 | SaveFileDialog ReceDataSaveFileDialog = new SaveFileDialog
956 | {
957 | Title = string.Format(CultureInfos, "接收数据保存"),
958 | FileName = string.Format(CultureInfos, "{0}", DateTime.Now.ToString("yyyyMMdd", CultureInfos)),
959 | DefaultExt = ".txt",
960 | Filter = string.Format(CultureInfos, "文本文件|*.txt")
961 | };
962 |
963 | if (ReceDataSaveFileDialog.ShowDialog() == true)
964 | {
965 | DataRecvPath = ReceDataSaveFileDialog.FileName;
966 | }
967 | }
968 | #endregion
969 |
970 | #region 清接收区
971 | internal void ClearReceData()
972 | {
973 | RecvModel.RecvData.Delete();
974 |
975 | RecvDataDeleteCount = 1;
976 | }
977 | #endregion
978 |
979 | #region 清发送区
980 | internal void ClearSendData()
981 | {
982 | SendModel.SendData = string.Empty;
983 | }
984 | #endregion
985 |
986 | #region 清空计数
987 | internal void ClearCount()
988 | {
989 | RecvModel.RecvDataCount = 0;
990 | SendModel.SendDataCount = 0;
991 | }
992 | #endregion
993 |
994 | #region 数据接收事件实现
995 | private void SerialPortDataReceived(object sender, SerialDataReceivedEventArgs e)
996 | {
997 | if ((SerialPort)sender == null)
998 | {
999 | return;
1000 | }
1001 |
1002 | SerialPort _SerialPort = (SerialPort)sender;
1003 |
1004 | int _BytesToRead = _SerialPort.BytesToRead;
1005 | byte[] _RecvData = new byte[_BytesToRead];
1006 |
1007 | _SerialPort.Read(_RecvData, 0, _BytesToRead);
1008 |
1009 | if (RecvModel.EnableRecv)
1010 | {
1011 | if (TimerModel.TimeStampEnable)
1012 | {
1013 | DateTime _DateTime = DateTime.Now;
1014 | RecvModel.RecvData.Append("[ " + _DateTime.ToString("yyyy/MM/dd HH:mm:ss:ffff", CultureInfos) + " ]");
1015 | }
1016 |
1017 | if (RecvModel.HexRecv)
1018 | {
1019 | foreach (var tmp in _RecvData)
1020 | {
1021 | RecvModel.RecvData.Append(string.Format(CultureInfos, "{0:X2} ", tmp));
1022 | }
1023 | }
1024 | else
1025 | {
1026 | RecvModel.RecvData.Append(_SerialPort.Encoding.GetString(_RecvData));
1027 | }
1028 |
1029 | if (TimerModel.TimeStampEnable)
1030 | {
1031 | RecvModel.RecvData.Append("\r\n");
1032 | }
1033 | }
1034 |
1035 | if (SaveRecv)
1036 | {
1037 | RecvModel.RecvAutoSave = string.Format(CultureInfos, "保存中");
1038 |
1039 | SaveRecvData(_SerialPort.Encoding.GetString(_RecvData));
1040 | }
1041 | else
1042 | {
1043 | RecvModel.RecvAutoSave = string.Format(CultureInfos, "已停止");
1044 | }
1045 |
1046 | RecvModel.RecvDataCount += _RecvData.Length;
1047 |
1048 | if (RecvModel.RecvDataCount > (32768 * RecvDataDeleteCount))
1049 | {
1050 | RecvModel.RecvData.Delete();
1051 |
1052 | RecvDataDeleteCount += 1; /* 接收区数据达到32MB(32768KB)或其倍数,则自动清空接收区数据 */
1053 | }
1054 | }
1055 |
1056 | private async void SaveRecvData(string ReceData)
1057 | {
1058 | try
1059 | {
1060 | /* 从路径的字符串长度判断路径是否合法(路径字符串长度小于1个必定不合法) */
1061 | if (DataRecvPath.Length < 1)
1062 | {
1063 | Directory.CreateDirectory(AppDomain.CurrentDomain.BaseDirectory + "\\ReceData\\");
1064 |
1065 | DataRecvPath = AppDomain.CurrentDomain.BaseDirectory +
1066 | "\\ReceData\\" + DateTime.Now.ToString("yyyyMMdd", CultureInfos) + ".txt";
1067 |
1068 | using (StreamWriter DefaultReceDataPath = new StreamWriter(DataRecvPath, true))
1069 | {
1070 | await DefaultReceDataPath.WriteAsync(ReceData).ConfigureAwait(false);
1071 | }
1072 | }
1073 | else
1074 | {
1075 | using (StreamWriter DefaultReceDataPath = new StreamWriter(DataRecvPath, true))
1076 | {
1077 | await DefaultReceDataPath.WriteAsync(ReceData).ConfigureAwait(false);
1078 | }
1079 | }
1080 | }
1081 | catch(IOException e)
1082 | {
1083 | SaveRecv = false;
1084 | RecvModel.RecvAutoSave = string.Format(CultureInfos, "已停止");
1085 |
1086 | DepictInfo = e.Message.Replace("\r\n", "");
1087 | }
1088 | catch(ArgumentException e)
1089 | {
1090 | SaveRecv = false;
1091 | RecvModel.RecvAutoSave = string.Format(CultureInfos, "已停止");
1092 |
1093 | DepictInfo = e.Message.Replace("\r\n", "");
1094 | }
1095 | catch(UnauthorizedAccessException e)
1096 | {
1097 | SaveRecv = false;
1098 | RecvModel.RecvAutoSave = string.Format(CultureInfos, "已停止");
1099 |
1100 | DepictInfo = e.Message.Replace("\r\n", "");
1101 | }
1102 | catch(NotSupportedException e)
1103 | {
1104 | SaveRecv = false;
1105 | RecvModel.RecvAutoSave = string.Format(CultureInfos, "已停止");
1106 |
1107 | DepictInfo = e.Message.Replace("\r\n", "");
1108 | }
1109 | catch (IndexOutOfRangeException)
1110 | {
1111 | SaveRecv = false;
1112 | RecvModel.RecvAutoSave = string.Format(CultureInfos, "已停止");
1113 |
1114 | DepictInfo = string.Format(CultureInfos, "正在试图执行越界访问,请通过菜单栏<帮助>报告问题!");
1115 | }
1116 | catch (ObjectDisposedException)
1117 | {
1118 | SaveRecv = false;
1119 | RecvModel.RecvAutoSave = string.Format(CultureInfos, "已停止");
1120 |
1121 | DepictInfo = string.Format(CultureInfos, "正在对已释放的对象执行操作,请通过菜单栏<帮助>报告问题!");
1122 | }
1123 | catch (AppDomainUnloadedException)
1124 | {
1125 | SaveRecv = false;
1126 | RecvModel.RecvAutoSave = string.Format(CultureInfos, "已停止");
1127 |
1128 | DepictInfo = string.Format(CultureInfos, "正在访问已卸载的应用程序域,请通过菜单栏<帮助>报告问题!");
1129 | }
1130 | catch(System.Security.SecurityException e)
1131 | {
1132 | SaveRecv = false;
1133 | RecvModel.RecvAutoSave = string.Format(CultureInfos, "已停止");
1134 |
1135 | DepictInfo = e.Message.Replace("\r\n", "");
1136 | }
1137 | }
1138 | #endregion
1139 |
1140 | #region 信号状态事件实现
1141 | private void SerialPortPinChanged(object sender, SerialPinChangedEventArgs e)
1142 | {
1143 | if((SerialPort)sender == null)
1144 | {
1145 | return;
1146 | }
1147 |
1148 | if(e == null)
1149 | {
1150 | return;
1151 | }
1152 |
1153 | SerialPort _SerialPort = (SerialPort)sender;
1154 |
1155 | switch (e.EventType)
1156 | {
1157 | case SerialPinChange.CDChanged:
1158 | if (_SerialPort.CDHolding)
1159 | {
1160 | SerialPortModel.DcdBrush = Brushes.GreenYellow;
1161 | }
1162 | else
1163 | {
1164 | SerialPortModel.DcdBrush = Brushes.Black;
1165 | }
1166 | break;
1167 | case SerialPinChange.CtsChanged:
1168 | if (_SerialPort.CtsHolding)
1169 | {
1170 | SerialPortModel.CtsBrush = Brushes.GreenYellow;
1171 | }
1172 | else
1173 | {
1174 | SerialPortModel.CtsBrush = Brushes.Black;
1175 | }
1176 | break;
1177 | case SerialPinChange.DsrChanged:
1178 | if (_SerialPort.DsrHolding)
1179 | {
1180 | SerialPortModel.DsrBrush = Brushes.GreenYellow;
1181 | }
1182 | else
1183 | {
1184 | SerialPortModel.DsrBrush = Brushes.Black;
1185 | }
1186 | break;
1187 | default:
1188 | break;
1189 | }
1190 | }
1191 | #endregion
1192 |
1193 | #region RecvTextBox Mouse Double Support
1194 | internal void EnableRecv()
1195 | {
1196 | RecvModel.EnableRecv = !RecvModel.EnableRecv;
1197 |
1198 | if(RecvModel.EnableRecv)
1199 | {
1200 | RecvModel.RecvEnable = string.Format(CultureInfos, "允许");
1201 | }
1202 | else
1203 | {
1204 | RecvModel.RecvEnable = string.Format(CultureInfos, "暂停");
1205 | }
1206 | }
1207 | #endregion
1208 |
1209 | public MainWindowViewModel()
1210 | {
1211 | SerialPortModel = new SerialPortModel();
1212 | SerialPortModel.SerialPortDataContext();
1213 |
1214 | SendModel = new SendModel();
1215 | SendModel.SendDataContext();
1216 |
1217 | RecvModel = new RecvModel();
1218 | RecvModel.RecvDataContext();
1219 |
1220 | TimerModel = new TimerModel();
1221 | TimerModel.TimerDataContext();
1222 |
1223 | HelpModel = new HelpModel();
1224 | HelpModel.HelpDataContext();
1225 |
1226 | SaveRecv = false;
1227 | HexSend = false;
1228 | AutoSend = false;
1229 | InitAutoSendTimer();
1230 |
1231 | DepictInfo = string.Format(CultureInfos, "串行端口调试助手");
1232 | }
1233 |
1234 | #region IDisposable Support
1235 | private bool disposedValue = false; /* 冗余检测 */
1236 |
1237 | ///
1238 | /// 释放组件所使用的非托管资源,并且有选择的释放托管资源(可以看作是Dispose()的安全实现)
1239 | ///
1240 | ///
1241 | protected virtual void Dispose(bool disposing)
1242 | {
1243 | /* 检查是否已调用dispose */
1244 | if (!disposedValue)
1245 | {
1246 | if (disposing)
1247 | {
1248 | /* 释放托管资源(如果需要的话) */
1249 |
1250 | /* SerialPort属于托管资源,但其本身却拥有非托管资源,所以需要实现IDisposable */
1251 | SerialPortBase.DataReceived -= SerialPortDataReceived;
1252 | SerialPortBase.PinChanged -= SerialPortPinChanged;
1253 | SerialPortBase.Dispose();
1254 | }
1255 |
1256 | /* 释放非托管资源(如果有的话) */
1257 |
1258 | disposedValue = true; /* 处理完毕 */
1259 | }
1260 | }
1261 |
1262 | ///
1263 | /// 实现IDisposable,释放组件所使用的所有资源
1264 | ///
1265 | public void Dispose()
1266 | {
1267 | Dispose(true);
1268 | GC.SuppressFinalize(this); /* this: OSDA.ViewModels.MainWindowViewmodel */
1269 | }
1270 | #endregion
1271 | }
1272 | }
1273 |
--------------------------------------------------------------------------------