Agregada la funcion --Menu para poder seleccionar la opcion a realizar dinamicamente.
This commit is contained in:
parent
5c6706aad1
commit
28e7df02ae
107
App.xaml.cs
107
App.xaml.cs
|
@ -25,66 +25,91 @@ namespace GTPCorrgir
|
|||
|
||||
KeyboardHelper pasteLogic = new KeyboardHelper();
|
||||
|
||||
private Window _mainWindow;
|
||||
|
||||
protected override async void OnStartup(StartupEventArgs e)
|
||||
{
|
||||
ShutdownMode = ShutdownMode.OnExplicitShutdown; // Añade esta línea
|
||||
base.OnStartup(e);
|
||||
_cancellationTokenSource = new CancellationTokenSource();
|
||||
|
||||
try
|
||||
{
|
||||
pasteLogic.SaveCurrentWindow();
|
||||
|
||||
if (Opciones.Instance.modo == Opciones.modoDeUso.OCRaTexto)
|
||||
if (Opciones.Instance.modo == Opciones.modoDeUso.Menu)
|
||||
{
|
||||
var captureWindow = new ScreenCaptureWindow();
|
||||
captureWindow.Show();
|
||||
_mainWindow = new ContextMenuWindow();
|
||||
(_mainWindow as ContextMenuWindow).Closed += async (s, args) =>
|
||||
{
|
||||
if (Opciones.Instance.modo != Opciones.modoDeUso.Menu)
|
||||
{
|
||||
await InitializeSelectedMode();
|
||||
}
|
||||
else
|
||||
{
|
||||
Application.Current.Shutdown();
|
||||
}
|
||||
};
|
||||
_mainWindow.Show();
|
||||
}
|
||||
else if (Opciones.Instance.modo == Opciones.modoDeUso.Chat)
|
||||
else
|
||||
{
|
||||
var chatWindows = new Chat(GTP);
|
||||
chatWindows.Show();
|
||||
}
|
||||
else {
|
||||
|
||||
if (Opciones.Instance.AutoCopy)
|
||||
{
|
||||
await pasteLogic.AutoCopyFromActiveWindow();
|
||||
}
|
||||
|
||||
if (System.Windows.Clipboard.ContainsText())
|
||||
{
|
||||
GTP.TextoACorregir = await ClipboardHelper.GetText();
|
||||
}
|
||||
if (string.IsNullOrEmpty(GTP.TextoACorregir))
|
||||
{
|
||||
GTP.Log.Log("No hay texto en el portapapeles");
|
||||
ShowCustomNotification("Error", "No hay texto para procesar");
|
||||
Application.Current.Shutdown();
|
||||
return;
|
||||
}
|
||||
if (Opciones.Instance.modo == Opciones.modoDeUso.Corregir ||
|
||||
Opciones.Instance.modo == Opciones.modoDeUso.Ortografia)
|
||||
{
|
||||
GTP.Log.Log("Iniciando proceso de corrección");
|
||||
stopwatch.Start();
|
||||
|
||||
ShowCustomNotification("Espera", $"Corrigiendo texto con {Opciones.Instance.nombreDeLLM()}...");
|
||||
IniciarCronometro();
|
||||
|
||||
// Ejecuta la tarea de corrección con timeout
|
||||
_ = ProcessCorreccionWithTimeout();
|
||||
}
|
||||
await InitializeSelectedMode();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
GTP.Log.Log($"Error en OnStartup: {ex.Message}");
|
||||
GTP.Log.Log($"StackTrace: {ex.StackTrace}");
|
||||
ShowCustomNotification("Error", "Se produjo un error al iniciar la aplicación");
|
||||
Application.Current.Shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task InitializeSelectedMode()
|
||||
{
|
||||
switch (Opciones.Instance.modo)
|
||||
{
|
||||
case Opciones.modoDeUso.OCRaTexto:
|
||||
_mainWindow = new ScreenCaptureWindow();
|
||||
_mainWindow.Closed += (s, e) => Application.Current.Shutdown();
|
||||
break;
|
||||
|
||||
case Opciones.modoDeUso.Chat:
|
||||
_mainWindow = new Chat(GTP);
|
||||
_mainWindow.Closed += (s, e) => Application.Current.Shutdown();
|
||||
break;
|
||||
|
||||
case Opciones.modoDeUso.Corregir:
|
||||
case Opciones.modoDeUso.Ortografia:
|
||||
case Opciones.modoDeUso.Traducir_a_Espanol:
|
||||
case Opciones.modoDeUso.Traducir_a_Ingles:
|
||||
case Opciones.modoDeUso.Traducir_a_Italiano:
|
||||
await HandleTextCorrection();
|
||||
return;
|
||||
}
|
||||
|
||||
if (_mainWindow != null)
|
||||
_mainWindow.Show();
|
||||
}
|
||||
|
||||
private async Task HandleTextCorrection()
|
||||
{
|
||||
if (Opciones.Instance.AutoCopy)
|
||||
{
|
||||
await pasteLogic.AutoCopyFromActiveWindow();
|
||||
}
|
||||
|
||||
if (!System.Windows.Clipboard.ContainsText())
|
||||
{
|
||||
ShowCustomNotification("Error", "No hay texto para procesar");
|
||||
Application.Current.Shutdown();
|
||||
return;
|
||||
}
|
||||
|
||||
GTP.TextoACorregir = await ClipboardHelper.GetText();
|
||||
await ProcessCorreccionWithTimeout();
|
||||
}
|
||||
|
||||
private async Task ProcessCorreccionWithTimeout()
|
||||
{
|
||||
try
|
||||
|
@ -125,7 +150,9 @@ namespace GTPCorrgir
|
|||
ShowCustomNotification("Se puede pegar",
|
||||
$"Corrección en: {Math.Round(stopwatch.ElapsedMilliseconds / 1000.0, 1)} s");
|
||||
|
||||
if (Opciones.Instance.modo == Opciones.modoDeUso.Corregir || Opciones.Instance.modo == Opciones.modoDeUso.Ortografia)
|
||||
if (Opciones.Instance.modo == Opciones.modoDeUso.Corregir || Opciones.Instance.modo == Opciones.modoDeUso.Ortografia ||
|
||||
Opciones.Instance.modo == Opciones.modoDeUso.Traducir_a_Espanol || Opciones.Instance.modo == Opciones.modoDeUso.Traducir_a_Ingles ||
|
||||
Opciones.Instance.modo == Opciones.modoDeUso.Traducir_a_Italiano)
|
||||
{
|
||||
if (Opciones.Instance.FuncionesOpcionales == Opciones.funcionesOpcionales.MostrarPopUp)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
<Window x:Class="GTPCorrgir.ContextMenuWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:GTPCorrgir" Title="Menu"
|
||||
WindowStyle="None" AllowsTransparency="True" Background="Transparent" ShowInTaskbar="False" Topmost="True"
|
||||
SizeToContent="WidthAndHeight" KeyDown="Window_KeyDown" Deactivated="Window_Deactivated">
|
||||
|
||||
<Window.Resources>
|
||||
<local:NullToBooleanConverter x:Key="NullToBooleanConverter" />
|
||||
<Style x:Key="CloseButtonStyle" TargetType="Button">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="Foreground" Value="#757575" />
|
||||
<Setter Property="BorderThickness" Value="0" />
|
||||
<Setter Property="FontSize" Value="14" />
|
||||
<Setter Property="Cursor" Value="Hand" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Grid Background="Transparent">
|
||||
<Border x:Name="border" Background="{TemplateBinding Background}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="2"
|
||||
Width="{TemplateBinding Width}" Height="{TemplateBinding Height}">
|
||||
<TextBlock Text="{TemplateBinding Content}" HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center" FontSize="{TemplateBinding FontSize}" />
|
||||
</Border>
|
||||
</Grid>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter TargetName="border" Property="Background" Value="#20000000" />
|
||||
<Setter Property="Foreground" Value="#FF4081" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsPressed" Value="True">
|
||||
<Setter TargetName="border" Property="Background" Value="#40000000" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</Window.Resources>
|
||||
|
||||
<Border Background="#F5F5F5" BorderBrush="#CCCCCC" BorderThickness="1" CornerRadius="3" Margin="5">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Header con título y botón de cerrar -->
|
||||
<Grid Grid.Row="0" Height="20" Margin="10,5,10,5">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBlock Text="Modo de Uso:" FontWeight="Bold" Grid.Column="0" VerticalAlignment="Center" />
|
||||
|
||||
<Button x:Name="CloseButton" Content="✕" Click="CloseButton_Click" Grid.Column="1" Width="20"
|
||||
Height="20" Style="{StaticResource CloseButtonStyle}" />
|
||||
</Grid>
|
||||
|
||||
<!-- Contenido principal -->
|
||||
<Grid Grid.Row="1" Margin="10,0,10,10">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<ListBox x:Name="ModeListBox" Height="200" Grid.Row="0" Margin="0,0,0,10">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding DisplayName}" Padding="5,3" />
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
|
||||
<StackPanel Grid.Row="1" Margin="0,0,0,10">
|
||||
<TextBlock Text="Modelo LLM:" FontWeight="Bold" Margin="0,0,0,5" />
|
||||
<ListBox x:Name="LLMListBox" Height="120">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding DisplayName}" Padding="5,3" />
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
</StackPanel>
|
||||
|
||||
<Button Grid.Row="2" Content="Aceptar" Height="30" Width="80" HorizontalAlignment="Right"
|
||||
Click="AcceptButton_Click" Margin="0,10,0,0">
|
||||
<!-- ... resto del estilo del botón ... -->
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Window>
|
|
@ -0,0 +1,170 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Forms;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Data;
|
||||
using KeyEventArgs = System.Windows.Input.KeyEventArgs;
|
||||
using MessageBox = System.Windows.MessageBox;
|
||||
|
||||
namespace GTPCorrgir
|
||||
{
|
||||
public class NullToBooleanConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
|
||||
{
|
||||
return value != null;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public partial class ContextMenuWindow : Window
|
||||
{
|
||||
public class MenuOption
|
||||
{
|
||||
public string DisplayName { get; set; }
|
||||
public object Value { get; set; }
|
||||
}
|
||||
|
||||
private readonly List<MenuOption> modeOptions;
|
||||
private readonly List<MenuOption> llmOptions;
|
||||
private bool optionsSelected = false;
|
||||
|
||||
public ContextMenuWindow()
|
||||
{
|
||||
// Initialize lists in constructor
|
||||
modeOptions = new List<MenuOption>
|
||||
{
|
||||
new MenuOption { DisplayName = "Corregir texto", Value = Opciones.modoDeUso.Corregir },
|
||||
new MenuOption { DisplayName = "Revisar ortografía", Value = Opciones.modoDeUso.Ortografia },
|
||||
new MenuOption { DisplayName = "Chat", Value = Opciones.modoDeUso.Chat },
|
||||
new MenuOption { DisplayName = "Traducir a inglés", Value = Opciones.modoDeUso.Traducir_a_Ingles },
|
||||
new MenuOption { DisplayName = "Traducir a italiano", Value = Opciones.modoDeUso.Traducir_a_Italiano },
|
||||
new MenuOption { DisplayName = "Traducir a español", Value = Opciones.modoDeUso.Traducir_a_Espanol },
|
||||
new MenuOption { DisplayName = "OCR a texto", Value = Opciones.modoDeUso.OCRaTexto }
|
||||
};
|
||||
|
||||
llmOptions = new List<MenuOption>
|
||||
{
|
||||
new MenuOption { DisplayName = "OpenAI", Value = Opciones.LLM_a_Usar.OpenAI },
|
||||
new MenuOption { DisplayName = "Ollama", Value = Opciones.LLM_a_Usar.Ollama },
|
||||
new MenuOption { DisplayName = "Groq", Value = Opciones.LLM_a_Usar.Groq },
|
||||
new MenuOption { DisplayName = "Grok", Value = Opciones.LLM_a_Usar.Grok }
|
||||
};
|
||||
|
||||
InitializeComponent();
|
||||
InitializeControls();
|
||||
LoadSavedSelections();
|
||||
|
||||
// Posicionar la ventana después de que se haya cargado completamente
|
||||
this.Loaded += (s, e) => PositionWindowAtCursor();
|
||||
}
|
||||
|
||||
private void InitializeControls()
|
||||
{
|
||||
ModeListBox.ItemsSource = modeOptions;
|
||||
LLMListBox.ItemsSource = llmOptions;
|
||||
}
|
||||
|
||||
private void LoadSavedSelections()
|
||||
{
|
||||
var savedSettings = MenuSettings.Instance;
|
||||
|
||||
var savedMode = modeOptions.FirstOrDefault(x =>
|
||||
(Opciones.modoDeUso)x.Value == savedSettings.Options.LastUsedMode);
|
||||
var savedLLM = llmOptions.FirstOrDefault(x =>
|
||||
(Opciones.LLM_a_Usar)x.Value == savedSettings.Options.LastUsedLLM);
|
||||
|
||||
if (savedMode != null)
|
||||
ModeListBox.SelectedItem = savedMode;
|
||||
|
||||
if (savedLLM != null)
|
||||
LLMListBox.SelectedItem = savedLLM;
|
||||
}
|
||||
|
||||
private void PositionWindowAtCursor()
|
||||
{
|
||||
var cursorPosition = System.Windows.Forms.Cursor.Position;
|
||||
var screen = Screen.FromPoint(cursorPosition);
|
||||
|
||||
// Calculate position ensuring the window stays within screen bounds
|
||||
double left = cursorPosition.X;
|
||||
double top = cursorPosition.Y;
|
||||
|
||||
// Get the window size (waiting for it to be rendered)
|
||||
this.UpdateLayout();
|
||||
double windowWidth = this.ActualWidth;
|
||||
double windowHeight = this.ActualHeight;
|
||||
|
||||
// Adjust position if window would go off screen
|
||||
if (left + windowWidth > screen.WorkingArea.Right)
|
||||
{
|
||||
left = screen.WorkingArea.Right - windowWidth;
|
||||
}
|
||||
|
||||
if (top + windowHeight > screen.WorkingArea.Bottom)
|
||||
{
|
||||
top = screen.WorkingArea.Bottom - windowHeight;
|
||||
}
|
||||
|
||||
// Ensure window doesn't go off the left or top of the screen
|
||||
left = Math.Max(screen.WorkingArea.Left, left);
|
||||
top = Math.Max(screen.WorkingArea.Top, top);
|
||||
|
||||
this.Left = left;
|
||||
this.Top = top;
|
||||
}
|
||||
|
||||
private void CloseButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.Close();
|
||||
}
|
||||
|
||||
private void Window_KeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.Key == Key.Escape)
|
||||
{
|
||||
this.Close();
|
||||
}
|
||||
}
|
||||
|
||||
private void Window_Deactivated(object sender, EventArgs e)
|
||||
{
|
||||
// Elimina este evento o modifícalo para que no cierre automáticamente
|
||||
// if (!optionsSelected)
|
||||
// {
|
||||
// this.DialogResult = false;
|
||||
// this.Close();
|
||||
// }
|
||||
}
|
||||
|
||||
private void AcceptButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (ModeListBox.SelectedItem is MenuOption selectedMode &&
|
||||
LLMListBox.SelectedItem is MenuOption selectedLLM)
|
||||
{
|
||||
UpdateOptionsAndClose(selectedMode, selectedLLM);
|
||||
}
|
||||
}
|
||||
private void UpdateOptionsAndClose(MenuOption selectedMode, MenuOption selectedLLM)
|
||||
{
|
||||
optionsSelected = true;
|
||||
|
||||
var modeValue = (Opciones.modoDeUso)selectedMode.Value;
|
||||
var llmValue = (Opciones.LLM_a_Usar)selectedLLM.Value;
|
||||
|
||||
Opciones.Instance.modo = modeValue;
|
||||
Opciones.Instance.LLM = llmValue;
|
||||
|
||||
MenuSettings.Instance.UpdateLastUsedOptions(modeValue, llmValue);
|
||||
|
||||
// Eliminar DialogResult
|
||||
this.Close();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using Newtonsoft.Json;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace GTPCorrgir
|
||||
{
|
||||
public class MenuSettings
|
||||
{
|
||||
private static readonly string SettingsPath =
|
||||
Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "menusettings.json");
|
||||
|
||||
private static MenuSettings instance;
|
||||
private static readonly object lockObject = new object();
|
||||
|
||||
public class DefaultOptions
|
||||
{
|
||||
public Opciones.modoDeUso LastUsedMode { get; set; } = Opciones.modoDeUso.Corregir;
|
||||
public Opciones.LLM_a_Usar LastUsedLLM { get; set; } = Opciones.LLM_a_Usar.OpenAI;
|
||||
}
|
||||
|
||||
public DefaultOptions Options { get; set; }
|
||||
|
||||
public MenuSettings()
|
||||
{
|
||||
Options = new DefaultOptions();
|
||||
}
|
||||
|
||||
public static MenuSettings Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
lock (lockObject)
|
||||
{
|
||||
instance ??= Load();
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
private static MenuSettings Load()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (File.Exists(SettingsPath))
|
||||
{
|
||||
string json = File.ReadAllText(SettingsPath);
|
||||
var settings = JsonConvert.DeserializeObject<MenuSettings>(json);
|
||||
if (settings != null)
|
||||
{
|
||||
return settings;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"Error loading menu settings: {ex.Message}");
|
||||
}
|
||||
return new MenuSettings();
|
||||
}
|
||||
|
||||
public void Save()
|
||||
{
|
||||
try
|
||||
{
|
||||
string json = JsonConvert.SerializeObject(this, Formatting.Indented);
|
||||
File.WriteAllText(SettingsPath, json);
|
||||
Debug.WriteLine("Menu settings saved successfully");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"Error saving menu settings: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateLastUsedOptions(Opciones.modoDeUso mode, Opciones.LLM_a_Usar llm)
|
||||
{
|
||||
Options.LastUsedMode = mode;
|
||||
Options.LastUsedLLM = llm;
|
||||
Save();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -64,8 +64,8 @@ namespace GTPCorrgir
|
|||
try
|
||||
{
|
||||
// Correct OCR errors using LLM
|
||||
// string correctedText = await CorrectOcrErrors(ocrText);
|
||||
string correctedText = ocrText;
|
||||
string correctedText = await CorrectOcrErrors(ocrText);
|
||||
//string correctedText = ocrText;
|
||||
|
||||
// Apply minimal markdown formatting
|
||||
string formattedText = ApplyBasicFormatting(correctedText);
|
||||
|
|
12
Program.cs
12
Program.cs
|
@ -34,6 +34,7 @@ namespace GTPCorrgir
|
|||
Traducir_a_Italiano,
|
||||
Traducir_a_Espanol,
|
||||
OCRaTexto,
|
||||
Menu,
|
||||
}
|
||||
|
||||
public Dictionary<LLM_a_Usar, string> nombreLLM = new Dictionary<LLM_a_Usar, string>
|
||||
|
@ -54,10 +55,13 @@ namespace GTPCorrgir
|
|||
if (_instance == null)
|
||||
{
|
||||
_instance = new Opciones();
|
||||
_instance.LLM = LLM_a_Usar.OpenAI;
|
||||
_instance.modo = modoDeUso.OCRaTexto;
|
||||
|
||||
// Cargar opciones guardadas si existen
|
||||
var savedSettings = MenuSettings.Instance;
|
||||
_instance.LLM = savedSettings.Options.LastUsedLLM;
|
||||
_instance.modo = savedSettings.Options.LastUsedMode;
|
||||
_instance.FuncionesOpcionales = 0;
|
||||
_instance.AutoCopy = false;
|
||||
_instance.AutoCopy = true;
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
|
@ -118,6 +122,8 @@ namespace GTPCorrgir
|
|||
Opciones.Instance.modo = Opciones.modoDeUso.OCRaTexto;
|
||||
if (arg.Contains("AutoCopy"))
|
||||
Opciones.Instance.AutoCopy = true;
|
||||
if (arg.Contains("Menu"))
|
||||
Opciones.Instance.modo = Opciones.modoDeUso.Menu;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"profiles": {
|
||||
"GTPCorrgir": {
|
||||
"commandName": "Project",
|
||||
"commandLineArgs": "--Menu"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -19,7 +19,10 @@ using Path = System.IO.Path;
|
|||
using MessageBox = System.Windows.MessageBox;
|
||||
using MouseEventArgs = System.Windows.Input.MouseEventArgs;
|
||||
using KeyEventArgs = System.Windows.Input.KeyEventArgs;
|
||||
using Rectangle = System.Windows.Shapes.Rectangle;
|
||||
using Rectangle = System.Windows.Shapes.Rectangle;
|
||||
using System.Windows.Data;
|
||||
using Binding = System.Windows.Data.Binding;
|
||||
using Image = System.Windows.Controls.Image;
|
||||
|
||||
namespace GTPCorrgir
|
||||
{
|
||||
|
@ -28,234 +31,202 @@ namespace GTPCorrgir
|
|||
private Point startPoint;
|
||||
private Point currentPoint;
|
||||
private bool hasFirstPoint;
|
||||
private System.Windows.Shapes.Rectangle selectionRectangle;
|
||||
private Rectangle selectionRectangle;
|
||||
private Canvas overlayCanvas;
|
||||
private readonly Cursor crosshairCursor = Cursors.Cross;
|
||||
private Window overlayWindow;
|
||||
private System.Windows.Forms.Screen targetScreen; // Añadimos esta referencia
|
||||
private bool isSelecting;
|
||||
private TextBlock dimensionsText;
|
||||
|
||||
public ScreenCaptureWindow()
|
||||
{
|
||||
InitializeInitialWindow();
|
||||
InitializeOverlayWindow();
|
||||
}
|
||||
|
||||
private void InitializeInitialWindow()
|
||||
private void InitializeOverlayWindow()
|
||||
{
|
||||
// Calcular el rectángulo virtual que engloba todas las pantallas
|
||||
var virtualScreen = GetVirtualScreenBounds();
|
||||
|
||||
// Configurar la ventana principal
|
||||
this.WindowStyle = WindowStyle.None;
|
||||
this.ResizeMode = ResizeMode.NoResize;
|
||||
this.AllowsTransparency = true;
|
||||
this.Background = new SolidColorBrush(Color.FromArgb(128, 0, 0, 0));
|
||||
this.ShowInTaskbar = false;
|
||||
this.Topmost = true;
|
||||
this.Cursor = crosshairCursor;
|
||||
|
||||
// Establecer la posición y tamaño para cubrir todas las pantallas
|
||||
this.Left = virtualScreen.Left;
|
||||
this.Top = virtualScreen.Top;
|
||||
this.Width = virtualScreen.Width;
|
||||
this.Height = virtualScreen.Height;
|
||||
|
||||
InitializeComponents();
|
||||
SetupEventHandlers();
|
||||
}
|
||||
|
||||
private System.Drawing.Rectangle GetVirtualScreenBounds()
|
||||
{
|
||||
var allScreens = System.Windows.Forms.Screen.AllScreens;
|
||||
int minX = allScreens.Min(s => s.Bounds.Left);
|
||||
int minY = allScreens.Min(s => s.Bounds.Top);
|
||||
int maxX = allScreens.Max(s => s.Bounds.Right);
|
||||
int maxY = allScreens.Max(s => s.Bounds.Bottom);
|
||||
|
||||
// Configurar la ventana inicial para cubrir todas las pantallas
|
||||
this.WindowStyle = WindowStyle.None;
|
||||
this.ResizeMode = ResizeMode.NoResize;
|
||||
this.Width = maxX - minX;
|
||||
this.Height = maxY - minY;
|
||||
this.Left = minX;
|
||||
this.Top = minY;
|
||||
this.AllowsTransparency = true;
|
||||
this.Background = new SolidColorBrush(Color.FromArgb(0, 0, 0, 0));
|
||||
this.ShowInTaskbar = false;
|
||||
this.Topmost = true;
|
||||
this.Cursor = crosshairCursor;
|
||||
|
||||
// Añadir un panel transparente que cubra toda la ventana
|
||||
var panel = new Grid
|
||||
{
|
||||
Background = new SolidColorBrush(Color.FromArgb(1, 0, 0, 0))
|
||||
};
|
||||
this.Content = panel;
|
||||
|
||||
// Agregar el evento del primer clic
|
||||
this.MouseLeftButtonDown += InitialWindow_MouseLeftButtonDown;
|
||||
return new System.Drawing.Rectangle(minX, minY, maxX - minX, maxY - minY);
|
||||
}
|
||||
|
||||
private void InitialWindow_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||
private void InitializeComponents()
|
||||
{
|
||||
// Obtener la pantalla donde se hizo clic
|
||||
var clickPoint = PointToScreen(e.GetPosition(this));
|
||||
Console.WriteLine($"Click point screen coords: X={clickPoint.X}, Y={clickPoint.Y}");
|
||||
overlayCanvas = new Canvas();
|
||||
|
||||
targetScreen = System.Windows.Forms.Screen.FromPoint(
|
||||
new System.Drawing.Point((int)clickPoint.X, (int)clickPoint.Y));
|
||||
// Obtener el área virtual que engloba todas las pantallas
|
||||
var virtualScreen = GetVirtualScreenBounds();
|
||||
|
||||
Console.WriteLine($"Target screen bounds: Left={targetScreen.Bounds.Left}, Top={targetScreen.Bounds.Top}, Right={targetScreen.Bounds.Right}, Bottom={targetScreen.Bounds.Bottom}");
|
||||
// Capturar toda el área de pantallas
|
||||
var screenBitmap = CaptureScreen(virtualScreen.Left, virtualScreen.Top, virtualScreen.Width, virtualScreen.Height);
|
||||
|
||||
// Remover este evento ya que solo lo necesitamos una vez
|
||||
this.MouseLeftButtonDown -= InitialWindow_MouseLeftButtonDown;
|
||||
|
||||
// Calcular el punto relativo a la pantalla objetivo
|
||||
startPoint = new Point(
|
||||
clickPoint.X - targetScreen.Bounds.Left,
|
||||
clickPoint.Y - targetScreen.Bounds.Top
|
||||
);
|
||||
|
||||
Console.WriteLine($"Start point relative coords: X={startPoint.X}, Y={startPoint.Y}");
|
||||
|
||||
// Inicializar la ventana de overlay ANTES de posicionar el rectángulo
|
||||
InitializeOverlayWindow(targetScreen);
|
||||
|
||||
// Asegurarse que el overlay esté completamente inicializado
|
||||
overlayWindow.Dispatcher.Invoke(() =>
|
||||
// Crear imagen con la captura
|
||||
var screenImage = new Image
|
||||
{
|
||||
selectionRectangle.Visibility = Visibility.Visible;
|
||||
Canvas.SetLeft(selectionRectangle, startPoint.X);
|
||||
Canvas.SetTop(selectionRectangle, startPoint.Y);
|
||||
selectionRectangle.Width = 0;
|
||||
selectionRectangle.Height = 0;
|
||||
hasFirstPoint = true;
|
||||
});
|
||||
}
|
||||
|
||||
private void InitializeOverlayWindow(System.Windows.Forms.Screen screen)
|
||||
{
|
||||
overlayWindow = new Window
|
||||
{
|
||||
WindowStyle = WindowStyle.None,
|
||||
ResizeMode = ResizeMode.NoResize,
|
||||
AllowsTransparency = true,
|
||||
Background = new SolidColorBrush(Color.FromArgb(128, 0, 0, 0)),
|
||||
Topmost = true,
|
||||
ShowInTaskbar = false,
|
||||
Width = screen.Bounds.Width,
|
||||
Height = screen.Bounds.Height,
|
||||
WindowStartupLocation = WindowStartupLocation.Manual,
|
||||
Left = screen.Bounds.Left,
|
||||
Top = screen.Bounds.Top
|
||||
Source = screenBitmap,
|
||||
Width = virtualScreen.Width,
|
||||
Height = virtualScreen.Height,
|
||||
Opacity = 0.3 // Esto oscurece toda la imagen
|
||||
};
|
||||
|
||||
InitializeComponents(overlayWindow);
|
||||
SetupEventHandlers();
|
||||
|
||||
overlayWindow.Show();
|
||||
overlayWindow.Activate(); // Asegurar que la ventana tiene el foco
|
||||
this.Hide();
|
||||
}
|
||||
|
||||
private void InitializeComponents(Window window)
|
||||
{
|
||||
overlayCanvas = new Canvas
|
||||
// Crear imagen para el área seleccionada (la misma captura pero opacidad normal)
|
||||
var selectionImage = new Image
|
||||
{
|
||||
HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch,
|
||||
VerticalAlignment = System.Windows.VerticalAlignment.Stretch
|
||||
Source = screenBitmap,
|
||||
Width = virtualScreen.Width,
|
||||
Height = virtualScreen.Height,
|
||||
Opacity = 1
|
||||
};
|
||||
|
||||
var grid = new Grid();
|
||||
grid.Children.Add(overlayCanvas);
|
||||
window.Content = grid;
|
||||
// Crear el clip para la imagen de selección
|
||||
var clipRectangle = new RectangleGeometry();
|
||||
selectionImage.Clip = clipRectangle;
|
||||
selectionImage.Visibility = Visibility.Collapsed;
|
||||
|
||||
selectionRectangle = new System.Windows.Shapes.Rectangle
|
||||
// Rectángulo de selección (solo el borde)
|
||||
selectionRectangle = new Rectangle
|
||||
{
|
||||
Stroke = new SolidColorBrush(Colors.Red),
|
||||
StrokeThickness = 2,
|
||||
Fill = new SolidColorBrush(Color.FromArgb(50, 255, 255, 255)),
|
||||
Stroke = new SolidColorBrush(Color.FromRgb(120, 255, 120)),
|
||||
StrokeThickness = 1.5,
|
||||
Fill = Brushes.Transparent,
|
||||
Visibility = Visibility.Collapsed
|
||||
};
|
||||
|
||||
// Agregar todos los elementos al canvas
|
||||
overlayCanvas.Children.Add(screenImage);
|
||||
overlayCanvas.Children.Add(selectionImage);
|
||||
overlayCanvas.Children.Add(selectionRectangle);
|
||||
}
|
||||
|
||||
private void SetupEventHandlers()
|
||||
{
|
||||
overlayWindow.MouseLeftButtonDown += OverlaySecondPoint_MouseLeftButtonDown;
|
||||
overlayWindow.MouseMove += OverlayCanvas_MouseMove;
|
||||
overlayWindow.KeyDown += MainWindow_KeyDown;
|
||||
}
|
||||
|
||||
private void OverlayCanvas_MouseMove(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (!hasFirstPoint) return;
|
||||
|
||||
currentPoint = e.GetPosition(overlayCanvas);
|
||||
UpdateSelectionRectangle(startPoint, currentPoint);
|
||||
}
|
||||
|
||||
private void OverlaySecondPoint_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (!hasFirstPoint) return;
|
||||
|
||||
// Capturar el segundo punto
|
||||
var endPoint = e.GetPosition(overlayCanvas);
|
||||
|
||||
// Validar el tamaño del rectángulo
|
||||
double width = Math.Abs(endPoint.X - startPoint.X);
|
||||
double height = Math.Abs(endPoint.Y - startPoint.Y);
|
||||
|
||||
// Validar tamaño mínimo (5x5 pixels)
|
||||
const double MIN_SIZE = 5.0;
|
||||
if (width < MIN_SIZE || height < MIN_SIZE)
|
||||
// Actualizar el clip cuando se mueve el rectángulo
|
||||
selectionRectangle.LayoutUpdated += (s, e) =>
|
||||
{
|
||||
selectionRectangle.Visibility = Visibility.Collapsed;
|
||||
var notification = new notificacion();
|
||||
notification.UpdateNotification("Selección muy pequeña",
|
||||
"Por favor, seleccione un área más grande (mínimo 5x5 píxeles)");
|
||||
notification.Show();
|
||||
hasFirstPoint = false;
|
||||
return;
|
||||
}
|
||||
if (selectionRectangle.Visibility == Visibility.Visible)
|
||||
{
|
||||
selectionImage.Visibility = Visibility.Visible;
|
||||
clipRectangle.Rect = new Rect(
|
||||
Canvas.GetLeft(selectionRectangle),
|
||||
Canvas.GetTop(selectionRectangle),
|
||||
selectionRectangle.Width,
|
||||
selectionRectangle.Height
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
selectionImage.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
};
|
||||
|
||||
// Ocultar el rectángulo inmediatamente
|
||||
selectionRectangle.Visibility = Visibility.Collapsed;
|
||||
|
||||
// Mostrar notificación de procesamiento
|
||||
var processingNotification = new notificacion();
|
||||
processingNotification.UpdateNotification("Procesando", "Analizando imagen seleccionada...");
|
||||
processingNotification.Show();
|
||||
|
||||
// Si las validaciones pasan, proceder con la captura
|
||||
CaptureAndProcessArea();
|
||||
this.Content = overlayCanvas;
|
||||
}
|
||||
|
||||
private void UpdateSelectionRectangle(Point start, Point current)
|
||||
{
|
||||
double x = Math.Min(start.X, current.X);
|
||||
double y = Math.Min(start.Y, current.Y);
|
||||
double left = Math.Min(start.X, current.X);
|
||||
double top = Math.Min(start.Y, current.Y);
|
||||
double width = Math.Abs(current.X - start.X);
|
||||
double height = Math.Abs(current.Y - start.Y);
|
||||
|
||||
Canvas.SetLeft(selectionRectangle, x);
|
||||
Canvas.SetTop(selectionRectangle, y);
|
||||
Canvas.SetLeft(selectionRectangle, left);
|
||||
Canvas.SetTop(selectionRectangle, top);
|
||||
selectionRectangle.Width = width;
|
||||
selectionRectangle.Height = height;
|
||||
}
|
||||
|
||||
private void MainWindow_KeyDown(object sender, KeyEventArgs e)
|
||||
private void SetupEventHandlers()
|
||||
{
|
||||
if (e.Key == Key.Escape)
|
||||
this.MouseLeftButtonDown += Overlay_MouseLeftButtonDown;
|
||||
this.MouseLeftButtonUp += Overlay_MouseLeftButtonUp;
|
||||
this.MouseMove += Overlay_MouseMove;
|
||||
this.KeyDown += Window_KeyDown;
|
||||
}
|
||||
|
||||
private void Overlay_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (!hasFirstPoint)
|
||||
{
|
||||
overlayWindow?.Close();
|
||||
this.Close();
|
||||
// Primer punto
|
||||
startPoint = e.GetPosition(overlayCanvas);
|
||||
hasFirstPoint = true;
|
||||
isSelecting = true;
|
||||
|
||||
selectionRectangle.Visibility = Visibility.Visible;
|
||||
UpdateSelectionRectangle(startPoint, startPoint);
|
||||
}
|
||||
}
|
||||
|
||||
private string GetTesseractExecutablePath()
|
||||
private void Overlay_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
string baseDir = AppDomain.CurrentDomain.BaseDirectory;
|
||||
string tessDataDir = Path.Combine(baseDir, "tessdata");
|
||||
|
||||
if (!Directory.Exists(tessDataDir))
|
||||
if (hasFirstPoint && isSelecting)
|
||||
{
|
||||
throw new DirectoryNotFoundException(
|
||||
$"No se encontró el directorio tessdata en {tessDataDir}. " +
|
||||
"Asegúrate de que la carpeta tessdata existe y contiene los archivos de entrenamiento.");
|
||||
}
|
||||
isSelecting = false;
|
||||
currentPoint = e.GetPosition(overlayCanvas);
|
||||
|
||||
return tessDataDir;
|
||||
double width = Math.Abs(currentPoint.X - startPoint.X);
|
||||
double height = Math.Abs(currentPoint.Y - startPoint.Y);
|
||||
|
||||
const double MIN_SIZE = 5.0;
|
||||
if (width < MIN_SIZE || height < MIN_SIZE)
|
||||
{
|
||||
selectionRectangle.Visibility = Visibility.Collapsed;
|
||||
var notification = new notificacion();
|
||||
notification.UpdateNotification("Selección muy pequeña",
|
||||
"Por favor, seleccione un área más grande (mínimo 5x5 píxeles)");
|
||||
notification.Show();
|
||||
hasFirstPoint = false;
|
||||
return;
|
||||
}
|
||||
|
||||
selectionRectangle.Visibility = Visibility.Collapsed;
|
||||
var processingNotification = new notificacion();
|
||||
processingNotification.UpdateNotification("Procesando", "Analizando imagen seleccionada...");
|
||||
processingNotification.Show();
|
||||
|
||||
CaptureAndProcessArea();
|
||||
}
|
||||
}
|
||||
|
||||
private void Overlay_MouseMove(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (hasFirstPoint && isSelecting)
|
||||
{
|
||||
currentPoint = e.GetPosition(overlayCanvas);
|
||||
UpdateSelectionRectangle(startPoint, currentPoint);
|
||||
}
|
||||
}
|
||||
|
||||
private BitmapSource CaptureScreen(double x, double y, double width, double height)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Usar la referencia guardada del screen objetivo
|
||||
var screenPoint = new System.Drawing.Point(
|
||||
(int)(targetScreen.Bounds.Left + x),
|
||||
(int)(targetScreen.Bounds.Top + y)
|
||||
);
|
||||
|
||||
Console.WriteLine($"Capture coordinates: X={screenPoint.X}, Y={screenPoint.Y}, Width={width}, Height={height}");
|
||||
// Las coordenadas ya están en el espacio de la pantalla virtual
|
||||
var screenPoint = new System.Drawing.Point((int)x, (int)y);
|
||||
|
||||
using (var screenBmp = new System.Drawing.Bitmap(
|
||||
(int)width,
|
||||
|
@ -292,6 +263,7 @@ namespace GTPCorrgir
|
|||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show($"Error al capturar pantalla: {ex.Message}");
|
||||
Console.WriteLine($"Stack trace: {ex.StackTrace}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -300,43 +272,29 @@ namespace GTPCorrgir
|
|||
{
|
||||
try
|
||||
{
|
||||
this.Hide();
|
||||
await Task.Delay(100);
|
||||
|
||||
double x = Canvas.GetLeft(selectionRectangle);
|
||||
double y = Canvas.GetTop(selectionRectangle);
|
||||
double width = selectionRectangle.Width;
|
||||
double height = selectionRectangle.Height;
|
||||
|
||||
// Ajustar las coordenadas al origen de la pantalla virtual
|
||||
x += this.Left;
|
||||
y += this.Top;
|
||||
|
||||
var screenCapture = CaptureScreen(x, y, width, height);
|
||||
if (screenCapture == null) return;
|
||||
|
||||
var screenBitmap = new RenderTargetBitmap(
|
||||
(int)width,
|
||||
(int)height,
|
||||
96, 96,
|
||||
PixelFormats.Pbgra32);
|
||||
|
||||
var visual = new DrawingVisual();
|
||||
using (var context = visual.RenderOpen())
|
||||
{
|
||||
context.DrawImage(screenCapture, new Rect(0, 0, width, height));
|
||||
}
|
||||
screenBitmap.Render(visual);
|
||||
|
||||
var encoder = new PngBitmapEncoder();
|
||||
encoder.Frames.Add(BitmapFrame.Create(screenBitmap));
|
||||
|
||||
// Resto del procesamiento OCR igual que antes
|
||||
using (var memoryStream = new MemoryStream())
|
||||
{
|
||||
var encoder = new PngBitmapEncoder();
|
||||
encoder.Frames.Add(BitmapFrame.Create(screenCapture));
|
||||
encoder.Save(memoryStream);
|
||||
memoryStream.Position = 0;
|
||||
|
||||
string tesseractPath = GetTesseractExecutablePath();
|
||||
using (var engine = new TesseractEngine(tesseractPath, "eng", EngineMode.Default))
|
||||
{
|
||||
engine.SetVariable("tessedit_char_whitelist", " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-.");
|
||||
|
||||
using (var img = Pix.LoadFromMemory(memoryStream.ToArray()))
|
||||
{
|
||||
var result = engine.Process(img);
|
||||
|
@ -360,9 +318,31 @@ namespace GTPCorrgir
|
|||
}
|
||||
finally
|
||||
{
|
||||
overlayWindow?.Close();
|
||||
this.Close();
|
||||
}
|
||||
}
|
||||
|
||||
private void Window_KeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.Key == Key.Escape)
|
||||
{
|
||||
this.Close();
|
||||
}
|
||||
}
|
||||
|
||||
private string GetTesseractExecutablePath()
|
||||
{
|
||||
string baseDir = AppDomain.CurrentDomain.BaseDirectory;
|
||||
string tessDataDir = Path.Combine(baseDir, "tessdata");
|
||||
|
||||
if (!Directory.Exists(tessDataDir))
|
||||
{
|
||||
throw new DirectoryNotFoundException(
|
||||
$"No se encontró el directorio tessdata en {tessDataDir}. " +
|
||||
"Asegúrate de que la carpeta tessdata existe y contiene los archivos de entrenamiento.");
|
||||
}
|
||||
|
||||
return tessDataDir;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -323,13 +323,13 @@ namespace GTPCorrgir
|
|||
$"Please check the following text for spelling errors and provide the corrected version. Do not change the meaning or structure of the sentences. Only correct any spelling mistakes you find on: \"{texto}\"",
|
||||
|
||||
Opciones.modoDeUso.Traducir_a_Ingles =>
|
||||
$"Please check the following text for spelling errors and provide the corrected version in English. Do not change the meaning or structure of the sentences. Only correct any spelling mistakes you find on: \"{texto}\"",
|
||||
$"Please check the following text for spelling errors and provide the corrected version tranlated to English. Do not change the meaning or structure of the sentences. Only correct any spelling mistakes you find on: \"{texto}\"",
|
||||
|
||||
Opciones.modoDeUso.Traducir_a_Italiano =>
|
||||
$"Please check the following text for spelling errors and provide the corrected version in Italian. Do not change the meaning or structure of the sentences. Only correct any spelling mistakes you find on: \"{texto}\"",
|
||||
$"Please check the following text for spelling errors and provide the corrected version tranlated to Italian. Do not change the meaning or structure of the sentences. Only correct any spelling mistakes you find on: \"{texto}\"",
|
||||
|
||||
Opciones.modoDeUso.Traducir_a_Espanol =>
|
||||
$"Please check the following text for spelling errors and provide the corrected version in Spanish. Do not change the meaning or structure of the sentences. Only correct any spelling mistakes you find on: \"{texto}\"",
|
||||
$"Please check the following text for spelling errors and provide the corrected version tranlated to Spanish. Do not change the meaning or structure of the sentences. Only correct any spelling mistakes you find on: \"{texto}\"",
|
||||
|
||||
_ => texto
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue