tmp: feat func

dev_without_third_libraries
DESKTOP-3BO4HSG\ksat 2 years ago
parent 2fe17e7f65
commit f01c4d02c9

@ -4,8 +4,8 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:STranslate"
xmlns:vm="clr-namespace:STranslate.ViewModel"
xmlns:hc="https://handyorg.github.io/handycontrol"
xmlns:vm="clr-namespace:STranslate.ViewModel"
mc:Ignorable="d"
Background="Transparent"
WindowStartupLocation="CenterScreen"
@ -20,6 +20,9 @@
Height="450"
Width="400"
Icon="/Images/translate2.ico">
<Window.DataContext>
<vm:MainVM/>
</Window.DataContext>
<Border BorderThickness="0"
Background="#fff"
CornerRadius="10">
@ -30,8 +33,7 @@
<RowDefinition Height="8*" />
</Grid.RowDefinitions>
<!--<hc:NotifyIcon Text="STranslate"
Click="NotifyIcon_Click"
<hc:NotifyIcon Text="STranslate"
IsBlink="False"
Visibility="Visible"
Icon="/Images/translate2.ico">
@ -42,13 +44,24 @@
<Setter Property="ContextMenu.Width" Value="100" />
</Style>
</ContextMenu.Style>
<MenuItem x:Name="CrossWordTranslateMenuItem"
Click="CrossWordTranslateMenuItem_Click"
Header="划词翻译" />
<MenuItem x:Name="ScreenshotTranslateMenuItem"
Click="ScreenshotTranslateMenuItem_Click"
Header="截图翻译" />
<MenuItem x:Name="InputTranslateMenuItem"
Click="InputTranslateMenuItem_Click"
Header="输入翻译" />
<Separator/>
<MenuItem Command="hc:ControlCommands.PushMainWindow2Top"
Header="主界面" />
<Separator/>
<MenuItem Command="hc:ControlCommands.ShutdownApp"
Header="退出" />
</ContextMenu>
</hc:NotifyIcon.ContextMenu>
</hc:NotifyIcon>-->
</hc:NotifyIcon>
<!--input-->
<Grid x:Name="Input"
@ -102,11 +115,11 @@
SelectedItem="{Binding OutputComboSelected}" />
<Button Margin="10,0,0,0"
Cursor="Hand"
Command="{Binding CopyTranslateResultCmd}">
Command="{Binding CopyResultCmd}">
<Image Source="/Images/copy.png" />
<hc:FloatingBlock.ContentTemplate>
<DataTemplate>
<TextBlock Text="复制成功" />
<TextBlock Text="复制" />
</DataTemplate>
</hc:FloatingBlock.ContentTemplate>
</Button>

@ -12,57 +12,14 @@ namespace STranslate
/// </summary>
public partial class MainWindow : Window
{
private MainVM vm;
public MainWindow()
{
InitializeComponent();
InitHwnd();
InitTray();
this.DataContext = MainVM.Instance;
}
private void InitHwnd()
{
var helper = new WindowInteropHelper(this);
helper.EnsureHandle();
vm = (MainVM)this.DataContext;
}
/// <summary>
/// 初始化托盘
/// </summary>
private void InitTray()
{
//notifyIcon.BalloonTipText = "程序开始运行";
//notifyIcon.ShowBalloonTip(1000);
notifyIcon.Text = "STranslate";
notifyIcon.Icon = new System.Drawing.Icon(@"D:\CodePepo\STranslate\STranslate\Images\translate2.ico");
notifyIcon.Visible = true;
System.Windows.Forms.MenuItem inputTranslateButton = new System.Windows.Forms.MenuItem("输入翻译");
inputTranslateButton.Click += new EventHandler(InputTranslate_Click);
System.Windows.Forms.MenuItem crosswordTranslateButton = new System.Windows.Forms.MenuItem("划词翻译");
crosswordTranslateButton.Click += new EventHandler(CrosswordTranslate_Click);
System.Windows.Forms.MenuItem screenshotTranslationButton = new System.Windows.Forms.MenuItem("截图翻译");
screenshotTranslationButton.Click += new EventHandler(ScreenshotTranslation_Click);
System.Windows.Forms.MenuItem openMainWinButton = new System.Windows.Forms.MenuItem("显示主窗口");
openMainWinButton.Click += new EventHandler(OpenMainWin_Click);
System.Windows.Forms.MenuItem exitButton = new System.Windows.Forms.MenuItem("退出");
exitButton.Click += new EventHandler(Exit_Click);
System.Windows.Forms.MenuItem[] childen = new System.Windows.Forms.MenuItem[] {
inputTranslateButton,
crosswordTranslateButton,
screenshotTranslationButton,
openMainWinButton,
exitButton
};
notifyIcon.ContextMenu = new System.Windows.Forms.ContextMenu(childen);
}
/// <summary>
/// 显示主窗口
/// </summary>
@ -83,6 +40,7 @@ namespace STranslate
{
DragMove();
}
/// <summary>
/// 软件运行时快捷键
/// </summary>
@ -94,15 +52,15 @@ namespace STranslate
if (e.Key == Key.Escape)
{
this.Hide();
MainVM.Instance.InputTxt = string.Empty;
MainVM.Instance.OutputTxt = string.Empty;
vm.InputTxt = string.Empty;
vm.OutputTxt = string.Empty;
}
//退出 Ctrl+Shift+Q
if (e.KeyboardDevice.Modifiers.HasFlag(ModifierKeys.Control)
&& e.KeyboardDevice.Modifiers.HasFlag(ModifierKeys.Shift)
&& e.Key == Key.Q)
{
Exit_Click(null, null);
Environment.Exit(0);
}
#if false
//置顶/取消置顶 Ctrl+T
@ -139,6 +97,7 @@ namespace STranslate
}
#endif
}
/// <summary>
/// 监听全局快捷键
/// </summary>
@ -146,38 +105,10 @@ namespace STranslate
protected override void OnSourceInitialized(EventArgs e)
{
IntPtr handle = new WindowInteropHelper(this).Handle;
HotKeysUtil2.RegisterHotKey(handle);
HotKeysUtil.RegisterHotKey(handle);
HwndSource source = HwndSource.FromHwnd(handle);
source.AddHook(WndProc);
#if false
HotkeysUtil.InitialHook(this);
HotkeysUtil.Regist(HotkeyModifiers.MOD_ALT, Key.A, () =>
{
this.Show();
this.Activate();
this.TextBoxInput.Focus();
});
HotkeysUtil.Regist(HotkeyModifiers.MOD_ALT, Key.D, () =>
{
//复制内容
KeyboardUtil.Press(Key.LeftCtrl);
KeyboardUtil.Type(Key.C);
KeyboardUtil.Release(Key.LeftCtrl);
System.Threading.Thread.Sleep(200);
System.Diagnostics.Debug.Print(Clipboard.GetText());
//this.Show();
//this.Activate();
//this.TextBoxInput.Text = "123";
//this.TextBoxInput.Text = Clipboard.GetText();
//this.TextBoxInput.Focus();
//KeyboardUtil.Type(Key.Enter);
});
#endif
}
/// <summary>
/// 热键的功能
@ -189,17 +120,17 @@ namespace STranslate
{
case 0x0312: //这个是window消息定义的 注册的热键消息
//Console.WriteLine(wParam.ToString());
if (wParam.ToString().Equals(HotKeysUtil2.InputTranslateId + ""))
if (wParam.ToString().Equals(HotKeysUtil.InputTranslateId + ""))
{
this.InputTranslate_Click(null, null);
this.InputTranslateMenuItem_Click(null, null);
}
else if (wParam.ToString().Equals(HotKeysUtil2.CrosswordTranslateId + ""))
else if (wParam.ToString().Equals(HotKeysUtil.CrosswordTranslateId + ""))
{
this.CrosswordTranslate_Click(null, null);
this.CrossWordTranslateMenuItem_Click(null, null);
}
else if (wParam.ToString().Equals(HotKeysUtil2.ScreenShotTranslateId + ""))
else if (wParam.ToString().Equals(HotKeysUtil.ScreenShotTranslateId + ""))
{
this.ScreenshotTranslation_Click(null, null);
this.ScreenshotTranslateMenuItem_Click(null, null);
}
break;
}
@ -217,28 +148,13 @@ namespace STranslate
}
/// <summary>
/// 截图翻译
/// 清空输入输出框
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ScreenshotTranslation_Click(object sender, EventArgs e)
private void ClearTextBox()
{
MessageBox.Show("开发中");
}
vm.InputTxt = string.Empty;
vm.OutputTxt = string.Empty;
/// <summary>
/// 划词翻译
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void CrosswordTranslate_Click(object sender, EventArgs e)
{
ClearTextBox();
var sentence = GetWords.Get();
this.Show();
this.Activate();
this.TextBoxInput.Text = sentence.Trim();
_ = MainVM.Instance.Translate();
}
/// <summary>
@ -246,37 +162,36 @@ namespace STranslate
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void InputTranslate_Click(object sender, EventArgs e)
private void InputTranslateMenuItem_Click(object sender, RoutedEventArgs e)
{
ClearTextBox();
Show();
Activate();
OpenMainWin_Click(null, null);
TextBoxInput.Focus();
}
/// <summary>
/// 退出程序
/// 划词翻译
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Exit_Click(object sender, EventArgs e)
private void CrossWordTranslateMenuItem_Click(object sender, RoutedEventArgs e)
{
notifyIcon.Dispose();
Environment.Exit(0);
ClearTextBox();
var sentence = GetWords.Get();
this.Show();
this.Activate();
this.TextBoxInput.Text = sentence.Trim();
_ = vm.Translate();
}
/// <summary>
/// 清空输入输出框
/// 截图翻译
/// </summary>
private void ClearTextBox()
/// <param name="sender"></param>
/// <param name="e"></param>
private void ScreenshotTranslateMenuItem_Click(object sender, RoutedEventArgs e)
{
MainVM.Instance.InputTxt = string.Empty;
MainVM.Instance.OutputTxt = string.Empty;
MessageBox.Show("开发中");
}
/// <summary>
/// 托盘图标
/// </summary>
private System.Windows.Forms.NotifyIcon notifyIcon = new System.Windows.Forms.NotifyIcon();
}
}

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static STranslate.Utils.NativeMethod;
namespace STranslate.Model
{
@ -10,21 +11,21 @@ namespace STranslate.Model
{
public static class InputTranslate
{
public static byte Modifiers = 1;
public static byte Modifiers = (byte)KeyModifiers.Alt;
public static int Key = 65;
public static String Text = "A";
public static bool Conflict = false;
}
public static class CrosswordTranslate
{
public static byte Modifiers = 0;
public static int Key = 113;
public static String Text = "F2";
public static byte Modifiers = (byte)KeyModifiers.Ctrl;
public static int Key = 68;
//public static String Text = "F2";
public static bool Conflict = false;
}
public static class ScreenShotTranslate
{
public static byte Modifiers = 1;
public static byte Modifiers = (byte)KeyModifiers.Alt;
public static int Key = 83;
public static String Text = "S";
public static bool Conflict = false;

@ -89,9 +89,7 @@
<Compile Include="Utils\ConfigUtil.cs" />
<Compile Include="Utils\GetWordsUtil.cs" />
<Compile Include="Utils\HotKeysUtil.cs" />
<Compile Include="Utils\HotKeysUtil2.cs" />
<Compile Include="Utils\HttpUtil.cs" />
<Compile Include="Utils\KeyboardUtil.cs" />
<Compile Include="Utils\MvvmUtil.cs" />
<Compile Include="Utils\NativeMethod.cs" />
<Compile Include="Utils\TranslateUtil.cs" />

@ -1,97 +1,94 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Input;
using System.Windows.Interop;
using STranslate.Model;
using System;
namespace STranslate.Utils
{
//TODO: 另一个方案: https://www.cnblogs.com/leolion/p/4693514.html
/// <summary>
/// 引用自 https://blog.csdn.net/weixin_44879611/article/details/103275347
/// </summary>
internal static class HotkeysUtil
internal class HotKeysUtil
{
#region 系统api
public static IntPtr mainFormHandle;
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool RegisterHotKey(IntPtr hWnd, int id, HotkeyModifiers fsModifiers, uint vk);
[DllImport("user32.dll")]
private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
#endregion 系统api
public static int InputTranslateId = 854;
public static byte InputTranslateModifiers;
public static int InputTranslateKey;
public static int CrosswordTranslateId = 855;
public static byte CrosswordTranslateModifiers;
public static int CrosswordTranslateKey;
public static int ScreenShotTranslateId = 856;
public static byte ScreenShotTranslateModifiers;
public static int ScreenShotTranslateKey;
public static void RegisterHotKey(IntPtr mainFormHandle)
{
HotKeysUtil.mainFormHandle = mainFormHandle;
public static IntPtr hwnd;
InputTranslateModifiers = HotKeys.InputTranslate.Modifiers;
InputTranslateKey = HotKeys.InputTranslate.Key;
CrosswordTranslateModifiers = HotKeys.CrosswordTranslate.Modifiers;
CrosswordTranslateKey = HotKeys.CrosswordTranslate.Key;
ScreenShotTranslateModifiers = HotKeys.ScreenShotTranslate.Modifiers;
ScreenShotTranslateKey = HotKeys.ScreenShotTranslate.Key;
public static void InitialHook(Window window)
{
hwnd = new WindowInteropHelper(window).Handle;
var _hwndSource = HwndSource.FromHwnd(hwnd);
_hwndSource.AddHook(WndProc);
if (HotKeys.InputTranslate.Key != 0)
{
HotKeys.InputTranslate.Conflict = !NativeMethod.RegisterHotKey(mainFormHandle, InputTranslateId, HotKeys.InputTranslate.Modifiers, HotKeys.InputTranslate.Key);
}
if (HotKeys.CrosswordTranslate.Key != 0)
{
HotKeys.CrosswordTranslate.Conflict = !NativeMethod.RegisterHotKey(mainFormHandle, CrosswordTranslateId, HotKeys.CrosswordTranslate.Modifiers, HotKeys.CrosswordTranslate.Key);
}
if (HotKeys.ScreenShotTranslate.Key != 0)
{
HotKeys.ScreenShotTranslate.Conflict = !NativeMethod.RegisterHotKey(mainFormHandle, ScreenShotTranslateId, HotKeys.ScreenShotTranslate.Modifiers, HotKeys.ScreenShotTranslate.Key);
}
}
/// <summary>
/// 注册快捷键
/// </summary>
/// <param name="window">持有快捷键窗口</param>
/// <param name="fsModifiers">组合键</param>
/// <param name="key">快捷键</param>
/// <param name="callBack">回调函数</param>
public static void Regist(HotkeyModifiers fsModifiers, Key key, HotKeyCallBackHanlder callBack)
public static void UnRegisterHotKey()
{
int id = keyid++;
var vk = KeyInterop.VirtualKeyFromKey(key);
if (!RegisterHotKey(hwnd, id, fsModifiers, (uint)vk))
throw new Exception("regist hotkey fail.");
keymap[id] = callBack;
NativeMethod.UnregisterHotKey(mainFormHandle, InputTranslateId);
NativeMethod.UnregisterHotKey(mainFormHandle, CrosswordTranslateId);
NativeMethod.UnregisterHotKey(mainFormHandle, ScreenShotTranslateId);
}
/// <summary>
/// 快捷键消息处理
/// </summary>
private static IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
public static void ReRegisterHotKey()
{
if (msg == WM_HOTKEY)
if (HotKeys.InputTranslate.Key == 0)
{
NativeMethod.UnregisterHotKey(mainFormHandle, InputTranslateId);
}
else if (InputTranslateModifiers != HotKeys.InputTranslate.Modifiers || InputTranslateKey != HotKeys.InputTranslate.Key)
{
int id = wParam.ToInt32();
if (keymap.TryGetValue(id, out var callback))
{
callback();
NativeMethod.UnregisterHotKey(mainFormHandle, InputTranslateId);
HotKeys.InputTranslate.Conflict = !NativeMethod.RegisterHotKey(mainFormHandle, InputTranslateId, HotKeys.InputTranslate.Modifiers, HotKeys.InputTranslate.Key);
}
}
return IntPtr.Zero;
}
InputTranslateModifiers = HotKeys.InputTranslate.Modifiers;
InputTranslateKey = HotKeys.InputTranslate.Key;
/// <summary>
/// 注销快捷键
/// </summary>
/// <param name="hWnd">持有快捷键窗口的句柄</param>
/// <param name="callBack">回调函数</param>
public static void UnRegist(IntPtr hWnd, HotKeyCallBackHanlder callBack)
{
foreach (KeyValuePair<int, HotKeyCallBackHanlder> var in keymap)
if (HotKeys.CrosswordTranslate.Key == 0)
{
if (var.Value == callBack)
UnregisterHotKey(hWnd, var.Key);
NativeMethod.UnregisterHotKey(mainFormHandle, CrosswordTranslateId);
}
}
private const int WM_HOTKEY = 0x312;
private static int keyid = 10;
private static Dictionary<int, HotKeyCallBackHanlder> keymap = new Dictionary<int, HotKeyCallBackHanlder>();
public delegate void HotKeyCallBackHanlder();
}
else if (CrosswordTranslateModifiers != HotKeys.CrosswordTranslate.Modifiers || CrosswordTranslateKey != HotKeys.CrosswordTranslate.Key)
{
{
NativeMethod.UnregisterHotKey(mainFormHandle, CrosswordTranslateId);
HotKeys.CrosswordTranslate.Conflict = !NativeMethod.RegisterHotKey(mainFormHandle, CrosswordTranslateId, HotKeys.CrosswordTranslate.Modifiers, HotKeys.CrosswordTranslate.Key);
}
}
CrosswordTranslateModifiers = HotKeys.CrosswordTranslate.Modifiers;
CrosswordTranslateKey = HotKeys.CrosswordTranslate.Key;
internal enum HotkeyModifiers
{
MOD_ALT = 0x1,
MOD_CONTROL = 0x2,
MOD_SHIFT = 0x4,
MOD_WIN = 0x8
if (HotKeys.ScreenShotTranslate.Key == 0)
{
NativeMethod.UnregisterHotKey(mainFormHandle, ScreenShotTranslateId);
}
else if (ScreenShotTranslateModifiers != HotKeys.ScreenShotTranslate.Modifiers || ScreenShotTranslateKey != HotKeys.ScreenShotTranslate.Key)
{
NativeMethod.UnregisterHotKey(mainFormHandle, ScreenShotTranslateId);
HotKeys.ScreenShotTranslate.Conflict = !NativeMethod.RegisterHotKey(mainFormHandle, ScreenShotTranslateId, HotKeys.ScreenShotTranslate.Modifiers, HotKeys.ScreenShotTranslate.Key);
}
ScreenShotTranslateModifiers = HotKeys.ScreenShotTranslate.Modifiers;
ScreenShotTranslateKey = HotKeys.ScreenShotTranslate.Key;
}
}
}
}

@ -1,94 +0,0 @@
using STranslate.Model;
using System;
namespace STranslate.Utils
{
internal class HotKeysUtil2
{
public static IntPtr mainFormHandle;
public static int InputTranslateId = 854;
public static byte InputTranslateModifiers;
public static int InputTranslateKey;
public static int CrosswordTranslateId = 855;
public static byte CrosswordTranslateModifiers;
public static int CrosswordTranslateKey;
public static int ScreenShotTranslateId = 856;
public static byte ScreenShotTranslateModifiers;
public static int ScreenShotTranslateKey;
public static void RegisterHotKey(IntPtr mainFormHandle)
{
HotKeysUtil2.mainFormHandle = mainFormHandle;
InputTranslateModifiers = HotKeys.InputTranslate.Modifiers;
InputTranslateKey = HotKeys.InputTranslate.Key;
CrosswordTranslateModifiers = HotKeys.CrosswordTranslate.Modifiers;
CrosswordTranslateKey = HotKeys.CrosswordTranslate.Key;
ScreenShotTranslateModifiers = HotKeys.ScreenShotTranslate.Modifiers;
ScreenShotTranslateKey = HotKeys.ScreenShotTranslate.Key;
if (HotKeys.InputTranslate.Key != 0)
{
HotKeys.InputTranslate.Conflict = !NativeMethod.RegisterHotKey(mainFormHandle, InputTranslateId, HotKeys.InputTranslate.Modifiers, HotKeys.InputTranslate.Key);
}
if (HotKeys.CrosswordTranslate.Key != 0)
{
HotKeys.CrosswordTranslate.Conflict = !NativeMethod.RegisterHotKey(mainFormHandle, CrosswordTranslateId, HotKeys.CrosswordTranslate.Modifiers, HotKeys.CrosswordTranslate.Key);
}
if (HotKeys.ScreenShotTranslate.Key != 0)
{
HotKeys.ScreenShotTranslate.Conflict = !NativeMethod.RegisterHotKey(mainFormHandle, ScreenShotTranslateId, HotKeys.ScreenShotTranslate.Modifiers, HotKeys.ScreenShotTranslate.Key);
}
}
public static void UnRegisterHotKey()
{
NativeMethod.UnregisterHotKey(mainFormHandle, InputTranslateId);
NativeMethod.UnregisterHotKey(mainFormHandle, CrosswordTranslateId);
NativeMethod.UnregisterHotKey(mainFormHandle, ScreenShotTranslateId);
}
public static void ReRegisterHotKey()
{
if (HotKeys.InputTranslate.Key == 0)
{
NativeMethod.UnregisterHotKey(mainFormHandle, InputTranslateId);
}
else if (InputTranslateModifiers != HotKeys.InputTranslate.Modifiers || InputTranslateKey != HotKeys.InputTranslate.Key)
{
{
NativeMethod.UnregisterHotKey(mainFormHandle, InputTranslateId);
HotKeys.InputTranslate.Conflict = !NativeMethod.RegisterHotKey(mainFormHandle, InputTranslateId, HotKeys.InputTranslate.Modifiers, HotKeys.InputTranslate.Key);
}
}
InputTranslateModifiers = HotKeys.InputTranslate.Modifiers;
InputTranslateKey = HotKeys.InputTranslate.Key;
if (HotKeys.CrosswordTranslate.Key == 0)
{
NativeMethod.UnregisterHotKey(mainFormHandle, CrosswordTranslateId);
}
else if (CrosswordTranslateModifiers != HotKeys.CrosswordTranslate.Modifiers || CrosswordTranslateKey != HotKeys.CrosswordTranslate.Key)
{
{
NativeMethod.UnregisterHotKey(mainFormHandle, CrosswordTranslateId);
HotKeys.CrosswordTranslate.Conflict = !NativeMethod.RegisterHotKey(mainFormHandle, CrosswordTranslateId, HotKeys.CrosswordTranslate.Modifiers, HotKeys.CrosswordTranslate.Key);
}
}
CrosswordTranslateModifiers = HotKeys.CrosswordTranslate.Modifiers;
CrosswordTranslateKey = HotKeys.CrosswordTranslate.Key;
if (HotKeys.ScreenShotTranslate.Key == 0)
{
NativeMethod.UnregisterHotKey(mainFormHandle, ScreenShotTranslateId);
}
else if (ScreenShotTranslateModifiers != HotKeys.ScreenShotTranslate.Modifiers || ScreenShotTranslateKey != HotKeys.ScreenShotTranslate.Key)
{
NativeMethod.UnregisterHotKey(mainFormHandle, ScreenShotTranslateId);
HotKeys.ScreenShotTranslate.Conflict = !NativeMethod.RegisterHotKey(mainFormHandle, ScreenShotTranslateId, HotKeys.ScreenShotTranslate.Modifiers, HotKeys.ScreenShotTranslate.Key);
}
ScreenShotTranslateModifiers = HotKeys.ScreenShotTranslate.Modifiers;
ScreenShotTranslateKey = HotKeys.ScreenShotTranslate.Key;
}
}
}

@ -1,538 +0,0 @@
using System;
using System.ComponentModel;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Windows.Input;
namespace STranslate.Utils
{
#region Operate Mouse Keyboard
//引用自: https://www.cnblogs.com/sixty/archive/2009/08/09/1542210.html
/// <summary>
/// Native methods
/// </summary>
internal static class NativeMethods
{
//User32 wrappers cover API's used for Mouse input
#region User32
// Two special bitmasks we define to be able to grab
// shift and character information out of a VKey.
internal const int VKeyShiftMask = 0x0100;
internal const int VKeyCharMask = 0x00FF;
// Various Win32 constants
internal const int KeyeventfExtendedkey = 0x0001;
internal const int KeyeventfKeyup = 0x0002;
internal const int KeyeventfScancode = 0x0008;
internal const int MouseeventfVirtualdesk = 0x4000;
internal const int SMXvirtualscreen = 76;
internal const int SMYvirtualscreen = 77;
internal const int SMCxvirtualscreen = 78;
internal const int SMCyvirtualscreen = 79;
internal const int XButton1 = 0x0001;
internal const int XButton2 = 0x0002;
internal const int WheelDelta = 120;
internal const int InputMouse = 0;
internal const int InputKeyboard = 1;
// Various Win32 data structures
[StructLayout(LayoutKind.Sequential)]
internal struct INPUT
{
internal int type;
internal INPUTUNION union;
};
[StructLayout(LayoutKind.Explicit)]
internal struct INPUTUNION
{
[FieldOffset(0)]
internal MOUSEINPUT mouseInput;
[FieldOffset(0)]
internal KEYBDINPUT keyboardInput;
};
[StructLayout(LayoutKind.Sequential)]
internal struct MOUSEINPUT
{
internal int dx;
internal int dy;
internal int mouseData;
internal int dwFlags;
internal int time;
internal IntPtr dwExtraInfo;
};
[StructLayout(LayoutKind.Sequential)]
internal struct KEYBDINPUT
{
internal short wVk;
internal short wScan;
internal int dwFlags;
internal int time;
internal IntPtr dwExtraInfo;
};
[Flags]
internal enum SendMouseInputFlags
{
Move = 0x0001,
LeftDown = 0x0002,
LeftUp = 0x0004,
RightDown = 0x0008,
RightUp = 0x0010,
MiddleDown = 0x0020,
MiddleUp = 0x0040,
XDown = 0x0080,
XUp = 0x0100,
Wheel = 0x0800,
Absolute = 0x8000,
};
// Importing various Win32 APIs that we need for input
[DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
internal static extern int GetSystemMetrics(int nIndex);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
internal static extern int MapVirtualKey(int nVirtKey, int nMapType);
[DllImport("user32.dll", SetLastError = true)]
internal static extern int SendInput(int nInputs, ref INPUT mi, int cbSize);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
internal static extern short VkKeyScan(char ch);
#endregion User32
}
/// <summary>
/// Exposes a simple interface to common mouse operations, allowing the user to simulate mouse input.
/// </summary>
/// <example>The following code moves to screen coordinate 100,100 and left clicks.
/// <code>
/**
Mouse.MoveTo(new Point(100, 100));
Mouse.Click(MouseButton.Left);
*/
/// </code>
/// </example>
public static class Mouse
{
/// <summary>
/// Clicks a mouse button.
/// </summary>
/// <param name="mouseButton">The mouse button to click.</param>
public static void Click(MouseButton mouseButton)
{
Down(mouseButton);
Up(mouseButton);
}
/// <summary>
/// Double-clicks a mouse button.
/// </summary>
/// <param name="mouseButton">The mouse button to click.</param>
public static void DoubleClick(MouseButton mouseButton)
{
Click(mouseButton);
Click(mouseButton);
}
/// <summary>
/// Performs a mouse-down operation for a specified mouse button.
/// </summary>
/// <param name="mouseButton">The mouse button to use.</param>
public static void Down(MouseButton mouseButton)
{
switch (mouseButton)
{
case MouseButton.Left:
SendMouseInput(0, 0, 0, NativeMethods.SendMouseInputFlags.LeftDown);
break;
case MouseButton.Right:
SendMouseInput(0, 0, 0, NativeMethods.SendMouseInputFlags.RightDown);
break;
case MouseButton.Middle:
SendMouseInput(0, 0, 0, NativeMethods.SendMouseInputFlags.MiddleDown);
break;
case MouseButton.XButton1:
SendMouseInput(0, 0, NativeMethods.XButton1, NativeMethods.SendMouseInputFlags.XDown);
break;
case MouseButton.XButton2:
SendMouseInput(0, 0, NativeMethods.XButton2, NativeMethods.SendMouseInputFlags.XDown);
break;
default:
throw new InvalidOperationException("Unsupported MouseButton input.");
}
}
/// <summary>
/// Moves the mouse pointer to the specified screen coordinates.
/// </summary>
/// <param name="point">The screen coordinates to move to.</param>
public static void MoveTo(System.Drawing.Point point)
{
SendMouseInput(point.X, point.Y, 0, NativeMethods.SendMouseInputFlags.Move | NativeMethods.SendMouseInputFlags.Absolute);
}
/// <summary>
/// Resets the system mouse to a clean state.
/// </summary>
public static void Reset()
{
MoveTo(new System.Drawing.Point(0, 0));
if (System.Windows.Input.Mouse.LeftButton == MouseButtonState.Pressed)
{
SendMouseInput(0, 0, 0, NativeMethods.SendMouseInputFlags.LeftUp);
}
if (System.Windows.Input.Mouse.MiddleButton == MouseButtonState.Pressed)
{
SendMouseInput(0, 0, 0, NativeMethods.SendMouseInputFlags.MiddleUp);
}
if (System.Windows.Input.Mouse.RightButton == MouseButtonState.Pressed)
{
SendMouseInput(0, 0, 0, NativeMethods.SendMouseInputFlags.RightUp);
}
if (System.Windows.Input.Mouse.XButton1 == MouseButtonState.Pressed)
{
SendMouseInput(0, 0, NativeMethods.XButton1, NativeMethods.SendMouseInputFlags.XUp);
}
if (System.Windows.Input.Mouse.XButton2 == MouseButtonState.Pressed)
{
SendMouseInput(0, 0, NativeMethods.XButton2, NativeMethods.SendMouseInputFlags.XUp);
}
}
/// <summary>
/// Simulates scrolling of the mouse wheel up or down.
/// </summary>
/// <param name="lines">The number of lines to scroll. Use positive numbers to scroll up and negative numbers to scroll down.</param>
public static void Scroll(double lines)
{
int amount = (int)(NativeMethods.WheelDelta * lines);
SendMouseInput(0, 0, amount, NativeMethods.SendMouseInputFlags.Wheel);
}
/// <summary>
/// Performs a mouse-up operation for a specified mouse button.
/// </summary>
/// <param name="mouseButton">The mouse button to use.</param>
public static void Up(MouseButton mouseButton)
{
switch (mouseButton)
{
case MouseButton.Left:
SendMouseInput(0, 0, 0, NativeMethods.SendMouseInputFlags.LeftUp);
break;
case MouseButton.Right:
SendMouseInput(0, 0, 0, NativeMethods.SendMouseInputFlags.RightUp);
break;
case MouseButton.Middle:
SendMouseInput(0, 0, 0, NativeMethods.SendMouseInputFlags.MiddleUp);
break;
case MouseButton.XButton1:
SendMouseInput(0, 0, NativeMethods.XButton1, NativeMethods.SendMouseInputFlags.XUp);
break;
case MouseButton.XButton2:
SendMouseInput(0, 0, NativeMethods.XButton2, NativeMethods.SendMouseInputFlags.XUp);
break;
default:
throw new InvalidOperationException("Unsupported MouseButton input.");
}
}
/// <summary>
/// Sends mouse input.
/// </summary>
/// <param name="x">x coordinate</param>
/// <param name="y">y coordinate</param>
/// <param name="data">scroll wheel amount</param>
/// <param name="flags">SendMouseInputFlags flags</param>
[PermissionSet(SecurityAction.Assert, Name = "FullTrust")]
private static void SendMouseInput(int x, int y, int data, NativeMethods.SendMouseInputFlags flags)
{
PermissionSet permissions = new PermissionSet(PermissionState.Unrestricted);
permissions.Demand();
int intflags = (int)flags;
if ((intflags & (int)NativeMethods.SendMouseInputFlags.Absolute) != 0)
{
// Absolute position requires normalized coordinates.
NormalizeCoordinates(ref x, ref y);
intflags |= NativeMethods.MouseeventfVirtualdesk;
}
NativeMethods.INPUT mi = new NativeMethods.INPUT();
mi.type = NativeMethods.InputMouse;
mi.union.mouseInput.dx = x;
mi.union.mouseInput.dy = y;
mi.union.mouseInput.mouseData = data;
mi.union.mouseInput.dwFlags = intflags;
mi.union.mouseInput.time = 0;
mi.union.mouseInput.dwExtraInfo = new IntPtr(0);
if (NativeMethods.SendInput(1, ref mi, Marshal.SizeOf(mi)) == 0)
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
}
private static void NormalizeCoordinates(ref int x, ref int y)
{
int vScreenWidth = NativeMethods.GetSystemMetrics(NativeMethods.SMCxvirtualscreen);
int vScreenHeight = NativeMethods.GetSystemMetrics(NativeMethods.SMCyvirtualscreen);
int vScreenLeft = NativeMethods.GetSystemMetrics(NativeMethods.SMXvirtualscreen);
int vScreenTop = NativeMethods.GetSystemMetrics(NativeMethods.SMYvirtualscreen);
// Absolute input requires that input is in 'normalized' coords - with the entire
// desktop being (0,0)...(65536,65536). Need to convert input x,y coords to this
// first.
//
// In this normalized world, any pixel on the screen corresponds to a block of values
// of normalized coords - eg. on a 1024x768 screen,
// y pixel 0 corresponds to range 0 to 85.333,
// y pixel 1 corresponds to range 85.333 to 170.666,
// y pixel 2 correpsonds to range 170.666 to 256 - and so on.
// Doing basic scaling math - (x-top)*65536/Width - gets us the start of the range.
// However, because int math is used, this can end up being rounded into the wrong
// pixel. For example, if we wanted pixel 1, we'd get 85.333, but that comes out as
// 85 as an int, which falls into pixel 0's range - and that's where the pointer goes.
// To avoid this, we add on half-a-"screen pixel"'s worth of normalized coords - to
// push us into the middle of any given pixel's range - that's the 65536/(Width*2)
// part of the formula. So now pixel 1 maps to 85+42 = 127 - which is comfortably
// in the middle of that pixel's block.
// The key ting here is that unlike points in coordinate geometry, pixels take up
// space, so are often better treated like rectangles - and if you want to target
// a particular pixel, target its rectangle's midpoint, not its edge.
x = ((x - vScreenLeft) * 65536) / vScreenWidth + 65536 / (vScreenWidth * 2);
y = ((y - vScreenTop) * 65536) / vScreenHeight + 65536 / (vScreenHeight * 2);
}
}
/// <summary>
/// Exposes a simple interface to common keyboard operations, allowing the user to simulate keyboard input.
/// </summary>
/// <example>
/// The following code types "Hello world" with the specified casing,
/// and then types "hello, capitalized world" which will be in all caps because
/// the left shift key is being held down.
/// <code>
/**
Keyboard.Type("Hello world");
Keyboard.Press(Key.LeftShift);
Keyboard.Type("hello, capitalized world");
Keyboard.Release(Key.LeftShift);
*/
/// </code>
/// </example>
public static class KeyboardUtil
{
#region Public Members
/// <summary>
/// Presses down a key.
/// </summary>
/// <param name="key">The key to press.</param>
public static void Press(Key key)
{
SendKeyboardInput(key, true);
}
/// <summary>
/// Releases a key.
/// </summary>
/// <param name="key">The key to release.</param>
public static void Release(Key key)
{
SendKeyboardInput(key, false);
}
/// <summary>
/// Resets the system keyboard to a clean state.
/// </summary>
public static void Reset()
{
foreach (Key key in Enum.GetValues(typeof(Key)))
{
if (key != Key.None && (System.Windows.Input.Keyboard.GetKeyStates(key) & KeyStates.Down) > 0)
{
Release(key);
}
}
}
/// <summary>
/// Performs a press-and-release operation for the specified key, which is effectively equivallent to typing.
/// </summary>
/// <param name="key">The key to press.</param>
public static void Type(Key key)
{
Press(key);
Release(key);
}
/// <summary>
/// Types the specified text.
/// </summary>
/// <param name="text">The text to type.</param>
public static void Type(string text)
{
foreach (char c in text)
{
// We get the vKey value for the character via a Win32 API. We then use bit masks to pull the
// upper and lower bytes to get the shift state and key information. We then use WPF KeyInterop
// to go from the vKey key info into a System.Windows.Input.Key data structure. This work is
// necessary because Key doesn't distinguish between upper and lower case, so we have to wrap
// the key type inside a shift press/release if necessary.
int vKeyValue = NativeMethods.VkKeyScan(c);
bool keyIsShifted = (vKeyValue & NativeMethods.VKeyShiftMask) == NativeMethods.VKeyShiftMask;
Key key = KeyInterop.KeyFromVirtualKey(vKeyValue & NativeMethods.VKeyCharMask);
if (keyIsShifted)
{
Type(key, new Key[] { Key.LeftShift });
}
else
{
Type(key);
}
}
}
#endregion Public Members
#region Private Members
/// <summary>
/// Types a key while a set of modifier keys are being pressed. Modifer keys
/// are pressed in the order specified and released in reverse order.
/// </summary>
/// <param name="key">Key to type.</param>
/// <param name="modifierKeys">Set of keys to hold down with key is typed.</param>
private static void Type(Key key, Key[] modifierKeys)
{
foreach (Key modiferKey in modifierKeys)
{
Press(modiferKey);
}
Type(key);
foreach (Key modifierKey in modifierKeys.Reverse())
{
Release(modifierKey);
}
}
/// <summary>
/// Injects keyboard input into the system.
/// </summary>
/// <param name="key">Indicates the key pressed or released. Can be one of the constants defined in the Key enum.</param>
/// <param name="press">True to inject a key press, false to inject a key release.</param>
[PermissionSet(SecurityAction.Assert, Name = "FullTrust")]
private static void SendKeyboardInput(Key key, bool press)
{
PermissionSet permissions = new PermissionSet(PermissionState.Unrestricted);
permissions.Demand();
NativeMethods.INPUT ki = new NativeMethods.INPUT();
ki.type = NativeMethods.InputKeyboard;
ki.union.keyboardInput.wVk = (short)KeyInterop.VirtualKeyFromKey(key);
ki.union.keyboardInput.wScan = (short)NativeMethods.MapVirtualKey(ki.union.keyboardInput.wVk, 0);
int dwFlags = 0;
if (ki.union.keyboardInput.wScan > 0)
{
dwFlags |= NativeMethods.KeyeventfScancode;
}
if (!press)
{
dwFlags |= NativeMethods.KeyeventfKeyup;
}
ki.union.keyboardInput.dwFlags = dwFlags;
if (ExtendedKeys.Contains(key))
{
ki.union.keyboardInput.dwFlags |= NativeMethods.KeyeventfExtendedkey;
}
ki.union.keyboardInput.time = 0;
ki.union.keyboardInput.dwExtraInfo = new IntPtr(0);
if (NativeMethods.SendInput(1, ref ki, Marshal.SizeOf(ki)) == 0)
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
}
// From the SDK:
// The extended-key flag indicates whether the keystroke message originated from one of
// the additional keys on the enhanced keyboard. The extended keys consist of the ALT and
// CTRL keys on the right-hand side of the keyboard; the INS, DEL, HOME, END, PAGE UP,
// PAGE DOWN, and arrow keys in the clusters to the left of the numeric keypad; the NUM LOCK
// key; the BREAK (CTRL+PAUSE) key; the PRINT SCRN key; and the divide (/) and ENTER keys in
// the numeric keypad. The extended-key flag is set if the key is an extended key.
//
// - docs appear to be incorrect. Use of Spy++ indicates that break is not an extended key.
// Also, menu key and windows keys also appear to be extended.
private static readonly Key[] ExtendedKeys = new Key[] {
Key.RightAlt,
Key.RightCtrl,
Key.NumLock,
Key.Insert,
Key.Delete,
Key.Home,
Key.End,
Key.Prior,
Key.Next,
Key.Up,
Key.Down,
Key.Left,
Key.Right,
Key.Apps,
Key.RWin,
Key.LWin };
// Note that there are no distinct values for the following keys:
// numpad divide
// numpad enter
#endregion Private Members
}
#endregion Operate Mouse Keyboard
}

@ -56,25 +56,4 @@ namespace STranslate.Utils
_execute(parameter);
}
}
/// <summary>
/// 单例辅助类
/// </summary>
public abstract class SingletonMode<T> where T : class
{
public static T _Instance;
public static T Instance()
{
Type type = typeof(T);
lock (type)
{
if (SingletonMode<T>._Instance == null)
{
SingletonMode<T>._Instance = (Activator.CreateInstance(typeof(T), true) as T);
}
return SingletonMode<T>._Instance;
}
}
}
}

@ -27,7 +27,7 @@ namespace STranslate.ViewModel
config = ConfigUtil.ReadConfig(ConfigPath);
//复制翻译结果
CopyTranslateResultCmd = new RelayCommand((_) =>
CopyResultCmd = new RelayCommand((_) =>
{
return string.IsNullOrEmpty(OutputTxt) ? false : true;
}, (_) =>
@ -44,6 +44,8 @@ namespace STranslate.ViewModel
await Translate();
});
}
#region handle
public async Task Translate()
{
try
@ -68,9 +70,11 @@ namespace STranslate.ViewModel
OutputTxt = ex.Message;
}
}
#endregion
#region Params
public ICommand TranslateCmd { get; private set; }
public ICommand CopyTranslateResultCmd { get; private set; }
public ICommand CopyResultCmd { get; private set; }
private string _InputTxt;
public string InputTxt { get => _InputTxt; set => UpdateProperty(ref _InputTxt, value); }
@ -89,8 +93,6 @@ namespace STranslate.ViewModel
private string _OutputComboSelected;
public string OutputComboSelected { get => _OutputComboSelected; set => UpdateProperty(ref _OutputComboSelected, value); }
private static readonly MainVM _Instance = new MainVM();
public static MainVM Instance { get => _Instance; }
#endregion
}
}

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="HandyControl" version="3.4.0" targetFramework="net48" />
<package id="Newtonsoft.Json" version="13.0.2" targetFramework="net48" />
<package id="YamlDotNet" version="12.2.1" targetFramework="net48" />
<package id="HandyControl" version="3.4.0" targetFramework="net48" />
<package id="Newtonsoft.Json" version="13.0.2" targetFramework="net48" />
<package id="YamlDotNet" version="12.2.1" targetFramework="net48" />
</packages>
Loading…
Cancel
Save