using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Numerics; using System.Text; using System.Threading.Tasks; using Windows.ApplicationModel; using Windows.Foundation; using Windows.Storage; using Windows.UI; using Windows.UI.Input.Inking; using Windows.UI.Input.Inking.Analysis; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Input; using Windows.UI.Xaml.Media; namespace JpInkRecognizer.ViewModel { public class BaseViewModel : Observable { public int CanvasTextStartIndex { get; set; } = 0; /// /// inkAnalyzer /// InkAnalyzer inkAnalyzer; /// /// recoTimer /// DispatcherTimer recoTimer; private InkCanvas baseInkCanvas = null; private UIElement showCanvasTextBox = null; /// /// canvasTextStartIndex /// public int canvasTextStartIndex = 0; private int canvasTextLength = 0; private bool canvasChangeFlag = false; private bool textChangeFlag = false; public string allowProcess = WinAppConstant.StrProcessDenied; public Array WhiteListArray { get; set; } public static SolidColorBrush GetSolidColorBush(string hex) { hex = hex.Replace("#", string.Empty); bool existAlpha = hex.Length == 8; if (!existAlpha && hex.Length != 6) { throw new ArgumentException(); } int n = 0; byte a; if (existAlpha) { n = 2; a = (byte)ConvertHexToByte(hex, 0); } else { a = 0xFF; } var r = (byte)ConvertHexToByte(hex, n); var g = (byte)ConvertHexToByte(hex, n + 2); var b = (byte)ConvertHexToByte(hex, n + 4); return new SolidColorBrush(Color.FromArgb(a, r, g, b)); } #region sample public void InialInkCanvas(InkCanvas inkCanvas, UIElement textBox) { var type = textBox.GetType(); if (typeof(TextBox) == type) { showCanvasTextBox = textBox as TextBox; } else { showCanvasTextBox = textBox as RichEditBox; } this.baseInkCanvas = inkCanvas; inkAnalyzer = new InkAnalyzer(); recoTimer = new DispatcherTimer(); recoTimer.Interval = TimeSpan.FromMilliseconds(300); recoTimer.Tick += RecoTimer_Tick; canvasTextStartIndex = 0; this.canvasTextLength = 0; this.baseInkCanvas.InkPresenter.InputDeviceTypes = Windows.UI.Core.CoreInputDeviceTypes.Mouse | Windows.UI.Core.CoreInputDeviceTypes.Touch | Windows.UI.Core.CoreInputDeviceTypes.Pen; this.baseInkCanvas.InkPresenter.StrokeInput.StrokeStarted += StrokeInput_StrokeStarted; var attr = new InkDrawingAttributes { Color = Colors.Red, IgnorePressure = true, PenTip = PenTipShape.Rectangle, Size = new Size(4, 10), PenTipTransform = Matrix3x2.CreateRotation((float)(70 * Math.PI / 180)) }; this.baseInkCanvas.InkPresenter.UpdateDefaultDrawingAttributes(attr); } /// /// RecoTimer_Tick /// /// sender /// object private async void RecoTimer_Tick(object sender, object e) { recoTimer.Stop(); if (!inkAnalyzer.IsAnalyzing && WinAppConstant.StrProcessAllow.Equals(this.allowProcess)) { this.allowProcess = WinAppConstant.StrProcessDenied; InkAnalysisResult result = await inkAnalyzer.AnalyzeAsync(); if (result.Status == InkAnalysisStatus.Updated) { string tempRecognizedText = await GetRecognitionText(); string recognizedText = ToSBC(tempRecognizedText); inkAnalyzer.ClearDataForAllStrokes(); await ShowTextBoxOfHandWrite(recognizedText.ToString()); } this.allowProcess = WinAppConstant.StrProcessAllow; } else { recoTimer.Start(); } } /// /// Convert string from half character to full character /// /// string to convert to full angle character /// full angle character private string ToSBC(string input) { char[] c = input.ToCharArray(); for (int i = 0; i < c.Length; i++) { if (c[i] == 32) { c[i] = (char)12288; continue; } //// a-z,1-0,A-Z if (c[i] > 32 && c[i] < 127) c[i] = (char)(c[i] + 65248); } return new string(c); } /// /// StrokeInput_StrokeStarted /// /// /// private void StrokeInput_StrokeStarted(InkStrokeInput sender, Windows.UI.Core.PointerEventArgs args) { recoTimer?.Stop(); } public async Task GetRecognitionText() { IReadOnlyList currentStrokes = this.baseInkCanvas.InkPresenter.StrokeContainer.GetStrokes(); if (currentStrokes.Count > 0) { InkRecognizerContainer inkRecognizerContainer = new InkRecognizerContainer(); if (inkRecognizerContainer != null) { var ink = inkRecognizerContainer.GetRecognizers(); foreach (var item in ink) { if ("Microsoft 日本語手書き認識エンジン".Equals(item.Name)) { inkRecognizerContainer.SetDefaultRecognizer(item); } } IReadOnlyList recognitionResults = await inkRecognizerContainer.RecognizeAsync(this.baseInkCanvas.InkPresenter.StrokeContainer, InkRecognitionTarget.All); if (recognitionResults.Count > 0) { if (recognitionResults.Count > 0) { foreach (var result in recognitionResults) { IReadOnlyList candidates = result.GetTextCandidates(); return candidates[0]; } } } } } return string.Empty; } public async Task ShowTextBoxOfHandWrite(string recognitionText) { var type = showCanvasTextBox.GetType(); if (type == typeof(TextBox)) { TextBox _showCanvasTextBox = showCanvasTextBox as TextBox; this.canvasTextStartIndex = _showCanvasTextBox.SelectionStart - this.canvasTextLength; if (_showCanvasTextBox.SelectionLength <= 0) { string putString1 = _showCanvasTextBox.Text.Substring(0, this.canvasTextStartIndex); string putString2 = _showCanvasTextBox.Text.Substring(this.canvasTextStartIndex + this.canvasTextLength); _showCanvasTextBox.Text = putString1 + recognitionText + putString2; _showCanvasTextBox.SelectionStart = this.canvasTextStartIndex + recognitionText.Length; } else { string putString1 = _showCanvasTextBox.Text.Substring(0, canvasTextStartIndex); string putString2 = _showCanvasTextBox.Text.Substring(canvasTextStartIndex + _showCanvasTextBox.SelectionLength); _showCanvasTextBox.Text = putString1 + recognitionText + putString2; _showCanvasTextBox.SelectionStart = putString1.Length + recognitionText.Length; } this.canvasChangeFlag = true; _showCanvasTextBox.Focus(FocusState.Programmatic); _showCanvasTextBox.Background = new SolidColorBrush(Color.FromArgb(255, 140, 180, 228)); _showCanvasTextBox.SelectionLength = 0; canvasTextLength = recognitionText.Length; } else { RichEditBox _showCanvasTextBox = showCanvasTextBox as RichEditBox; canvasTextStartIndex = _showCanvasTextBox.Document.Selection.StartPosition; string textStr = GetTextFromRichEditBox(_showCanvasTextBox); int tempLength = canvasTextLength != 0 ? canvasTextLength : _showCanvasTextBox.Document.Selection.Length; if (tempLength <= 0) { string putString1 = textStr.Substring(0, canvasTextStartIndex); string putString2 = textStr.Substring(canvasTextStartIndex); string allText = putString1 + recognitionText + putString2; _showCanvasTextBox.Document.SetText(Windows.UI.Text.TextSetOptions.None, allText); await ChangeTextColor(_showCanvasTextBox, allText, Colors.Red); _showCanvasTextBox.Document.Selection.StartPosition = canvasTextStartIndex + recognitionText.Length; } else { string putString1 = textStr.Substring(0, canvasTextStartIndex - tempLength); string putString2 = textStr.Substring(canvasTextStartIndex); string allText = putString1 + recognitionText + putString2; _showCanvasTextBox.Document.SetText(Windows.UI.Text.TextSetOptions.None, allText); await ChangeTextColor(_showCanvasTextBox, allText, Colors.Red); _showCanvasTextBox.Document.Selection.StartPosition = canvasTextStartIndex - tempLength + recognitionText.Length; } this.canvasChangeFlag = true; _showCanvasTextBox.Focus(FocusState.Programmatic); _showCanvasTextBox.Background = GetSolidColorBush("#F8B500"); canvasTextLength = recognitionText.Length; } } /// /// Get Text from RichEditBox /// /// the target richeditbox /// the text of the richEditBox private string GetTextFromRichEditBox(RichEditBox richEditBox) { string temp; richEditBox.Document.GetText(Windows.UI.Text.TextGetOptions.None, out temp); var range = richEditBox.Document.GetRange(0, temp.Length - 1); string textStr; range.GetText(Windows.UI.Text.TextGetOptions.None, out textStr); return textStr; } public async Task ChangeTextColor(RichEditBox richEditBox, string s, Color color) { var temp = richEditBox.Document.GetRange(0, s.Length); temp.CharacterFormat.BackgroundColor = Colors.Transparent; ArrayList indexarray = await matchstring(s); int tempPosition = richEditBox.Document.Selection.StartPosition; foreach (int x in indexarray) { var tempRange = richEditBox.Document.GetRange(x, x + 1); tempRange.CharacterFormat.BackgroundColor = Colors.Red; richEditBox.Document.Selection.StartPosition = x + 1; } richEditBox.Document.Selection.StartPosition = tempPosition; richEditBox.Document.Selection.EndPosition = tempPosition; } public async Task matchstring(string document) { if (WhiteListArray == null) { StorageFolder assetsStorageFolder = await Package.Current.InstalledLocation.GetFolderAsync("Assets"); StorageFile file = await assetsStorageFolder.GetFileAsync("inputwhitelist.txt"); IList resultlist = await FileIO.ReadLinesAsync(file); WhiteListArray = resultlist.ToArray(); } char[] charlist = document.ToCharArray(); ArrayList indexlist = new ArrayList(); for (int i = 0; i < document.Length; i++) { int value = Convert.ToInt32(charlist[i]); string hexoutput = String.Format("{0:X}", value); int tmp = Array.IndexOf(WhiteListArray, hexoutput); if (tmp == -1) { indexlist.Add(i); } } await Task.CompletedTask; return indexlist; } public void ClearCanvas() { // Clear Canvas this.baseInkCanvas.InkPresenter.StrokeContainer.Clear(); canvasTextLength = 0; var type = showCanvasTextBox.GetType(); if (type == typeof(TextBox)) { var _showCanvasTextBox = showCanvasTextBox as TextBox; _showCanvasTextBox.Focus(FocusState.Programmatic); } else { var _showCanvasTextBox = showCanvasTextBox as RichEditBox; _showCanvasTextBox.Focus(FocusState.Programmatic); } } public void DeleteOneWord() { var type = showCanvasTextBox.GetType(); if (type == typeof(TextBox)) { // Clear Canvas this.baseInkCanvas.InkPresenter.StrokeContainer.Clear(); canvasTextLength = 0; var _showCanvasTextBox = showCanvasTextBox as TextBox; if (_showCanvasTextBox.Text.Length > 0) { int selectPos = _showCanvasTextBox.SelectionStart; if (_showCanvasTextBox.SelectionLength > 0) { string putString1 = _showCanvasTextBox.Text.Substring(0, selectPos); string putString2 = _showCanvasTextBox.Text.Substring(selectPos + _showCanvasTextBox.SelectionLength); _showCanvasTextBox.Text = putString1 + putString2; _showCanvasTextBox.Focus(FocusState.Programmatic); _showCanvasTextBox.SelectionStart = putString1.Length; _showCanvasTextBox.SelectionLength = 0; } else { if (selectPos <= 0) { return; } string putString1 = _showCanvasTextBox.Text.Substring(0, selectPos - 1); string putString2 = string.Empty; putString2 += _showCanvasTextBox.Text.Substring(selectPos); _showCanvasTextBox.Text = putString1 + putString2; _showCanvasTextBox.Focus(FocusState.Programmatic); _showCanvasTextBox.SelectionStart = selectPos - 1; _showCanvasTextBox.SelectionLength = 0; } } } else { this.baseInkCanvas.InkPresenter.StrokeContainer.Clear(); var _showCanvasTextBox = showCanvasTextBox as RichEditBox; string textStr = GetTextFromRichEditBox(_showCanvasTextBox); int tempLength = canvasTextLength != 0 ? canvasTextLength : _showCanvasTextBox.Document.Selection.Length; canvasTextLength = 0; if (textStr.Length > 0) { int selectPos = _showCanvasTextBox.Document.Selection.StartPosition; if (selectPos <= 0) { return; } string putString1 = textStr.Substring(0, selectPos - 1); string putString2 = string.Empty; putString2 += textStr.Substring(selectPos); _showCanvasTextBox.Document.SetText(Windows.UI.Text.TextSetOptions.None, putString1 + putString2); _showCanvasTextBox.Focus(FocusState.Programmatic); _showCanvasTextBox.Document.Selection.StartPosition = selectPos - 1; } } } public void DeleteAllWord() { // clear canvas and result this.baseInkCanvas.InkPresenter.StrokeContainer.Clear(); canvasTextLength = 0; var type = showCanvasTextBox.GetType(); if (type == typeof(TextBox)) { var _showCanvasTextBox = showCanvasTextBox as TextBox; _showCanvasTextBox.Text = string.Empty; } else { var _showCanvasTextBox = showCanvasTextBox as RichEditBox; _showCanvasTextBox.Document.SetText(Windows.UI.Text.TextSetOptions.None, string.Empty); } } public void Blank() { var type = showCanvasTextBox.GetType(); if (type == typeof(TextBox)) { var _showCanvasTextBox = showCanvasTextBox as TextBox; //// clear canvas and result this.baseInkCanvas.InkPresenter.StrokeContainer.Clear(); canvasTextLength = 0; int selectPos = _showCanvasTextBox.SelectionStart; if (_showCanvasTextBox.SelectionLength > 0) { string putString1 = _showCanvasTextBox.Text.Substring(0, selectPos); string putString2 = _showCanvasTextBox.Text.Substring(selectPos + _showCanvasTextBox.SelectionLength); _showCanvasTextBox.Text = putString1 + " " + putString2; _showCanvasTextBox.Focus(FocusState.Programmatic); _showCanvasTextBox.SelectionStart = selectPos + 1; _showCanvasTextBox.SelectionLength = 0; } else { _showCanvasTextBox.Text = _showCanvasTextBox.Text.Insert(selectPos, " "); _showCanvasTextBox.Focus(FocusState.Programmatic); _showCanvasTextBox.SelectionStart = selectPos + 1; _showCanvasTextBox.SelectionLength = 0; } } else { // clear canvas and result this.baseInkCanvas.InkPresenter.StrokeContainer.Clear(); canvasTextLength = 0; var _showCanvasTextBox = showCanvasTextBox as RichEditBox; string textStr = GetTextFromRichEditBox(_showCanvasTextBox); int selectPos = _showCanvasTextBox.Document.Selection.StartPosition; int tempLength = canvasTextLength != 0 ? canvasTextLength : _showCanvasTextBox.Document.Selection.Length; if (tempLength > 0) { string putString1 = textStr.Substring(0, selectPos); string putString2 = textStr.Substring(selectPos + tempLength); _showCanvasTextBox.Document.SetText(Windows.UI.Text.TextSetOptions.None, putString1 + " " + putString2); _showCanvasTextBox.Focus(FocusState.Programmatic); _showCanvasTextBox.Document.Selection.StartPosition = selectPos + 1; } else { _showCanvasTextBox.Document.SetText(Windows.UI.Text.TextSetOptions.None, textStr.Insert(selectPos, " ")); _showCanvasTextBox.Focus(FocusState.Programmatic); _showCanvasTextBox.Document.Selection.StartPosition = selectPos + 1; } } } public void InkPresenter_StrokesCollected(InkPresenter sender, InkStrokesCollectedEventArgs args) { if (this.allowProcess == WinAppConstant.StrProcessDenied) { return; } else { this.allowProcess = WinAppConstant.StrProcessDenied; recoTimer?.Stop(); foreach (var stroke in args.Strokes) { var rect = stroke.BoundingRect; inkAnalyzer.AddDataForStroke(stroke); inkAnalyzer.SetStrokeDataKind(stroke.Id, InkAnalysisStrokeKind.Writing); } recoTimer?.Start(); this.allowProcess = WinAppConstant.StrProcessAllow; } } public void TextBox_SelectionChanged(object sender, RoutedEventArgs e) { if (!this.canvasChangeFlag && !this.textChangeFlag) { this.ClearCanvas(); } else { this.canvasChangeFlag = false; this.textChangeFlag = false; } } public void TextBox_TextChanged(object sender, TextChangedEventArgs e) { this.textChangeFlag = true; } public void TextBox_OnPointerPressed(object sender, PointerRoutedEventArgs e) { this.ClearCanvas(); } private static uint ConvertHexToByte(string hex, int n) { return System.Convert.ToUInt32(hex.Substring(n, 2), 16); } #endregion public void Tbx_ContextMenuOpening(object sender, ContextMenuEventArgs e) { e.Handled = true; } } }