diff --git a/Text-Grab/App.xaml.cs b/Text-Grab/App.xaml.cs
index 662c6703..f84fd237 100644
--- a/Text-Grab/App.xaml.cs
+++ b/Text-Grab/App.xaml.cs
@@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
+using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
@@ -234,6 +235,9 @@ private void appExit(object sender, ExitEventArgs e)
private async void appStartup(object sender, StartupEventArgs e)
{
+ if (checkForAdminWindow(e.Args))
+ return;
+
NumberOfRunningInstances = Process.GetProcessesByName("Text-Grab").Length;
Current.DispatcherUnhandledException += CurrentDispatcherUnhandledException;
@@ -272,6 +276,23 @@ private async void appStartup(object sender, StartupEventArgs e)
DefaultLaunch();
}
+ private bool checkForAdminWindow(string[] args)
+ {
+ WindowCollection allWindows = Current.Windows;
+
+ foreach (Window window in allWindows)
+ if (window is AdminWindow)
+ return true;
+
+ if (args.Length == 0 || !args.Contains("admin"))
+ return false;
+
+ AdminWindow aw = new();
+ aw.Show();
+
+ return true;
+ }
+
private void CurrentDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
// unhandled exceptions thrown from UI thread
diff --git a/Text-Grab/Pages/LanguageSettings.xaml b/Text-Grab/Pages/LanguageSettings.xaml
index a4b64540..d134975e 100644
--- a/Text-Grab/Pages/LanguageSettings.xaml
+++ b/Text-Grab/Pages/LanguageSettings.xaml
@@ -25,6 +25,14 @@
Click="HyperlinkButton_Click"
Content="How to install OCR languages with PowerShell"
NavigateUri="https://learn.microsoft.com/en-us/windows/powertoys/text-extractor#how-to-query-for-ocr-language-packs" />
+
+
+
-/// Interaction logic for LanguageSettings.xaml
-///
public partial class LanguageSettings : Page
{
private readonly Settings DefaultSettings = AppUtilities.TextGrabSettings;
@@ -47,7 +44,7 @@ private async void Page_Loaded(object sender, RoutedEventArgs e)
private void LoadWindowsLanguages()
{
WindowsLanguagesListView.Items.Clear();
- List possibleOCRLanguages = OcrEngine.AvailableRecognizerLanguages.ToList();
+ List possibleOCRLanguages = [.. OcrEngine.AvailableRecognizerLanguages];
foreach (Language language in possibleOCRLanguages)
WindowsLanguagesListView.Items.Add(language);
}
@@ -155,4 +152,44 @@ private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e
Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri) { UseShellExecute = true });
e.Handled = true;
}
+
+ private void InstalWindowsLangButton_Click(object sender, RoutedEventArgs e)
+ {
+ if (AppContext.BaseDirectory is not string exeDir)
+ return;
+
+ string exePath = Path.Combine(exeDir, "Text-Grab.exe");
+
+ ProcessStartInfo startInfo = new()
+ {
+ UseShellExecute = true,
+ WorkingDirectory = Environment.CurrentDirectory,
+ FileName = exePath,
+ Verb = "runas",
+ Arguments = "admin",
+ WindowStyle = ProcessWindowStyle.Normal
+ };
+
+ try
+ {
+ Process? process = Process.Start(startInfo);
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show(ex.Message);
+ }
+ }
+}
+
+
+public record LangListItem
+{
+ public string RightPart { get; set; } = string.Empty;
+
+ public string LeftPart { get; set; } = string.Empty;
+
+ public override string ToString()
+ {
+ return string.Join(' ', [LeftPart, RightPart]);
+ }
}
diff --git a/Text-Grab/Text-Grab.csproj b/Text-Grab/Text-Grab.csproj
index 6ccd2424..4d3afbf5 100644
--- a/Text-Grab/Text-Grab.csproj
+++ b/Text-Grab/Text-Grab.csproj
@@ -71,6 +71,7 @@
+
diff --git a/Text-Grab/Utilities/WindowsLanguageUtilities.cs b/Text-Grab/Utilities/WindowsLanguageUtilities.cs
new file mode 100644
index 00000000..c6abeaeb
--- /dev/null
+++ b/Text-Grab/Utilities/WindowsLanguageUtilities.cs
@@ -0,0 +1,58 @@
+namespace Text_Grab.Utilities;
+public class WindowsLanguageUtilities
+{
+ public static string PowerShellCommandForInstallingWithTag(string languageTag)
+ {
+ // $Capability = Get-WindowsCapability -Online | Where-Object { $_.Name -Like 'Language.OCR*en-US*' }
+ return $"$Capability = Get-WindowsCapability -Online | Where-Object {{ $_.Name -Like 'Language.OCR*{languageTag}*' }}; $Capability | Add-WindowsCapability -Online";
+ }
+
+ public static string DismLanguageCommand(string languageTag)
+ {
+ return $"Language.OCR~~~{languageTag}";
+ }
+
+ public static string PowerShellCommandForUninstallingWithTag(string languageTag)
+ {
+ // $Capability = Get-WindowsCapability -Online | Where-Object { $_.Name -Like 'Language.OCR*en-US*' }
+ return $"$Capability = Get-WindowsCapability -Online | Where-Object {{ $_.Name -Like 'Language.OCR*{languageTag}*' }}; $Capability | Remove-WindowsCapability -Online";
+ }
+
+ public static readonly string[] AllLanguages = [
+ "ar-SA",
+ "bg-BG",
+ "bs-LATN-BA",
+ "cs-CZ",
+ "da-DK",
+ "de-DE",
+ "el-GR",
+ "en-GB",
+ "en-US",
+ "es-ES",
+ "es-MX",
+ "fi-FI",
+ "fr-CA",
+ "fr-FR",
+ "hr-HR",
+ "hu-HU",
+ "it-IT",
+ "ja-JP",
+ "ko-KR",
+ "nb-NO",
+ "nl-NL",
+ "pl-PL",
+ "pt-BR",
+ "pt-PT",
+ "ro-RO",
+ "ru-RU",
+ "sk-SK",
+ "sl-SI",
+ "sr-CYRL-RS",
+ "sr-LATN-RS",
+ "sv-SE",
+ "tr-TR",
+ "zh-CN",
+ "zh-HK",
+ "zh-TW",
+ ];
+}
diff --git a/Text-Grab/Views/AdminWindow.xaml b/Text-Grab/Views/AdminWindow.xaml
new file mode 100644
index 00000000..044b2c39
--- /dev/null
+++ b/Text-Grab/Views/AdminWindow.xaml
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Text-Grab/Views/AdminWindow.xaml.cs b/Text-Grab/Views/AdminWindow.xaml.cs
new file mode 100644
index 00000000..5ff5eacb
--- /dev/null
+++ b/Text-Grab/Views/AdminWindow.xaml.cs
@@ -0,0 +1,98 @@
+using Microsoft.Dism;
+using System;
+using System.Globalization;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows;
+using Text_Grab.Pages;
+using Text_Grab.Utilities;
+
+namespace Text_Grab.Views;
+
+public partial class AdminWindow : Wpf.Ui.Controls.FluentWindow
+{
+ public AdminWindow()
+ {
+ InitializeComponent();
+
+ AllWindowsLanguagesComboBox.Items.Clear();
+ foreach (string textName in WindowsLanguageUtilities.AllLanguages)
+ {
+ CultureInfo languageCulture = new(textName);
+ string paddedTextName = textName.PadRight(12);
+ LangListItem langListItem = new()
+ {
+ LeftPart = paddedTextName,
+ RightPart = languageCulture.DisplayName
+ };
+ AllWindowsLanguagesComboBox.Items.Add(langListItem);
+ }
+
+ DismApi.Initialize(DismLogLevel.LogErrorsWarnings);
+ }
+
+ private void Window_Closed(object sender, EventArgs e)
+ {
+ DismApi.Shutdown();
+ Application.Current.Shutdown();
+ }
+
+ private async void InstalWindowsLangButton_Click(object sender, RoutedEventArgs e)
+ {
+ if (AllWindowsLanguagesComboBox.SelectedItem is not LangListItem pickedLanguageFile)
+ return;
+
+ using DismSession session = DismApi.OpenOnlineSession();
+
+ DismCapability? langToInstall = DismApi.GetCapabilities(session).FirstOrDefault(cap => cap.Name.Contains(pickedLanguageFile.LeftPart.Trim()));
+
+ if (langToInstall is null)
+ {
+ foreach (DismCapability cap in DismApi.GetCapabilities(session))
+ if (cap.Name.Contains("Language.OCR~~~"))
+ {
+ DismOutputTextBlock.Text += $"{Environment.NewLine}Dism capability: {cap.Name}";
+
+ if (cap.Name.Contains(pickedLanguageFile.LeftPart))
+ DismOutputTextBlock.Text += $"<--- Found {pickedLanguageFile.LeftPart}";
+ }
+
+ DismOutputTextBlock.Text += $"{Environment.NewLine}Language: {pickedLanguageFile.LeftPart} not found.";
+ return;
+ }
+
+ DismProgressBar.Visibility = Visibility.Visible;
+
+ DismProgressCallback progressCallback = new(progress =>
+ {
+ DismProgressBar.Maximum = progress.Total;
+ DismProgressBar.Value = progress.Current;
+ });
+
+ await Task.Run(() =>
+ {
+ DismApi.AddCapability(session, langToInstall.Name, false, null, progressCallback, null);
+ });
+
+ DismProgressBar.Visibility = Visibility.Collapsed;
+ }
+
+ private void LoadLanguages_Click(object sender, RoutedEventArgs e)
+ {
+ using DismSession session = DismApi.OpenOnlineSession();
+
+ var caps = DismApi.GetCapabilities(session);
+
+ foreach (DismCapability cap in DismApi.GetCapabilities(session))
+ {
+ string capName = cap.Name;
+ if (!capName.StartsWith("Language.OCR~~~"))
+ continue;
+ if (cap.State != DismPackageFeatureState.Installed)
+ continue;
+ string localeName = capName["Language.OCR~~~".Length..capName.LastIndexOf('~')];
+ CultureInfo culture = new(localeName);
+ DismOutputTextBlock.Text += $"{Environment.NewLine}{localeName} - {culture.DisplayName} - {capName}";
+ }
+ }
+}
diff --git a/Text-Grab/Views/GrabFrame.xaml b/Text-Grab/Views/GrabFrame.xaml
index d276ba4f..71187e2a 100644
--- a/Text-Grab/Views/GrabFrame.xaml
+++ b/Text-Grab/Views/GrabFrame.xaml
@@ -130,7 +130,9 @@
x:Name="IsTopmostMenuItem"
Header="Keep Grab Frame On Top"
IsCheckable="True"
- IsChecked="{Binding Topmost, ElementName=GrabFrameWindow, Mode=TwoWay}" />
+ IsChecked="{Binding Topmost,
+ ElementName=GrabFrameWindow,
+ Mode=TwoWay}" />
+ IsChecked="{Binding IsChecked,
+ ElementName=FreezeToggleButton,
+ Mode=TwoWay}" />
+ IsChecked="{Binding IsChecked,
+ ElementName=TableToggleButton,
+ Mode=TwoWay}" />
+ IsChecked="{Binding IsChecked,
+ ElementName=EditToggleButton,
+ Mode=TwoWay}" />
+ IsChecked="{Binding IsChecked,
+ ElementName=EditTextToggleButton,
+ Mode=TwoWay}" />
+ Visibility="{Binding Visibility,
+ ElementName=SearchBox,
+ Mode=OneWay}" />