Files
mpv.net/src/MpvNet.Windows/WPF/LearnWindow.xaml.cs

292 lines
8.4 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.Runtime.InteropServices;
using System.Text;
using System.Windows;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Forms;
using MpvNet.Help;
using MpvNet.Windows.UI;
namespace MpvNet.Windows;
public partial class LearnWindow : Window
{
public Binding? InputItem { get; set; }
string NewKey = "";
uint MAPVK_VK_TO_VSC = 0;
int VK_MENU = 0x12;
int VK_LMENU = 0xA4;
int VK_RMENU = 0xA5;
int VK_CONTROL = 0x11;
int VK_LCONTROL = 0xA2;
int VK_RCONTROL = 0xA3;
bool BlockMBTN_LEFT;
bool BlockMBTN_RIGHT;
public LearnWindow()
{
InitializeComponent();
DataContext = this;
}
public Theme? Theme => Theme.Current;
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern short GetKeyState(int keyCode);
[DllImport("user32.dll")]
static extern uint MapVirtualKey(uint uCode, uint uMapType);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
static extern int ToUnicode(uint wVirtKey, uint wScanCode, byte[] lpKeyState,
StringBuilder pwszBuff, int cchBuff, uint wFlags);
[DllImport("user32.dll")]
static extern bool GetKeyboardState(byte[] lpKeyState);
string ToUnicode(uint vk, ref bool firstEmpty)
{
byte[] keys = new byte[256];
if (!GetKeyboardState(keys))
return "";
if ((keys[VK_CONTROL] & 0x80) != 0 && (keys[VK_MENU] & 0x80) == 0)
keys[VK_LCONTROL] = keys[VK_RCONTROL] = keys[VK_CONTROL] = 0;
uint scanCode = MapVirtualKey(vk, MAPVK_VK_TO_VSC);
string ret = ToUnicode(vk, scanCode, keys);
firstEmpty = ret == "";
if (ret.Length == 1 && ret[0] < 32)
return "";
if (firstEmpty)
{
keys[VK_LCONTROL] = keys[VK_RCONTROL] = keys[VK_CONTROL] = 0;
keys[VK_LMENU] = keys[VK_RMENU] = keys[VK_MENU] = 0;
ret = ToUnicode(vk, scanCode, keys);
}
return ret;
}
public string ToUnicode(uint vk, uint scanCode, byte[] keys)
{
StringBuilder sb = new StringBuilder(10);
ToUnicode(vk, scanCode, keys, sb, sb.Capacity, 0);
return sb.ToString();
}
IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
Message m = new Message();
m.HWnd = hwnd;
m.Msg = msg;
m.WParam = wParam;
m.LParam = lParam;
ProcessKeyEventArgs(ref m);
return m.Result;
}
void OnKeyDown(uint vk)
{
bool firstEmpty = false;
Keys key = (Keys)vk;
if (key == Keys.ControlKey || key == Keys.ShiftKey ||
key == Keys.Menu || key == Keys.None)
return;
string text = ToUnicode(vk, ref firstEmpty);
if ((int)key > 111 && (int)key < 136)
text = "F" + ((int)key - 111);
if ((int)key > 95 && (int)key < 106)
text = "KP" + ((int)key - 96);
switch (text)
{
case "#": text = "SHARP"; break;
case "´´": text = "´"; break;
case "``": text = "`"; break;
case "^^": text = "^"; break;
}
switch (key)
{
case Keys.Left: text = "Left"; break;
case Keys.Up: text = "Up"; break;
case Keys.Right: text = "Right"; break;
case Keys.Down: text = "Down"; break;
case Keys.Space: text = "Space"; break;
case Keys.Enter: text = "Enter"; break;
case Keys.Tab: text = "Tab"; break;
case Keys.Back: text = "BS"; break;
case Keys.Delete: text = "Del"; break;
case Keys.Insert: text = "Ins"; break;
case Keys.Home: text = "Home"; break;
case Keys.End: text = "End"; break;
case Keys.PageUp: text = "PGUP"; break;
case Keys.PageDown: text = "PGDWN"; break;
case Keys.Escape: text = "Esc"; break;
case Keys.Sleep: text = "Sleep"; break;
case Keys.Cancel: text = "Cancel"; break;
case Keys.PrintScreen: text = "Print"; break;
case Keys.BrowserFavorites: text = "Favorites"; break;
case Keys.BrowserSearch: text = "Search"; break;
case Keys.BrowserHome: text = "Homepage"; break;
case Keys.LaunchMail: text = "Mail"; break;
case Keys.Play: text = "Play"; break;
case Keys.Pause: text = "Pause"; break;
case Keys.MediaPlayPause: text = "PlayPause"; break;
case Keys.MediaStop: text = "Stop"; break;
case Keys.MediaNextTrack: text = "Next"; break;
case Keys.MediaPreviousTrack: text = "Prev"; break;
case Keys.VolumeUp:
case Keys.VolumeDown:
case Keys.VolumeMute:
text = ""; break;
}
bool isAlt = GetKeyState(18) < 0;
bool isShift = GetKeyState(16) < 0;
bool isCtrl = GetKeyState(17) < 0;
bool isLetter = (int)key > 64 && (int)key < 91;
if (isLetter && isShift)
text = text.ToUpper();
string keyString = ToUnicode(vk, ref firstEmpty);
if (isAlt && !isCtrl)
text = "Alt+" + text;
if (isShift && keyString == "")
text = "Shift+" + text;
if (isCtrl && isAlt && firstEmpty)
text = "Ctrl+Alt+" + text;
else if (isCtrl && !(keyString != "" && isCtrl && isAlt))
text = "Ctrl+" + text;
if (!string.IsNullOrEmpty(text))
SetKey(text);
}
void SetKey(string? key)
{
NewKey = key!;
MenuTextBlock.Text = InputItem?.Path;
KeyTextBlock.Text = key;
}
void ProcessKeyEventArgs(ref Message m)
{
int WM_KEYDOWN = 0x100;
int WM_SYSKEYDOWN = 0x104;
int WM_APPCOMMAND = 0x319;
if (m.Msg == WM_KEYDOWN || m.Msg == WM_SYSKEYDOWN)
OnKeyDown((uint)m.WParam.ToInt64());
else if (m.Msg == WM_APPCOMMAND)
{
string? value = MpvHelp.WM_APPCOMMAND_to_mpv_key((int)(m.LParam.ToInt64() >> 16 & ~0xf000));
if (value != null)
SetKey(value);
}
}
void Window_Loaded(object sender, RoutedEventArgs e)
{
HwndSource source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
source.AddHook(new HwndSourceHook(WndProc));
SetKey(InputItem?.Input);
}
void ConfirmButton_Click(object sender, RoutedEventArgs e)
{
InputItem!.Input = NewKey;
Close();
}
void ClearButton_Click(object sender, RoutedEventArgs e)
{
InputItem!.Input = "";
Close();
}
void Window_MouseWheel(object sender, MouseWheelEventArgs e)
{
if (e.Delta > 0)
SetKey("WHEEL_UP");
else
SetKey("WHEEL_DOWN");
}
void Window_MouseUp(object sender, MouseButtonEventArgs e)
{
switch (e.ChangedButton)
{
case MouseButton.Left:
if (BlockMBTN_LEFT)
BlockMBTN_LEFT = false;
else
SetKey("MBTN_LEFT");
break;
case MouseButton.Right:
if (BlockMBTN_RIGHT)
BlockMBTN_RIGHT = false;
else
SetKey("MBTN_RIGHT");
break;
case MouseButton.Middle:
SetKey("MBTN_MID");
break;
case MouseButton.XButton1:
SetKey("MBTN_BACK");
break;
case MouseButton.XButton2:
SetKey("MBTN_FORWARD");
break;
}
}
void Window_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Left)
{
SetKey("MBTN_LEFT_DBL");
BlockMBTN_LEFT = true;
}
if (e.ChangedButton == MouseButton.Right)
{
SetKey("MBTN_RIGHT_DBL");
BlockMBTN_RIGHT = true;
}
}
void Window_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
if (e.Key == Key.Tab)
{
OnKeyDown((uint)Keys.Tab);
e.Handled = true;
}
}
}