Compare commits

...

30 Commits

Author SHA1 Message Date
DESKTOP-3BO4HSG\ksat f265b48e8a chore: optimized singleton pattern is lazy and thread-safe
2 years ago
DESKTOP-3BO4HSG\ksat 758a21f9ad perf: update new serve
2 years ago
Song 0b3a9ee6f0
feat: update config model
2 years ago
DESKTOP-3BO4HSG\ksat ec2ded168e perf: optimize animation effects
2 years ago
DESKTOP-3BO4HSG\ksat 98b6408115 docs: api failure description
2 years ago
DESKTOP-3BO4HSG\ksat 67141f97bd docs: update readme
2 years ago
DESKTOP-3BO4HSG\ksat 5b9731caec perf: update version to 0.25
2 years ago
SONGE9B3\song_pd_win11 d5eac2ebf0 perf: optimized display
2 years ago
SONGE9B3\song_pd_win11 7eaa02503c feat: add toast
2 years ago
Song 0bdd7757ce
docs: update readme
2 years ago
SONGE9B3\song_pd_win11 4000bd23d5 docs: update readme
2 years ago
DESKTOP-3BO4HSG\ksat 46b1da8b14 Merge branch 'main' of https://github.com/ZGGSONG/STranslate
2 years ago
SONGE9B3\song_pd_win11 af38ef7cfb chore: update version tag
2 years ago
Song 18ecb6aca5
Update README.md
2 years ago
SONGE9B3\song_pd_win11 8abd2f3dea feat: update new api
2 years ago
DESKTOP-3BO4HSG\ksat 21c5cab0f8 feat: add tooltip
2 years ago
DESKTOP-3BO4HSG\ksat 9b2fbc6e49 perf: create desktop shorcut at first time
2 years ago
DESKTOP-3BO4HSG\ksat 01b9af34dd Merge branch 'main' of https://github.com/ZGGSONG/STranslate
2 years ago
DESKTOP-3BO4HSG\ksat e4c690f226 feat: optimize the problem of blurred icons when switching resolution
2 years ago
zggsong d3da657e52 chore: ignore .dsstore
2 years ago
zggsong 127c5c3d56 docs: update readme
2 years ago
DESKTOP-3BO4HSG\ksat 1f6b277c8e Merge branch 'main' of https://github.com/ZGGSONG/STranslate
2 years ago
DESKTOP-3BO4HSG\ksat 1d91ab510e 0.21
2 years ago
DESKTOP-3BO4HSG\ksat b561f44678 feat: add reset hot keys
2 years ago
DESKTOP-3BO4HSG\ksat 471cc632b2 feat: add change hotkeys func
2 years ago
DESKTOP-3BO4HSG\ksat 84ea248601 perf: add keydown to textbox
2 years ago
DESKTOP-3BO4HSG\ksat 74eb8755a5 fix: hot keys conflict message
2 years ago
Song 0de7a3776d
docs: update readme
2 years ago
DESKTOP-3BO4HSG\ksat 5fbfc19ec3 feat: add translation local cache function
2 years ago
DESKTOP-3BO4HSG\ksat a93c422838 perf: update chinese and english automatic recognition proportion configuration item
2 years ago

4
.gitignore vendored

@ -4,4 +4,6 @@ obj/
*.user
.idea/
packages/
packages/
.DS_Store

@ -10,11 +10,11 @@
<a href="https://github.com/ZGGSONG/STranslate/releases/latest" target="_blank">
<img alt="Latest GitHub release" src="https://img.shields.io/github/release/ZGGSONG/STranslate.svg" />
</a>
<a href="https://github.com/ZGGSONG/STranslate" target="_self">
<img alt="GitHub last commit" src="https://img.shields.io/github/last-commit/ZGGSONG/STranslate" />
<a href="https://hub.docker.com/r/zggsong/translate">
<img alt="Docker pull" src="https://img.shields.io/docker/pulls/zggsong/translate">
</a>
<a href="https://github.com/ZGGSONG/STranslate" target="_self">
<img alt="GitHub repo size" src="https://img.shields.io/github/repo-size/ZGGSONG/STranslate" />
<img alt="GitHub last commit" src="https://img.shields.io/github/last-commit/ZGGSONG/STranslate" />
</a>
</p>
<h1 align="center">STranslate</h1>
@ -25,18 +25,20 @@
## 功能
- [x] 添加 DeepL API
- [x] 实现基本翻译功能
- [x] 优化防止多开
- [x] 添加划词翻译
- [x] 添加复制结果蛇形、大小驼峰
- [x] 软件层面识别语种(目前支持中英文)
- [x] 软件层面识别语种(中英文)
- [x] 添加开机自启
- [x] 添加明/暗主题
- [x] 添加 UI 设置缓存(用户目录下 `AppData\Local\STranslate`)
- [x] 添加语音合成
- [x] 添加离线截图翻译
- [x] 添加离线语音合成
- [x] 添加离线截图文字识别(支持英文, 中文数据包过大且体验不好)
- [x] 添加检查更新
- [ ] 添加翻译记录缓存功能
- [x] 添加翻译记录缓存功能
## 安装
下载最新 [Release](https://github.com/ZGGSONG/STranslate/releases) 版本后解压即可使用
## 使用
@ -58,14 +60,31 @@
- `Ctrl+Shift+R` 切换主题
- `Ctrl+Shift+T` 置顶/取消置顶
点击软件外部界面任意处或点击软件则会自动隐藏到后台,即用即走。
点击软件外部任意处即自动隐藏到后台——即用即走。
> STranslate依赖于.NET Framework 4.8 运行环境如果程序启动时提示“This application requires *** .NETFramework,Version=v4.8”,请点击以下链接下载并安装.NET Framework 4.8 运行环境。
> [适用于 Windows 的 Microsoft .NET Framework 4.8 脱机安装程序下载](https://download.visualstudio.microsoft.com/download/pr/2d6bb6b2-226a-4baa-bdec-798822606ff1/8494001c276a4b96804cde7829c04d7f/ndp48-x86-x64-allos-enu.exe) | [Microsoft Support](https://support.microsoft.com/zh-cn/topic/%E9%80%82%E7%94%A8%E4%BA%8E-windows-%E7%9A%84-microsoft-net-framework-4-8-%E8%84%B1%E6%9C%BA%E5%AE%89%E8%A3%85%E7%A8%8B%E5%BA%8F-9d23f658-3b97-68ab-d013-aa3c3e7495e0)
## 卸载
1. 删除软件运行目录
2. 打开 cmd 运行下面的命令即可
```shell
rd /s /q "%localappdata%\stranslate"
```
## 开发历史
- 2023-03-02 0.25 添加复制提醒动画
- 2023-02-28 0.24 添加 deepl([deno.dev](deno.dev)) 接口(已经安装的cmd运行 `del %localappdata%\stranslate\stranslate.json` 后打开即可更新接口)
- 2023-02-24 0.22 优化分辨率切换时托盘图标模糊问题
- 2023-01-17 0.20 添加翻译记录缓存功能,重复翻译从本地数据库获取,本地记录数量上限可调整
- 2023-01-12 0.18 优化 GC 后台静默运行内存占用保持 4MB 左右
- 2023-01-12 0.17 添加检查更新功能
@ -106,17 +125,14 @@ public static string TesseractGetText(Bitmap bmp)
- 2022-12-27 0.08 版本添加开机启动
![previews](./example_tray.png)
## 接口失效
若远端接口均失效,需要自己本地运行翻译服务(感谢[zu1k](https://github.com/zu1k)),根据自己的系统 [下载可执行文件](https://github.com/zu1k/removed-2022-07-12/releases/tag/0.1.2) 自己的版本,软件右上角选择 `local` 接口即可
## 如果接口失效
当请求人数较多时,远端接口可能暂时失效,可自行运行翻译接口程序
1. **【推荐】** 下载对应平台可 [执行文件](https://github.com/ZGGSONG/STranslate/releases/tag/0.01),随后在软件右上角选择 `local` 接口即可
2. 【进阶】 下载 [docker镜像](https://hub.docker.com/r/zggsong/translate),关闭软件 - cmd 运行 `start %localappdata%\stranslate\stranslate.json` - 修改接口地址 - 重启软件即可
## 参考项目
[https://github.com/NPCDW/WpfTool](https://github.com/NPCDW/WpfTool)
[https://github.com/zu1k/removed-2022-07-12/releases/tag/0.1.2](https://github.com/zu1k/removed-2022-07-12/releases/tag/0.1.2)
[https://github.com/Planshit/Tai](https://github.com/Planshit/Tai)

@ -0,0 +1,2 @@
@echo off
rd /s /q "%localappdata%\stranslate"

@ -10,7 +10,7 @@ using System.Threading.Tasks;
namespace STranslate.Helper
{
public class ConfigHelper
public class ConfigHelper : Singleton<ConfigHelper>
{
public T ReadConfig<T>()
{
@ -34,6 +34,7 @@ namespace STranslate.Helper
if (!Directory.Exists(_ApplicationData))//判断是否存在
{
Directory.CreateDirectory(_ApplicationData);//创建新路径
ShortcutHelper.SetDesktopShortcut();//创建桌面快捷方式
}
if (!File.Exists(_CnfName))//文件不存在
{
@ -53,7 +54,5 @@ namespace STranslate.Helper
/// </summary>
private static string _ApplicationData => $"{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}\\{_AppName}";
private static readonly string _AppName = Path.GetFileNameWithoutExtension(Assembly.GetEntryAssembly().Location);
private static ConfigHelper _Instance;
public static ConfigHelper Instance { get => _Instance ?? (_Instance = new ConfigHelper()); }
}
}

@ -2,45 +2,11 @@
using System.Collections.Generic;
using System.Windows;
using System.Windows.Interop;
using WpfScreenHelper;
using static STranslate.Helper.NativeMethodHelper;
namespace STranslate.Helper
{
public static class Hotkeys
{
public static class InputTranslate
{
public static byte Modifiers = (byte)KeyModifiers.MOD_ALT;
public static int Key = 65;
public static String Text = "A";
public static bool Conflict = false;
}
public static class CrosswordTranslate
{
public static byte Modifiers = (byte)KeyModifiers.MOD_ALT;
public static int Key = 68;
public static String Text = "D";
public static bool Conflict = false;
}
#if true
public static class ScreenShotTranslate
{
public static byte Modifiers = (byte)KeyModifiers.MOD_ALT;
public static int Key = 83;
public static String Text = "S";
public static bool Conflict = false;
}
#endif
public static class OpenMainWindow
{
public static byte Modifiers = (byte)KeyModifiers.MOD_ALT;
public static int Key = 71;
public static String Text = "G";
public static bool Conflict = false;
}
}
internal class HotkeysHelper
{
@ -81,6 +47,19 @@ namespace STranslate.Helper
{
keymap[id] = callBack;
}
/// <summary>
/// 屏幕分辨率以及文本显示比例变更对应的消息标志
/// </summary>
private const int WmDisplayChange = 0x007e;
/// <summary>
/// 文本显示比例变更消息标志
/// </summary>
private const int WmTextChange = 0x02E0;
/// <summary>
/// window消息定义的 注册的热键消息标志
/// </summary>
private const int WmHotkeys = 0x0312;
/// <summary>
/// 快捷键消息处理
/// </summary>
@ -88,7 +67,7 @@ namespace STranslate.Helper
{
switch (msg)
{
case 0x0312: //这个是window消息定义的 注册的热键消息
case WmHotkeys:
int id = wParam.ToInt32();
if (keymap.TryGetValue(id, out var callback))
{
@ -107,31 +86,31 @@ namespace STranslate.Helper
{
HotkeysHelper.mainFormHandle = mainFormHandle;
InputTranslateModifiers = Hotkeys.InputTranslate.Modifiers;
InputTranslateKey = Hotkeys.InputTranslate.Key;
CrosswordTranslateModifiers = Hotkeys.CrosswordTranslate.Modifiers;
CrosswordTranslateKey = Hotkeys.CrosswordTranslate.Key;
InputTranslateModifiers = ViewModel.MainVM.Instance.NHotkeys.InputTranslate.Modifiers;
InputTranslateKey = ViewModel.MainVM.Instance.NHotkeys.InputTranslate.Key;
CrosswordTranslateModifiers = ViewModel.MainVM.Instance.NHotkeys.CrosswordTranslate.Modifiers;
CrosswordTranslateKey = ViewModel.MainVM.Instance.NHotkeys.CrosswordTranslate.Key;
#if true
ScreenShotTranslateModifiers = Hotkeys.ScreenShotTranslate.Modifiers;
ScreenShotTranslateKey = Hotkeys.ScreenShotTranslate.Key;
if (Hotkeys.ScreenShotTranslate.Key != 0)
ScreenShotTranslateModifiers = ViewModel.MainVM.Instance.NHotkeys.ScreenShotTranslate.Modifiers;
ScreenShotTranslateKey = ViewModel.MainVM.Instance.NHotkeys.ScreenShotTranslate.Key;
if (ViewModel.MainVM.Instance.NHotkeys.ScreenShotTranslate.Key != 0)
{
Hotkeys.ScreenShotTranslate.Conflict = !NativeMethodHelper.RegisterHotKey(mainFormHandle, ScreenShotTranslateId, Hotkeys.ScreenShotTranslate.Modifiers, Hotkeys.ScreenShotTranslate.Key);
ViewModel.MainVM.Instance.NHotkeys.ScreenShotTranslate.Conflict = !NativeMethodHelper.RegisterHotKey(mainFormHandle, ScreenShotTranslateId, ViewModel.MainVM.Instance.NHotkeys.ScreenShotTranslate.Modifiers, ViewModel.MainVM.Instance.NHotkeys.ScreenShotTranslate.Key);
}
#endif
if (Hotkeys.InputTranslate.Key != 0)
if (ViewModel.MainVM.Instance.NHotkeys.InputTranslate.Key != 0)
{
Hotkeys.InputTranslate.Conflict = !NativeMethodHelper.RegisterHotKey(mainFormHandle, InputTranslateId, Hotkeys.InputTranslate.Modifiers, Hotkeys.InputTranslate.Key);
ViewModel.MainVM.Instance.NHotkeys.InputTranslate.Conflict = !NativeMethodHelper.RegisterHotKey(mainFormHandle, InputTranslateId, ViewModel.MainVM.Instance.NHotkeys.InputTranslate.Modifiers, ViewModel.MainVM.Instance.NHotkeys.InputTranslate.Key);
}
if (Hotkeys.CrosswordTranslate.Key != 0)
if (ViewModel.MainVM.Instance.NHotkeys.CrosswordTranslate.Key != 0)
{
Hotkeys.CrosswordTranslate.Conflict = !NativeMethodHelper.RegisterHotKey(mainFormHandle, CrosswordTranslateId, Hotkeys.CrosswordTranslate.Modifiers, Hotkeys.CrosswordTranslate.Key);
ViewModel.MainVM.Instance.NHotkeys.CrosswordTranslate.Conflict = !NativeMethodHelper.RegisterHotKey(mainFormHandle, CrosswordTranslateId, ViewModel.MainVM.Instance.NHotkeys.CrosswordTranslate.Modifiers, ViewModel.MainVM.Instance.NHotkeys.CrosswordTranslate.Key);
}
if (Hotkeys.OpenMainWindow.Key != 0)
if (ViewModel.MainVM.Instance.NHotkeys.OpenMainWindow.Key != 0)
{
Hotkeys.OpenMainWindow.Conflict = !NativeMethodHelper.RegisterHotKey(mainFormHandle, OpenMainWindowId, Hotkeys.OpenMainWindow.Modifiers, Hotkeys.OpenMainWindow.Key);
ViewModel.MainVM.Instance.NHotkeys.OpenMainWindow.Conflict = !NativeMethodHelper.RegisterHotKey(mainFormHandle, OpenMainWindowId, ViewModel.MainVM.Instance.NHotkeys.OpenMainWindow.Modifiers, ViewModel.MainVM.Instance.NHotkeys.OpenMainWindow.Key);
}
}
@ -153,59 +132,59 @@ namespace STranslate.Helper
/// </summary>
public static void ReRegisterHotKey()
{
if (Hotkeys.InputTranslate.Key == 0)
if (ViewModel.MainVM.Instance.NHotkeys.InputTranslate.Key == 0)
{
UnregisterHotKey(mainFormHandle, InputTranslateId);
}
else if (InputTranslateModifiers != Hotkeys.InputTranslate.Modifiers || InputTranslateKey != Hotkeys.InputTranslate.Key)
else if (InputTranslateModifiers != ViewModel.MainVM.Instance.NHotkeys.InputTranslate.Modifiers || InputTranslateKey != ViewModel.MainVM.Instance.NHotkeys.InputTranslate.Key)
{
{
UnregisterHotKey(mainFormHandle, InputTranslateId);
Hotkeys.InputTranslate.Conflict = !NativeMethodHelper.RegisterHotKey(mainFormHandle, InputTranslateId, Hotkeys.InputTranslate.Modifiers, Hotkeys.InputTranslate.Key);
ViewModel.MainVM.Instance.NHotkeys.InputTranslate.Conflict = !NativeMethodHelper.RegisterHotKey(mainFormHandle, InputTranslateId, ViewModel.MainVM.Instance.NHotkeys.InputTranslate.Modifiers, ViewModel.MainVM.Instance.NHotkeys.InputTranslate.Key);
}
}
InputTranslateModifiers = Hotkeys.InputTranslate.Modifiers;
InputTranslateKey = Hotkeys.InputTranslate.Key;
InputTranslateModifiers = ViewModel.MainVM.Instance.NHotkeys.InputTranslate.Modifiers;
InputTranslateKey = ViewModel.MainVM.Instance.NHotkeys.InputTranslate.Key;
if (Hotkeys.CrosswordTranslate.Key == 0)
if (ViewModel.MainVM.Instance.NHotkeys.CrosswordTranslate.Key == 0)
{
UnregisterHotKey(mainFormHandle, CrosswordTranslateId);
}
else if (CrosswordTranslateModifiers != Hotkeys.CrosswordTranslate.Modifiers || CrosswordTranslateKey != Hotkeys.CrosswordTranslate.Key)
else if (CrosswordTranslateModifiers != ViewModel.MainVM.Instance.NHotkeys.CrosswordTranslate.Modifiers || CrosswordTranslateKey != ViewModel.MainVM.Instance.NHotkeys.CrosswordTranslate.Key)
{
{
UnregisterHotKey(mainFormHandle, CrosswordTranslateId);
Hotkeys.CrosswordTranslate.Conflict = !NativeMethodHelper.RegisterHotKey(mainFormHandle, CrosswordTranslateId, Hotkeys.CrosswordTranslate.Modifiers, Hotkeys.CrosswordTranslate.Key);
ViewModel.MainVM.Instance.NHotkeys.CrosswordTranslate.Conflict = !NativeMethodHelper.RegisterHotKey(mainFormHandle, CrosswordTranslateId, ViewModel.MainVM.Instance.NHotkeys.CrosswordTranslate.Modifiers, ViewModel.MainVM.Instance.NHotkeys.CrosswordTranslate.Key);
}
}
CrosswordTranslateModifiers = Hotkeys.CrosswordTranslate.Modifiers;
CrosswordTranslateKey = Hotkeys.CrosswordTranslate.Key;
CrosswordTranslateModifiers = ViewModel.MainVM.Instance.NHotkeys.CrosswordTranslate.Modifiers;
CrosswordTranslateKey = ViewModel.MainVM.Instance.NHotkeys.CrosswordTranslate.Key;
#if true
if (Hotkeys.ScreenShotTranslate.Key == 0)
if (ViewModel.MainVM.Instance.NHotkeys.ScreenShotTranslate.Key == 0)
{
UnregisterHotKey(mainFormHandle, ScreenShotTranslateId);
}
else if (ScreenShotTranslateModifiers != Hotkeys.ScreenShotTranslate.Modifiers || ScreenShotTranslateKey != Hotkeys.ScreenShotTranslate.Key)
else if (ScreenShotTranslateModifiers != ViewModel.MainVM.Instance.NHotkeys.ScreenShotTranslate.Modifiers || ScreenShotTranslateKey != ViewModel.MainVM.Instance.NHotkeys.ScreenShotTranslate.Key)
{
UnregisterHotKey(mainFormHandle, ScreenShotTranslateId);
Hotkeys.ScreenShotTranslate.Conflict = !NativeMethodHelper.RegisterHotKey(mainFormHandle, ScreenShotTranslateId, Hotkeys.ScreenShotTranslate.Modifiers, Hotkeys.ScreenShotTranslate.Key);
ViewModel.MainVM.Instance.NHotkeys.ScreenShotTranslate.Conflict = !NativeMethodHelper.RegisterHotKey(mainFormHandle, ScreenShotTranslateId, ViewModel.MainVM.Instance.NHotkeys.ScreenShotTranslate.Modifiers, ViewModel.MainVM.Instance.NHotkeys.ScreenShotTranslate.Key);
}
ScreenShotTranslateModifiers = Hotkeys.ScreenShotTranslate.Modifiers;
ScreenShotTranslateKey = Hotkeys.ScreenShotTranslate.Key;
ScreenShotTranslateModifiers = ViewModel.MainVM.Instance.NHotkeys.ScreenShotTranslate.Modifiers;
ScreenShotTranslateKey = ViewModel.MainVM.Instance.NHotkeys.ScreenShotTranslate.Key;
#endif
if (Hotkeys.OpenMainWindow.Key == 0)
if (ViewModel.MainVM.Instance.NHotkeys.OpenMainWindow.Key == 0)
{
UnregisterHotKey(mainFormHandle, OpenMainWindowId);
}
else if (OpenMainWindowModifiers != Hotkeys.OpenMainWindow.Modifiers || OpenMainWindowKey != Hotkeys.OpenMainWindow.Key)
else if (OpenMainWindowModifiers != ViewModel.MainVM.Instance.NHotkeys.OpenMainWindow.Modifiers || OpenMainWindowKey != ViewModel.MainVM.Instance.NHotkeys.OpenMainWindow.Key)
{
UnregisterHotKey(mainFormHandle, OpenMainWindowId);
Hotkeys.OpenMainWindow.Conflict = !NativeMethodHelper.RegisterHotKey(mainFormHandle, OpenMainWindowId, Hotkeys.OpenMainWindow.Modifiers, Hotkeys.OpenMainWindow.Key);
ViewModel.MainVM.Instance.NHotkeys.OpenMainWindow.Conflict = !NativeMethodHelper.RegisterHotKey(mainFormHandle, OpenMainWindowId, ViewModel.MainVM.Instance.NHotkeys.OpenMainWindow.Modifiers, ViewModel.MainVM.Instance.NHotkeys.OpenMainWindow.Key);
}
OpenMainWindowModifiers = Hotkeys.OpenMainWindow.Modifiers;
OpenMainWindowKey = Hotkeys.OpenMainWindow.Key;
OpenMainWindowModifiers = ViewModel.MainVM.Instance.NHotkeys.OpenMainWindow.Modifiers;
OpenMainWindowKey = ViewModel.MainVM.Instance.NHotkeys.OpenMainWindow.Key;
}
}
}

@ -5,6 +5,18 @@ using System.Runtime.CompilerServices;
namespace STranslate.Helper
{
/// <summary>
/// Generate Singleton
/// </summary>
/// <typeparam name="T"></typeparam>
public class Singleton<T> where T : class
{
private static readonly Lazy<T> _instance = new Lazy<T>(()
=> Activator.CreateInstance(typeof(T), true) as T, true);
public static T Instance => _instance.Value;
}
/// <summary>
/// 通知
/// </summary>

@ -6,7 +6,7 @@ using IWshRuntimeLibrary;
namespace STranslate.Helper
{
public class StartupHelper
public class ShortcutHelper
{
#region public method
@ -32,6 +32,13 @@ namespace STranslate.Helper
{
ShortCutDelete(appPath, StartUpPath);
}
/// <summary>
/// 设置桌面快捷方式
/// </summary>
public static void SetDesktopShortcut()
{
ShortCutCreate(true);
}
#endregion
#region params
@ -40,6 +47,11 @@ namespace STranslate.Helper
/// </summary>
private static readonly string StartUpPath = Environment.GetFolderPath(Environment.SpecialFolder.Startup);
/// <summary>
/// 用户桌面目录
/// </summary>
private static readonly string DesktopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
/// <summary>
/// 当前程序二进制文件路径
/// </summary>
@ -49,6 +61,8 @@ namespace STranslate.Helper
/// 组合的开机启动目录中的快捷方式路径
/// </summary>
private static readonly string appShortcutPath = Path.Combine(StartUpPath, Path.GetFileNameWithoutExtension(appPath) + ".lnk");
private static readonly string desktopShortcutPath = Path.Combine(DesktopPath, Path.GetFileNameWithoutExtension(appPath) + ".lnk");
#endregion
#region native method
@ -136,18 +150,25 @@ namespace STranslate.Helper
return Result;
}
/// <summary>
/// 为本程序创建一个开机启动快捷方式
/// 为本程序创建一个快捷方式
/// </summary>
private static bool ShortCutCreate()
/// <param name="isDesktop">是否为桌面快捷方式</param>
/// <returns></returns>
private static bool ShortCutCreate(bool isDesktop = false)
{
bool Result = false;
try
{
ShortCutDelete(appPath, StartUpPath);
if (!isDesktop)
ShortCutDelete(appPath, StartUpPath);
var shellType = Type.GetTypeFromProgID("WScript.Shell");
dynamic shell = Activator.CreateInstance(shellType);
var shortcut = shell.CreateShortcut(appShortcutPath);
IWshShortcut shortcut;
if (!isDesktop)
shortcut = shell.CreateShortcut(appShortcutPath);
else
shortcut = shell.CreateShortcut(desktopShortcutPath);
shortcut.TargetPath = Assembly.GetEntryAssembly().Location;
shortcut.Arguments = string.Empty;
shortcut.WorkingDirectory = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;

@ -0,0 +1,98 @@
using SQLite;
using STranslate.Model;
using STranslate.ViewModel;
using System;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
namespace STranslate.Helper
{
//https://github.com/praeclarum/sqlite-net
public class SqliteHelper : IDisposable
{
public SqliteHelper()
{
_sqlDB = new SQLiteConnection(_dbName);
_sqlDB.CreateTable<SqliteModel>();
}
public void Insert(DateTime time, string source, string target, LanguageEnum sourceLang, LanguageEnum targetLang, string api)
{
try
{
var model = new SqliteModel
{
Time = time,
SourceText = source,
TargetText = target,
SourceLang = sourceLang.ToString(),
TargetLang = targetLang.ToString(),
Api = api,
};
//查询最大数量
var count = _sqlDB.Table<SqliteModel>().Count();
if (count >= SettingsVM.Instance.MaxHistoryCount)
{
_sqlDB.Execute("delete from histories where id in (select id from histories limit (?))"
, count + 1 - SettingsVM.Instance.MaxHistoryCount);
}
//手动切换目标语言强制插入替换
_sqlDB.Table<SqliteModel>()
.Where(x => x.SourceText.Equals(model.SourceText))
.ToList().ForEach(x =>
{
_sqlDB.Delete(x);
});
_sqlDB.Insert(model);
}
catch (Exception ex)
{
System.Windows.MessageBox.Show($"本地记录插入错误\n{ex.Message}");
}
}
/// <summary>
/// 查询记录
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
public string Query(string str)
{
var query = _sqlDB.Table<SqliteModel>().Where(x => x.SourceText.Equals(str));
if (query.Count() <= 0)
{
return string.Empty;
}
else//如果超过一个删除多余的
{
var tmp = query.ToList();
for (int i = 1; i < tmp.Count; i++)
{
_sqlDB.Delete(tmp[i]);
}
return query.First().TargetText;
}
}
public void Dispose()
{
_sqlDB.Close();
}
private readonly SQLiteConnection _sqlDB;
/// <summary>
/// 数据文件
/// </summary>
private static string _dbName => $"{_ApplicationData}\\{_AppName.ToLower()}.db";
/// <summary>
/// C:\Users\user\AppData\Local\STranslate
/// </summary>
private static string _ApplicationData => $"{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}\\{_AppName}";
private static readonly string _AppName = Path.GetFileNameWithoutExtension(Assembly.GetEntryAssembly().Location);
}
}

Binary file not shown.

@ -7,8 +7,102 @@ using System.Threading.Tasks;
namespace STranslate.Model
{
public class Hotkeys
{
[JsonProperty("inputTranslate")]
public InputTranslate InputTranslate { get; set; }
[JsonProperty("crosswordTranslate")]
public CrosswordTranslate CrosswordTranslate { get; set; }
[JsonProperty("screenShotTranslate")]
public ScreenShotTranslate ScreenShotTranslate { get; set; }
[JsonProperty("openMainWindow")]
public OpenMainWindow OpenMainWindow { get; set; }
}
public class InputTranslate
{
public byte Modifiers { get; set; }
public int Key { get; set; }
public String Text { get; set; }
public bool Conflict { get; set; }
}
public class CrosswordTranslate
{
public byte Modifiers { get; set; }
public int Key { get; set; }
public String Text { get; set; }
public bool Conflict { get; set; }
}
public class ScreenShotTranslate
{
public byte Modifiers { get; set; }
public int Key { get; set; }
public String Text { get; set; }
public bool Conflict { get; set; }
}
public class OpenMainWindow
{
public byte Modifiers { get; set; }
public int Key { get; set; }
public String Text { get; set; }
public bool Conflict { get; set; }
}
public class Server
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("api")]
public string Api { get; set; }
}
public class ConfigModel
{
/// <summary>
/// 最大历史记录数量
/// </summary>
[JsonProperty("maxHistoryCount")]
public int MaxHistoryCount { get; set; }
/// <summary>
/// 自动识别语种标度
/// </summary>
[JsonProperty("autoScale")]
public double AutoScale { get; set; }
/// <summary>
/// 取词间隔
/// </summary>
[JsonProperty("wordPickupInterval")]
public double WordPickupInterval { get; set; }
/// <summary>
/// 是否亮色模式
/// </summary>
[JsonProperty("isBright")]
public bool IsBright { get; set; }
[JsonProperty("sourceLanguage")]
public string SourceLanguage { get; set; }
[JsonProperty("targetLanguage")]
public string TargetLanguage { get; set; }
[JsonProperty("selectServer")]
public int SelectServer { get; set; }
/// <summary>
/// 服务
/// </summary>
[JsonProperty("servers")]
public Server[] Servers { get; set; }
/// <summary>
/// 热键
/// </summary>
[JsonProperty("hotkeys")]
public Hotkeys Hotkeys { get; set; }
public ConfigModel()
{
}
@ -17,6 +111,8 @@ namespace STranslate.Model
{
return new ConfigModel
{
MaxHistoryCount = 100,
AutoScale = 0.8,
WordPickupInterval = 200,
IsBright = true,
SourceLanguage = LanguageEnum.AUTO.GetDescription(),
@ -27,7 +123,7 @@ namespace STranslate.Model
new Server
{
Name = "zggsong",
Api = "https://zggsong.cn/tt"
Api = "https://dfree.deno.dev/translate"
},
new Server
{
@ -39,44 +135,39 @@ namespace STranslate.Model
Name = "local",
Api = "http://127.0.0.1:8000/translate"
}
},
Hotkeys = new Hotkeys
{
InputTranslate = new InputTranslate
{
Modifiers = 1,
Key = 65,
Text = "Alt + A",
Conflict = false,
},
CrosswordTranslate = new CrosswordTranslate
{
Modifiers = 1,
Key = 68,
Text = "Alt + D",
Conflict = false,
},
ScreenShotTranslate = new ScreenShotTranslate
{
Modifiers = 1,
Key = 83,
Text = "Alt + S",
Conflict = false,
},
OpenMainWindow = new OpenMainWindow
{
Modifiers = 1,
Key = 71,
Text = "Alt + G",
Conflict = false,
},
}
};
}
/// <summary>
/// 是否亮色模式
/// </summary>
[JsonProperty("wordPickupInterval")]
public double WordPickupInterval { get; set; }
/// <summary>
/// 是否亮色模式
/// </summary>
[JsonProperty("isBright")]
public bool IsBright { get; set; }
[JsonProperty("sourceLanguage")]
public string SourceLanguage { get; set; }
[JsonProperty("targetLanguage")]
public string TargetLanguage { get; set; }
[JsonProperty("selectServer")]
public int SelectServer { get; set; }
/// <summary>
/// 服务
/// </summary>
[JsonProperty("servers")]
public Server[] Servers { get; set; }
}
public class Server
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("api")]
public string Api { get; set; }
}
}

@ -0,0 +1,38 @@
using SQLite;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace STranslate.Model
{
[Table("Histories")]
public class SqliteModel
{
[PrimaryKey, AutoIncrement]
[Column("id")]
public int Id { get; set; }
[Column("time")]
public DateTime Time { get; set; }
[Column("source_lang")]
public string SourceLang { get; set; }
[Column("target_lang")]
public string TargetLang { get; set; }
[Column("source_text")]
public string SourceText { get; set; }
[Column("target_text")]
public string TargetText { get; set; }
[Column("api")]
public string Api { get; set; }
[Column("remark")]
public string Remark { get; set; }
}
}

@ -0,0 +1,20 @@
using System;
using System.Windows.Data;
namespace STranslate.Model
{
public class WidthConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
double w = System.Convert.ToDouble(value);
return w + 30;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

@ -47,6 +47,6 @@ using System.Windows;
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
//通过使用 "*",如下所示:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.1.9.0")]
[assembly: AssemblyFileVersion("0.1.9.0")]
[assembly: AssemblyVersion("0.2.6.0")]
[assembly: AssemblyFileVersion("0.2.6.0")]
[assembly: Guid("CE252DD8-179F-4544-9989-453F5DEA378D")]

@ -19,7 +19,7 @@ namespace STranslate.Properties {
// 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
// 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
// (以 /str 作为命令选项),或重新生成 VS 项目。
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {

@ -59,9 +59,37 @@
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.13.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="SQLite-net, Version=1.8.116.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\sqlite-net-pcl.1.8.116\lib\netstandard2.0\SQLite-net.dll</HintPath>
</Reference>
<Reference Include="SQLitePCLRaw.batteries_v2, Version=2.0.4.976, Culture=neutral, PublicKeyToken=8226ea5df37bcae9, processorArchitecture=MSIL">
<HintPath>..\packages\SQLitePCLRaw.bundle_green.2.0.4\lib\net461\SQLitePCLRaw.batteries_v2.dll</HintPath>
</Reference>
<Reference Include="SQLitePCLRaw.core, Version=2.0.4.976, Culture=neutral, PublicKeyToken=1488e028ca7ab535, processorArchitecture=MSIL">
<HintPath>..\packages\SQLitePCLRaw.core.2.0.4\lib\netstandard2.0\SQLitePCLRaw.core.dll</HintPath>
</Reference>
<Reference Include="SQLitePCLRaw.nativelibrary, Version=2.0.4.976, Culture=neutral, PublicKeyToken=502ed628492ab262, processorArchitecture=MSIL">
<HintPath>..\packages\SQLitePCLRaw.bundle_green.2.0.4\lib\net461\SQLitePCLRaw.nativelibrary.dll</HintPath>
</Reference>
<Reference Include="SQLitePCLRaw.provider.dynamic_cdecl, Version=2.0.4.976, Culture=neutral, PublicKeyToken=b68184102cba0b3b, processorArchitecture=MSIL">
<HintPath>..\packages\SQLitePCLRaw.provider.dynamic_cdecl.2.0.4\lib\netstandard2.0\SQLitePCLRaw.provider.dynamic_cdecl.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Buffers, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Buffers.4.4.0\lib\netstandard2.0\System.Buffers.dll</HintPath>
</Reference>
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.Memory, Version=4.0.1.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Memory.4.5.3\lib\netstandard2.0\System.Memory.dll</HintPath>
</Reference>
<Reference Include="System.Numerics" />
<Reference Include="System.Numerics.Vectors, Version=4.1.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Numerics.Vectors.4.4.0\lib\net46\System.Numerics.Vectors.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=4.0.4.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.4.5.2\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
</Reference>
<Reference Include="System.Speech" />
<Reference Include="System.Web" />
<Reference Include="System.Windows.Forms" />
@ -95,9 +123,12 @@
<Compile Include="Helper\MvvmHelper.cs" />
<Compile Include="Helper\NativeMethodHelper.cs" />
<Compile Include="Helper\Processhelper.cs" />
<Compile Include="Helper\StartupHelper.cs" />
<Compile Include="Helper\SqliteHelper.cs" />
<Compile Include="Helper\ShortcutHelper.cs" />
<Compile Include="Model\ConfigModel.cs" />
<Compile Include="Model\SqliteModel.cs" />
<Compile Include="Model\VisibilityConverter.cs" />
<Compile Include="Model\WidthConverter.cs" />
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
@ -182,12 +213,15 @@
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<None Include="tessdata\eng.traineddata">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<Resource Include="Images\iconfont.ttf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Resource>
<Content Include="ClearCache.bat">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<None Include="tessdata\eng.traineddata">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="packages.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
@ -230,5 +264,7 @@
<ErrorText>这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\Tesseract.5.2.0\build\Tesseract.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Tesseract.5.2.0\build\Tesseract.targets'))" />
<Error Condition="!Exists('..\packages\SQLitePCLRaw.lib.e_sqlite3.2.0.4\build\net461\SQLitePCLRaw.lib.e_sqlite3.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\SQLitePCLRaw.lib.e_sqlite3.2.0.4\build\net461\SQLitePCLRaw.lib.e_sqlite3.targets'))" />
</Target>
<Import Project="..\packages\SQLitePCLRaw.lib.e_sqlite3.2.0.4\build\net461\SQLitePCLRaw.lib.e_sqlite3.targets" Condition="Exists('..\packages\SQLitePCLRaw.lib.e_sqlite3.2.0.4\build\net461\SQLitePCLRaw.lib.e_sqlite3.targets')" />
</Project>

@ -191,4 +191,17 @@
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<!--ToolTip-->
<ControlTemplate x:Key="ToolTipTemplate"
TargetType="ToolTip">
<Border CornerRadius="3"
BorderThickness="1"
BorderBrush="#393c43"
Background="#2e323a"
Padding="4">
<TextBlock Text="{TemplateBinding Name}"
Foreground="#abb2bf"/>
</Border>
</ControlTemplate>
</ResourceDictionary>

@ -191,4 +191,16 @@
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<!--ToolTip-->
<ControlTemplate x:Key="ToolTipTemplate"
TargetType="ToolTip">
<Border CornerRadius="3"
BorderThickness="1"
BorderBrush="#dfdfdf"
Background="#f6f6f6"
Padding="4">
<TextBlock Text="{TemplateBinding Name}"/>
</Border>
</ControlTemplate>
</ResourceDictionary>

@ -1,10 +1,12 @@
using Newtonsoft.Json;
using IWshRuntimeLibrary;
using Newtonsoft.Json;
using STranslate.Model;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
@ -295,5 +297,30 @@ namespace STranslate.Util
}
}
#endregion
#region Shortcut
public static void CreateShortcut()
{
string deskTop = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Desktop);
string dirPath = System.Environment.CurrentDirectory;
string exePath = Assembly.GetExecutingAssembly().Location;
System.Diagnostics.FileVersionInfo exeInfo = System.Diagnostics.FileVersionInfo.GetVersionInfo(exePath);
if (System.IO.File.Exists(string.Format(@"{0}\STranslate.lnk", deskTop)))
{
System.IO.File.Delete(string.Format(@"{0}\STranslate.lnk",deskTop));//删除原来的桌面快捷键方式
return;
}
WshShell shell = new WshShell();
IWshShortcut shortcut = (IWshShortcut)shell.CreateShortcut(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + "\\" + "STranslate.lnk");
shortcut.TargetPath = @exePath; //目标文件
shortcut.WorkingDirectory = dirPath; //目标文件夹
shortcut.WindowStyle = 1; //目标应用程序的窗口状态分为普通、最大化、最小化【1,3,7】
shortcut.Description = "自动更新程序"; //描述
shortcut.IconLocation = string.Format(@"{0}\64.ico", dirPath); //快捷方式图标
shortcut.Arguments = "";
shortcut.Hotkey = "SHIFT+DELETE"; // 快捷键
shortcut.Save();
}
#endregion
}
}

@ -3,6 +3,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:model="clr-namespace:STranslate.Model"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
mc:Ignorable="d"
x:Name="Mwin"
@ -15,7 +16,11 @@
WindowStyle="None"
SizeToContent="Height"
Width="400"
FontFamily="{DynamicResource {x:Static SystemFonts.CaptionFontFamilyKey}}"
Icon="/Images/translate.ico">
<Window.Resources>
<model:WidthConverter x:Key="WidthConverter"/>
</Window.Resources>
<Window.InputBindings>
<KeyBinding Modifiers="Ctrl+Shift"
@ -101,8 +106,13 @@
Visibility="{Binding InputTxt, Converter={StaticResource String2VisibilityConverter}}"
Command="{Binding SourceSpeakCmd}"/>
<Button Template="{DynamicResource ButtonTemplate}"
Click="Copy_Click"
Visibility="{Binding InputTxt, Converter={StaticResource String2VisibilityConverter}}"
Command="{Binding CopyInputCmd}"/>
Command="{Binding CopyInputCmd}">
<Button.ToolTip>
<ToolTip x:Name="复制输入内容" Template="{DynamicResource ToolTipTemplate}"/>
</Button.ToolTip>
</Button>
<Border Style="{DynamicResource LanguageMarkBorderStyle}"
Visibility="{Binding IdentifyLanguage, Converter={StaticResource String2VisibilityConverter}}">
<StackPanel Margin="5,2"
@ -118,6 +128,34 @@
</Border>
</Grid>
<!--toast-->
<Border x:Name="Toast"
CornerRadius="12"
Grid.Row="0"
Grid.RowSpan="2"
VerticalAlignment="Top"
Visibility="Visible"
Margin="0,-40"
Width="{Binding ElementName=toastTxt, Path=ActualWidth,Converter={StaticResource WidthConverter}}"
BorderBrush="Transparent"
Background="#65c248">
<WrapPanel Orientation="Horizontal"
HorizontalAlignment="Center">
<TextBlock Text="&#xe632;"
FontSize="16"
Foreground="White"
Padding="5,10"
Style="{StaticResource IconStyle}"/>
<TextBlock x:Name="toastTxt"
Background="Transparent"
Foreground="#fff"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Padding="0,5,10,5"
FontSize="16"/>
</WrapPanel>
</Border>
<!--mid-->
<StackPanel x:Name="MidArea"
Grid.Row="2"
@ -165,27 +203,48 @@
<StackPanel Orientation="Horizontal"
Margin="10,5"
VerticalAlignment="Bottom">
<!--语音-->
<Button Template="{DynamicResource ButtonTemplateSpeak}"
Visibility="{Binding OutputTxt, Converter={StaticResource String2VisibilityConverter}}"
Command="{Binding TargetSpeakCmd}"/>
Visibility="{Binding OutputTxt, Converter={StaticResource String2VisibilityConverter}}"
Command="{Binding TargetSpeakCmd}"/>
<!--普通复制-->
<Button Template="{DynamicResource ButtonTemplate}"
Visibility="{Binding OutputTxt, Converter={StaticResource String2VisibilityConverter}}"
Command="{Binding CopyResultCmd}"/>
Click="Copy_Click"
Visibility="{Binding OutputTxt, Converter={StaticResource String2VisibilityConverter}}"
Command="{Binding CopyResultCmd}">
<Button.ToolTip>
<ToolTip x:Name="直接复制结果" Template="{DynamicResource ToolTipTemplate}"/>
</Button.ToolTip>
</Button>
<!--蛇形复制-->
<Button Margin="5,0"
Template="{DynamicResource ButtonTemplateSnakeCopy}"
Visibility="{Binding SnakeRet, Converter={StaticResource String2VisibilityConverter}}"
Command="{Binding CopySnakeResultCmd}"/>
Click="Copy_Click"
Template="{DynamicResource ButtonTemplateSnakeCopy}"
Visibility="{Binding SnakeRet, Converter={StaticResource String2VisibilityConverter}}"
Command="{Binding CopySnakeResultCmd}">
<Button.ToolTip>
<ToolTip x:Name="复制为蛇形字符串" Template="{DynamicResource ToolTipTemplate}"/>
</Button.ToolTip>
</Button>
<!--小驼峰复制-->
<Button Template="{DynamicResource ButtonTemplateSmallHumpCopy}"
Visibility="{Binding SmallHumpRet, Converter={StaticResource String2VisibilityConverter}}"
Command="{Binding CopySmallHumpResultCmd}"/>
Click="Copy_Click"
Visibility="{Binding SmallHumpRet, Converter={StaticResource String2VisibilityConverter}}"
Command="{Binding CopySmallHumpResultCmd}">
<Button.ToolTip>
<ToolTip x:Name="复制为小驼峰字符串" Template="{DynamicResource ToolTipTemplate}"/>
</Button.ToolTip>
</Button>
<!--大驼峰复制-->
<Button Margin="5,0"
Template="{DynamicResource ButtonTemplateLargeHumpCopy}"
Visibility="{Binding LargeHumpRet, Converter={StaticResource String2VisibilityConverter}}"
Command="{Binding CopyLargeHumpResultCmd}"/>
Click="Copy_Click"
Template="{DynamicResource ButtonTemplateLargeHumpCopy}"
Visibility="{Binding LargeHumpRet, Converter={StaticResource String2VisibilityConverter}}"
Command="{Binding CopyLargeHumpResultCmd}">
<Button.ToolTip>
<ToolTip x:Name="复制为大驼峰字符串" Template="{DynamicResource ToolTipTemplate}"/>
</Button.ToolTip>
</Button>
</StackPanel>
</Grid>
</Border>

@ -4,6 +4,8 @@ using System;
using System.IO;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Media.Animation;
using System.Windows.Media;
using Application = System.Windows.Application;
using MessageBox = System.Windows.MessageBox;
@ -21,10 +23,12 @@ namespace STranslate.View
InitialTray();
//if (HotKeys.InputTranslate.Conflict || HotKeys.CrosswordTranslate.Conflict || HotKeys.ScreenShotTranslate.Conflict)
//{
// MessageBox.Show("全局快捷键有冲突...");
//}
Microsoft.Win32.SystemEvents.DisplaySettingsChanged += SystemEvents_DisplaySettingsChanged;
}
private void SystemEvents_DisplaySettingsChanged(object sender, EventArgs e)
{
InitIcon();
}
/// <summary>
@ -57,6 +61,34 @@ namespace STranslate.View
{
vm.OpenMainWin();
});
if (ViewModel.MainVM.Instance.NHotkeys.InputTranslate.Conflict
|| ViewModel.MainVM.Instance.NHotkeys.CrosswordTranslate.Conflict
|| ViewModel.MainVM.Instance.NHotkeys.ScreenShotTranslate.Conflict
|| ViewModel.MainVM.Instance.NHotkeys.OpenMainWindow.Conflict)
{
MessageBox.Show("全局快捷键有冲突,请前往软件首选项中修改...");
}
}
private void Copy_Click(object sender, RoutedEventArgs e)
{
var o = sender as System.Windows.Controls.Button;
toastTxt.Text = (o.ToolTip as System.Windows.Controls.ToolTip).Name;
//创建一个一个对象,对两个值在时间线上进行动画处理(移动距离,移动到的位置)
var da = new DoubleAnimation();
//设定动画时间线
da.Duration = new Duration(TimeSpan.FromSeconds(0.8));
//设定移动动画的结束值控件向下移动60个像素向上移动则是-60
da.To = 50;
da.From = 0;
da.AccelerationRatio = 0.2;
da.DecelerationRatio = 0.8;
da.AutoReverse = true;
//btnFlash要进行动画操作的控件名
Toast.RenderTransform = new TranslateTransform();
//开始进行动画处理
Toast.RenderTransform.BeginAnimation(TranslateTransform.YProperty, da);
}
private MainVM vm = MainVM.Instance;
@ -64,31 +96,41 @@ namespace STranslate.View
public readonly NotifyIcon NotifyIcon = new NotifyIcon();
#region Initial TrayIcon
private void InitialTray()
private void InitIcon()
{
var app = Path.GetFileNameWithoutExtension(System.Reflection.Assembly.GetEntryAssembly()?.Location);
NotifyIcon.Text = $@"{app} {SettingsVM.Instance.Version}";
var stream = Application
.GetResourceStream(new Uri("Images/translate.ico", UriKind.Relative))?.Stream;
if (NotifyIcon.Icon != null)
{
NotifyIcon.Icon.Dispose();
}
if (stream != null)
{
NotifyIcon.Icon = new System.Drawing.Icon(stream);
}
}
private void InitialTray()
{
var app = Path.GetFileNameWithoutExtension(System.Reflection.Assembly.GetEntryAssembly()?.Location);
NotifyIcon.Text = $@"{app} {SettingsVM.Instance.Version}";
InitIcon();
NotifyIcon.Visible = true;
NotifyIcon.BalloonTipText = $@"{app} already started...";
NotifyIcon.ShowBalloonTip(500);
NotifyIcon.MouseDoubleClick += InputTranslateMenuItem_Click;
var inputTranslateMenuItemBtn = new MenuItem("输入翻译\tAlt+A");
var inputTranslateMenuItemBtn = new MenuItem("输入翻译");
inputTranslateMenuItemBtn.Click += InputTranslateMenuItem_Click;
var screenshotTranslateMenuItemBtn = new MenuItem("截图翻译\tAlt+S");
var screenshotTranslateMenuItemBtn = new MenuItem("截图翻译");
screenshotTranslateMenuItemBtn.Click += ScreenshotTranslateMenuItem_Click;
var crossWordTranslateMenuItemBtn = new MenuItem("划词翻译\tAlt+D");
var crossWordTranslateMenuItemBtn = new MenuItem("划词翻译");
//CrossWordTranslateMenuItemBTN.Click += CrossWordTranslateMenuItem_Click;
//当失去焦点后无法从托盘处获取选中文本
crossWordTranslateMenuItemBtn.Enabled = false;
var openMainWinBtn = new MenuItem("显示主界面\tAlt+G");
var openMainWinBtn = new MenuItem("显示主界面");
openMainWinBtn.Click += OpenMainWin_Click;
var preferenceBtn = new MenuItem("首选项");
@ -155,5 +197,6 @@ namespace STranslate.View
}
#endregion
}
}

@ -6,7 +6,8 @@
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
xmlns:local="clr-namespace:STranslate.View"
mc:Ignorable="d"
SizeToContent="Height"
SizeToContent="WidthAndHeight"
Loaded="window_Loaded"
WindowStartupLocation="CenterScreen"
Icon="/Images/translate.ico"
Title="STranslate 首选项" Height="450" Width="450">
@ -15,12 +16,12 @@
TargetType="Button">
<Border x:Name="border"
CornerRadius="5"
Padding="4"
Padding="5"
Background="#dedfde"
MaxHeight="25">
<TextBlock VerticalAlignment="Center"
HorizontalAlignment="Center"
Text="检查更新"/>
Text="{Binding Content, RelativeSource={RelativeSource TemplatedParent}}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
@ -65,6 +66,36 @@
</CheckBox>
</WrapPanel>
</GroupBox>
<GroupBox Header="语种识别(zh-en)"
ToolTip="根据英文字符占所有字符比例判断中英文">
<WrapPanel Margin="0,5,0,5">
<Slider Value="{Binding DataContext.AutoScale, ElementName=window}"
Minimum="0.01"
Maximum="0.99"
MinWidth="200"
TickFrequency="0.01"
TickPlacement="None"
IsSnapToTickEnabled="True">
</Slider>
<TextBlock Text="{Binding AutoScale, StringFormat={}{0}}" Margin="10,0,0,0" />
</WrapPanel>
</GroupBox>
<GroupBox Header="历史记录数量"
ToolTip="记录记录至本地数据库,以便省去重复查询的时间,调整最大历史记录数量">
<WrapPanel Margin="0,5,0,5">
<Slider Value="{Binding DataContext.MaxHistoryCount, ElementName=window}"
Minimum="1"
Maximum="1000"
MinWidth="200"
TickFrequency="10"
TickPlacement="None"
IsSnapToTickEnabled="True">
</Slider>
<TextBlock Text="{Binding MaxHistoryCount, StringFormat={}{0}条}" Margin="10,0,0,0" />
</WrapPanel>
</GroupBox>
<GroupBox Header="取词间隔"
ToolTip="划词翻译实现原理是用户用鼠标划词后模拟Ctrl+C间隔一定时间后程序再从剪切板取词如果电脑反应慢可能会出现取不到词的问题将间隔调大可以适配一些老旧的机器">
<WrapPanel Margin="0,5,0,5">
@ -83,134 +114,144 @@
</TabItem>
<!--
<TabItem Header="控制"
Padding="10,2">
<StackPanel Margin="20">
<GroupBox Header="快捷键">
<Grid Margin="20,10,20,10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="100*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="100*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Label Content="划词翻译"
VerticalAlignment="Center"
Grid.Row="1"
Grid.Column="0"
Margin="0,5,0,0" />
<TextBox Cursor="Arrow"
Width="200"
Grid.Row="1"
Grid.Column="1"
Margin="0,5,0,0"
CaretBrush="Transparent"
VerticalContentAlignment="Center"
InputMethod.IsInputMethodEnabled="False">
<i:Interaction.Triggers>
<i:EventTrigger EventName="">
<i:InvokeCommandAction Command="{Binding }"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBox>
<Label Grid.Row="1"
Grid.Column="2"
Margin="0,5,0,0"
Content="热键冲突"
VerticalAlignment="Center"
Visibility="Hidden"
Foreground="Red" />
<Label Content="划词翻译"
VerticalAlignment="Center"
Grid.Row="1"
Grid.Column="0"
Margin="0,5,0,0" />
<TextBox x:Name="CrossWordTextBox"
Cursor="Arrow"
Width="200"
Grid.Row="1"
Grid.Column="1"
Margin="0,5,0,0"
CaretBrush="Transparent"
VerticalContentAlignment="Center"
InputMethod.IsInputMethodEnabled="False"
PreviewKeyDown="HotKeyTextBox_PreviewKeyDown"
KeyUp="CrossWord_KeyUp"/>
<Label x:Name="CrossWordHotKeyConflictLabel"
Grid.Row="1"
Grid.Column="2"
Margin="0,5,0,0"
Content="热键冲突"
VerticalAlignment="Center"
Visibility="Hidden"
Foreground="Red" />
<Label Content="截图翻译"
VerticalAlignment="Center"
Grid.Row="2"
Grid.Column="0"
Margin="0,5,0,0" />
<TextBox Cursor="Arrow"
Width="200"
Grid.Row="2"
Grid.Column="1"
Margin="0,5,0,0"
CaretBrush="Transparent"
VerticalContentAlignment="Center"
InputMethod.IsInputMethodEnabled="False"/>
<Label Grid.Row="2"
Grid.Column="2"
Margin="0,5,0,0"
Content="热键冲突"
VerticalAlignment="Center"
Visibility="Hidden"
Foreground="Red" />
<Label Content="截图翻译"
VerticalAlignment="Center"
Grid.Row="2"
Grid.Column="0"
Margin="0,5,0,0" />
<TextBox x:Name="ScreenshotTextBox"
Cursor="Arrow"
Width="200"
Grid.Row="2"
Grid.Column="1"
Margin="0,5,0,0"
CaretBrush="Transparent"
VerticalContentAlignment="Center"
InputMethod.IsInputMethodEnabled="False"
PreviewKeyDown="HotKeyTextBox_PreviewKeyDown"
KeyUp="Screenshot_KeyUp"/>
<Label x:Name="ScreenshotHotKeyConflictLabel"
Grid.Row="2"
Grid.Column="2"
Margin="0,5,0,0"
Content="热键冲突"
VerticalAlignment="Center"
Visibility="Hidden"
Foreground="Red" />
<Label Content="输入翻译"
VerticalAlignment="Center"
Grid.Row="3"
Grid.Column="0"
Margin="0,5,0,0" />
<TextBox Cursor="Arrow"
Width="200"
Grid.Row="3"
Grid.Column="1"
Margin="0,5,0,0"
CaretBrush="Transparent"
VerticalContentAlignment="Center"
InputMethod.IsInputMethodEnabled="False"/>
<Label Grid.Row="3"
Grid.Column="2"
Margin="0,5,0,0"
Content="热键冲突"
VerticalAlignment="Center"
Visibility="Hidden"
Foreground="Red" />
<Label Content="输入翻译"
VerticalAlignment="Center"
Grid.Row="3"
Grid.Column="0"
Margin="0,5,0,0" />
<TextBox x:Name="InputTextBox"
Cursor="Arrow"
Width="200"
Grid.Row="3"
Grid.Column="1"
Margin="0,5,0,0"
CaretBrush="Transparent"
VerticalContentAlignment="Center"
InputMethod.IsInputMethodEnabled="False"
PreviewKeyDown="HotKeyTextBox_PreviewKeyDown"
KeyUp="Input_KeyUp"/>
<Label x:Name="InputHotKeyConflictLabel"
Grid.Row="3"
Grid.Column="2"
Margin="0,5,0,0"
Content="热键冲突"
VerticalAlignment="Center"
Visibility="Hidden"
Foreground="Red"/>
<Label Content="显示界面"
VerticalAlignment="Center"
Grid.Row="4"
Grid.Column="0"
Margin="0,5,0,0" />
<TextBox Cursor="Arrow"
Width="200"
Grid.Row="4"
Grid.Column="1"
Margin="0,5,0,0"
CaretBrush="Transparent"
VerticalContentAlignment="Center"
InputMethod.IsInputMethodEnabled="False"/>
<Label Grid.Row="4"
Grid.Column="2"
Margin="0,5,0,0"
Content="热键冲突"
VerticalAlignment="Center"
Visibility="Hidden"
Foreground="Red" />
<Label Content="显示界面"
VerticalAlignment="Center"
Grid.Row="4"
Grid.Column="0"
Margin="0,5,0,0" />
<TextBox x:Name="ShowMainwinTextBox"
Cursor="Arrow"
Width="200"
Grid.Row="4"
Grid.Column="1"
Margin="0,5,0,0"
CaretBrush="Transparent"
VerticalContentAlignment="Center"
InputMethod.IsInputMethodEnabled="False"
PreviewKeyDown="HotKeyTextBox_PreviewKeyDown"
KeyUp="ShowMainwin_KeyUp"/>
<Label x:Name="ShowMainwinHotKeyConflictLabel"
Grid.Row="4"
Grid.Column="2"
Margin="0,5,0,0"
Content="热键冲突"
VerticalAlignment="Center"
Visibility="Hidden"
Foreground="Red" />
<Button Content="恢复默认"
Template="{StaticResource buttonstyle}"
Width="80"
Grid.Row="5"
Margin="5"
Grid.Column="1"
Command="{Binding ResetHotKeysCmd}"/>
</Grid>
<Button Content="恢复默认"
Template="{StaticResource buttonstyle}"
Width="80"
Grid.Row="5"
Margin="5"
Grid.Column="1"
Click="ResetHoskeys_Click"/>
</Grid>
</GroupBox>
</StackPanel>
</TabItem>
-->
<TabItem Header="服务"
Visibility="Collapsed"
@ -221,7 +262,8 @@
</GroupBox>
</TabItem>
<TabItem Header="关于"
<TabItem Header="关于"
Padding="10,2">
<ScrollViewer VerticalScrollBarVisibility="Auto">

@ -1,4 +1,5 @@
using System;
using STranslate.Helper;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@ -23,7 +24,164 @@ namespace STranslate.View
{
InitializeComponent();
#if DEBUG
this.window.Topmost = true;
#endif
DataContext = ViewModel.SettingsVM.Instance;
}
private void window_Loaded(object sender, RoutedEventArgs e)
{
this.InputTextBox.Text = ViewModel.MainVM.Instance.NHotkeys.InputTranslate.Text;
this.CrossWordTextBox.Text = ViewModel.MainVM.Instance.NHotkeys.CrosswordTranslate.Text;
this.ScreenshotTextBox.Text = ViewModel.MainVM.Instance.NHotkeys.ScreenShotTranslate.Text;
this.ShowMainwinTextBox.Text = ViewModel.MainVM.Instance.NHotkeys.OpenMainWindow.Text;
HotKeyConflictCheck();
}
private byte _hotkeysModifiers;
private int _hotkeysKey;
private string _hotkeysText = string.Empty;
private void HotKeyTextBox_PreviewKeyDown(object sender, KeyEventArgs e)
{
e.Handled = true;
_hotkeysModifiers = 0;
_hotkeysKey = 0;
_hotkeysText = "";
Key key = (e.Key == Key.System ? e.SystemKey : e.Key);
if (key == Key.LeftShift || key == Key.RightShift
|| key == Key.LeftCtrl || key == Key.RightCtrl
|| key == Key.LeftAlt || key == Key.RightAlt
|| key == Key.LWin || key == Key.RWin)
{
return;
}
StringBuilder shortcutText = new StringBuilder();
if ((Keyboard.Modifiers & ModifierKeys.Control) != 0)
{
_hotkeysModifiers += 2;
shortcutText.Append("Ctrl + ");
}
if ((Keyboard.Modifiers & ModifierKeys.Shift) != 0)
{
_hotkeysModifiers += 4;
shortcutText.Append("Shift + ");
}
if ((Keyboard.Modifiers & ModifierKeys.Alt) != 0)
{
_hotkeysModifiers += 1;
shortcutText.Append("Alt + ");
}
if (_hotkeysModifiers == 0 && (key < Key.F1 || key > Key.F12))
{
_hotkeysKey = 0;
shortcutText.Clear();
((System.Windows.Controls.TextBox)sender).Text = _hotkeysText = "";
return;
}
_hotkeysKey = KeyInterop.VirtualKeyFromKey(key);
shortcutText.Append(key.ToString());
((System.Windows.Controls.TextBox)sender).Text = _hotkeysText = shortcutText.ToString();
}
private void CrossWord_KeyUp(object sender, KeyEventArgs e)
{
Key key = (e.Key == Key.System ? e.SystemKey : e.Key);
if (key == Key.LeftShift || key == Key.RightShift
|| key == Key.LeftCtrl || key == Key.RightCtrl
|| key == Key.LeftAlt || key == Key.RightAlt
|| key == Key.LWin || key == Key.RWin)
{
return;
}
ViewModel.MainVM.Instance.NHotkeys.CrosswordTranslate.Modifiers = _hotkeysModifiers;
ViewModel.MainVM.Instance.NHotkeys.CrosswordTranslate.Key = _hotkeysKey;
ViewModel.MainVM.Instance.NHotkeys.CrosswordTranslate.Text = _hotkeysText.ToString();
HotkeysHelper.ReRegisterHotKey();
HotKeyConflictCheck();
}
private void Input_KeyUp(object sender, KeyEventArgs e)
{
Key key = (e.Key == Key.System ? e.SystemKey : e.Key);
if (key == Key.LeftShift || key == Key.RightShift
|| key == Key.LeftCtrl || key == Key.RightCtrl
|| key == Key.LeftAlt || key == Key.RightAlt
|| key == Key.LWin || key == Key.RWin)
{
return;
}
ViewModel.MainVM.Instance.NHotkeys.InputTranslate.Modifiers = _hotkeysModifiers;
ViewModel.MainVM.Instance.NHotkeys.InputTranslate.Key = _hotkeysKey;
ViewModel.MainVM.Instance.NHotkeys.InputTranslate.Text = _hotkeysText.ToString();
HotkeysHelper.ReRegisterHotKey();
HotKeyConflictCheck();
}
private void Screenshot_KeyUp(object sender, KeyEventArgs e)
{
Key key = (e.Key == Key.System ? e.SystemKey : e.Key);
if (key == Key.LeftShift || key == Key.RightShift
|| key == Key.LeftCtrl || key == Key.RightCtrl
|| key == Key.LeftAlt || key == Key.RightAlt
|| key == Key.LWin || key == Key.RWin)
{
return;
}
ViewModel.MainVM.Instance.NHotkeys.ScreenShotTranslate.Modifiers = _hotkeysModifiers;
ViewModel.MainVM.Instance.NHotkeys.ScreenShotTranslate.Key = _hotkeysKey;
ViewModel.MainVM.Instance.NHotkeys.ScreenShotTranslate.Text = _hotkeysText.ToString();
HotkeysHelper.ReRegisterHotKey();
HotKeyConflictCheck();
}
private void ShowMainwin_KeyUp(object sender, KeyEventArgs e)
{
Key key = (e.Key == Key.System ? e.SystemKey : e.Key);
if (key == Key.LeftShift || key == Key.RightShift
|| key == Key.LeftCtrl || key == Key.RightCtrl
|| key == Key.LeftAlt || key == Key.RightAlt
|| key == Key.LWin || key == Key.RWin)
{
return;
}
ViewModel.MainVM.Instance.NHotkeys.OpenMainWindow.Modifiers = _hotkeysModifiers;
ViewModel.MainVM.Instance.NHotkeys.OpenMainWindow.Key = _hotkeysKey;
ViewModel.MainVM.Instance.NHotkeys.OpenMainWindow.Text = _hotkeysText.ToString();
HotkeysHelper.ReRegisterHotKey();
HotKeyConflictCheck();
}
private void ResetHoskeys_Click(object sender, RoutedEventArgs e)
{
CrossWordTextBox.Text = "Alt + D";
InputTextBox.Text = "Alt + A";
ScreenshotTextBox.Text = "Alt + S";
ShowMainwinTextBox.Text = "Alt + G";
ViewModel.MainVM.Instance.NHotkeys.CrosswordTranslate.Modifiers = 1;
ViewModel.MainVM.Instance.NHotkeys.CrosswordTranslate.Key = 68;
ViewModel.MainVM.Instance.NHotkeys.CrosswordTranslate.Text = "Alt + D";
ViewModel.MainVM.Instance.NHotkeys.InputTranslate.Modifiers = 1;
ViewModel.MainVM.Instance.NHotkeys.InputTranslate.Key = 65;
ViewModel.MainVM.Instance.NHotkeys.InputTranslate.Text = "Alt + A";
ViewModel.MainVM.Instance.NHotkeys.ScreenShotTranslate.Modifiers = 1;
ViewModel.MainVM.Instance.NHotkeys.ScreenShotTranslate.Key = 83;
ViewModel.MainVM.Instance.NHotkeys.ScreenShotTranslate.Text = "Alt + S";
ViewModel.MainVM.Instance.NHotkeys.OpenMainWindow.Modifiers = 1;
ViewModel.MainVM.Instance.NHotkeys.OpenMainWindow.Key = 71;
ViewModel.MainVM.Instance.NHotkeys.OpenMainWindow.Text = "Alt + G";
HotkeysHelper.ReRegisterHotKey();
HotKeyConflictCheck();
}
private void HotKeyConflictCheck()
{
this.CrossWordHotKeyConflictLabel.Visibility = ViewModel.MainVM.Instance.NHotkeys.CrosswordTranslate.Conflict ? Visibility.Visible : Visibility.Hidden;
this.ScreenshotHotKeyConflictLabel.Visibility = ViewModel.MainVM.Instance.NHotkeys.ScreenShotTranslate.Conflict ? Visibility.Visible : Visibility.Hidden;
this.InputHotKeyConflictLabel.Visibility = ViewModel.MainVM.Instance.NHotkeys.InputTranslate.Conflict ? Visibility.Visible : Visibility.Hidden;
this.ShowMainwinHotKeyConflictLabel.Visibility = ViewModel.MainVM.Instance.NHotkeys.OpenMainWindow.Conflict ? Visibility.Visible : Visibility.Hidden;
}
}
}

@ -25,6 +25,7 @@ namespace STranslate.ViewModel
InputCombo = LanguageEnumDict.Keys.ToList();
OutputCombo = LanguageEnumDict.Keys.ToList();
_sqlHelper = new SqliteHelper();
#endregion
#region Common
@ -209,6 +210,8 @@ namespace STranslate.ViewModel
Util.Util.FlushMemory();
Mainwin.NotifyIcon.Dispose();
Mainwin.Close();
//关闭数据库
_sqlHelper.Dispose();
//语音合成销毁
_speech.Dispose();
//注销快捷键
@ -231,6 +234,48 @@ namespace STranslate.ViewModel
{
_globalConfig = ConfigHelper.Instance.ReadConfig<ConfigModel>();
#region 读取热键
NHotkeys = _globalConfig.Hotkeys ?? new Hotkeys
{
InputTranslate = new InputTranslate
{
Modifiers = 1,
Key = 65,
Text = "Alt + A",
Conflict = false,
},
CrosswordTranslate = new CrosswordTranslate
{
Modifiers = 1,
Key = 68,
Text = "Alt + D",
Conflict = false,
},
ScreenShotTranslate = new ScreenShotTranslate
{
Modifiers = 1,
Key = 83,
Text = "Alt + S",
Conflict = false,
},
OpenMainWindow = new OpenMainWindow
{
Modifiers = 1,
Key = 71,
Text = "Alt + G",
Conflict = false,
},
};
#endregion
//读取历史记录数量
var count = _globalConfig.MaxHistoryCount;
SettingsVM.Instance.MaxHistoryCount = (count <= 0 || count >= 1000) ? 100 : count;
//读取自动识别语种比例
var scale = _globalConfig.AutoScale;
SettingsVM.Instance.AutoScale = (scale <= 0 || scale >= 1) ? 0.8 : scale;
//读取间隔
var tmp = _globalConfig.WordPickupInterval;
SettingsVM.Instance.WordPickupInterval = (tmp == 0 || tmp > 1000 || tmp < 100) ? 200 : tmp;
@ -271,12 +316,15 @@ namespace STranslate.ViewModel
{
ConfigHelper.Instance.WriteConfig(new ConfigModel
{
MaxHistoryCount = SettingsVM.Instance.MaxHistoryCount,
AutoScale = SettingsVM.Instance.AutoScale,
WordPickupInterval = SettingsVM.Instance.WordPickupInterval,
IsBright = Application.Current.Resources.MergedDictionaries[0].Source.ToString() == ThemeDefault ? true : false,
SourceLanguage = InputComboSelected,
TargetLanguage = OutputComboSelected,
SelectServer = TranslationInterface.FindIndex(x => x == SelectedTranslationInterface),
Servers = _globalConfig.Servers,
Hotkeys = NHotkeys,
});
}
catch (Exception ex)
@ -306,9 +354,8 @@ namespace STranslate.ViewModel
var ratio = (double)engStr.Length / text.Length;
//3. 判断英文字符个数占第一步所有字符个数比例,若超过一半则判定原字符串为英文字符串,否则为中文字符串
//TODO: 配置项
if (ratio > 0.8)
//3. 判断英文字符个数占第一步所有字符个数比例,若超过一定比例则判定原字符串为英文字符串,否则为中文字符串
if (ratio > SettingsVM.Instance.AutoScale)
{
return new Tuple<string, string>(LanguageEnum.EN.GetDescription(), LanguageEnum.ZH.GetDescription());
}
@ -326,7 +373,8 @@ namespace STranslate.ViewModel
{
try
{
if (string.IsNullOrEmpty(InputTxt.Trim())) throw new Exception("输入值为空!");
if (string.IsNullOrEmpty(InputTxt.Trim()))
throw new Exception("输入值为空!");
var isEng = string.Empty;
IdentifyLanguage = string.Empty;
OutputTxt = "翻译中...";
@ -338,6 +386,13 @@ namespace STranslate.ViewModel
//自动选择目标语言
if (OutputComboSelected == LanguageEnum.AUTO.GetDescription())
{
//只有在自动的模式下读取
var resp = _sqlHelper.Query(InputTxt);
if (!string.IsNullOrEmpty(resp))
{
OutputTxt = resp;
return;
}
var autoRet = AutomaticLanguageRecognition(InputTxt);
IdentifyLanguage = autoRet.Item1;
isEng = autoRet.Item2;
@ -357,6 +412,16 @@ namespace STranslate.ViewModel
}
OutputTxt = _translateResp;
await Task.Run(() =>
{
_sqlHelper.Insert(DateTime.Now,
InputTxt,
OutputTxt,
LanguageEnumDict[string.IsNullOrEmpty(IdentifyLanguage) ? InputComboSelected : IdentifyLanguage],
LanguageEnumDict[string.IsNullOrEmpty(isEng) ? OutputComboSelected : isEng],
SelectedTranslationInterface.Api);
});
//如果目标语言不是英文则不进行转换
//1. 自动判断语种Tuple item2 不为 EN
//2. 非自动判断语种,目标语种不为 EN
@ -386,6 +451,7 @@ namespace STranslate.ViewModel
#endregion handle
#region Params
private readonly SqliteHelper _sqlHelper;
private string _translateResp;
public ICommand MouseLeftDownCmd { get; set; }
public ICommand DeactivatedCmd { get; set; }
@ -408,9 +474,10 @@ namespace STranslate.ViewModel
/// </summary>
public MainWindow Mainwin;
private static MainVM _instance;
public static MainVM Instance => _instance ?? (_instance = new MainVM());
private static Lazy<MainVM> _instance = new Lazy<MainVM>(() => new MainVM());
public static MainVM Instance => _instance.Value;
public Hotkeys NHotkeys;
private bool IsTopmost { get; set; }
private const string TopmostTemplateName = "ButtonTemplateTopmost";
private const string UnTopmostTemplateName = "ButtonTemplateUnTopmost";

@ -14,7 +14,7 @@ namespace STranslate.ViewModel
{
public SettingsVM()
{
IsStartup = StartupHelper.IsStartup();
IsStartup = ShortcutHelper.IsStartup();
Version = HandleVersion(System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString() ?? "1.0.0.0");
@ -63,9 +63,9 @@ namespace STranslate.ViewModel
StartupCmd = new RelayCommand((_) => true, (_) =>
{
if (StartupHelper.IsStartup()) StartupHelper.UnSetStartup();
else StartupHelper.SetStartup();
IsStartup = StartupHelper.IsStartup();
if (ShortcutHelper.IsStartup()) ShortcutHelper.UnSetStartup();
else ShortcutHelper.SetStartup();
IsStartup = ShortcutHelper.IsStartup();
});
EscCmd = new RelayCommand((_) => true, (o) =>
{
@ -109,8 +109,9 @@ namespace STranslate.ViewModel
public ICommand StartupCmd { get; private set; }
public ICommand EscCmd { get; private set; }
private static SettingsVM _instance;
public static SettingsVM Instance => _instance ?? (_instance = new SettingsVM());
private static Lazy<SettingsVM> _instance = new Lazy<SettingsVM>(() => new SettingsVM());
public static SettingsVM Instance => _instance.Value;
/// <summary>
/// 是否开机自启
@ -124,11 +125,23 @@ namespace STranslate.ViewModel
private string _version;
public string Version { get => _version; set => UpdateProperty(ref _version, value); }
/// <summary>
/// 语种识别比例
/// </summary>
private double _autoScale;
public double AutoScale { get => _autoScale; set => UpdateProperty(ref _autoScale, value); }
/// <summary>
/// 取词间隔
/// </summary>
private double _wordPickupInterval;
public double WordPickupInterval { get => _wordPickupInterval; set => UpdateProperty(ref _wordPickupInterval, value); }
/// <summary>
/// 最大历史记录数量
/// </summary>
private int _maxHistoryCount;
public int MaxHistoryCount { get => _maxHistoryCount; set => UpdateProperty(ref _maxHistoryCount, value); }
}
}

@ -2,6 +2,15 @@
<packages>
<package id="Microsoft.Xaml.Behaviors.Wpf" version="1.1.39" targetFramework="net48" />
<package id="Newtonsoft.Json" version="13.0.2" targetFramework="net48" />
<package id="sqlite-net-pcl" version="1.8.116" targetFramework="net48" />
<package id="SQLitePCLRaw.bundle_green" version="2.0.4" targetFramework="net48" />
<package id="SQLitePCLRaw.core" version="2.0.4" targetFramework="net48" />
<package id="SQLitePCLRaw.lib.e_sqlite3" version="2.0.4" targetFramework="net48" />
<package id="SQLitePCLRaw.provider.dynamic_cdecl" version="2.0.4" targetFramework="net48" />
<package id="System.Buffers" version="4.4.0" targetFramework="net48" />
<package id="System.Memory" version="4.5.3" targetFramework="net48" />
<package id="System.Numerics.Vectors" version="4.4.0" targetFramework="net48" />
<package id="System.Runtime.CompilerServices.Unsafe" version="4.5.2" targetFramework="net48" />
<package id="Tesseract" version="5.2.0" targetFramework="net48" />
<package id="WpfScreenHelper" version="2.1.0" targetFramework="net48" />
</packages>

@ -144,14 +144,14 @@ namespace Updater
if (unresult)
{
SetStatus("更新完成!", false);
Process tai = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo(System.IO.Path.Combine(unpath, "Tai.exe"));
tai.StartInfo = startInfo;
tai.Start();
Process p = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo(System.IO.Path.Combine(unpath, "STranslate.exe"));
p.StartInfo = startInfo;
p.Start();
}
else
{
SetStatus("解压文件时发生异常,请重试!通常情况可能是因为Tai主程序尚未退出。", false);
SetStatus("解压文件时发生异常,请重试!通常情况可能是因为 STranslate 主程序尚未退出。", false);
UpdateBtn.Visibility = Visibility.Visible;
}

@ -102,6 +102,7 @@
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<None Include="packages.config" />
<None Include="Properties\Settings.settings">

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

Loading…
Cancel
Save