diff --git a/App.xaml.cs b/App.xaml.cs index 1e69304..252205f 100644 --- a/App.xaml.cs +++ b/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) { diff --git a/ContextMenuWindow.xaml b/ContextMenuWindow.xaml new file mode 100644 index 0000000..01a8600 --- /dev/null +++ b/ContextMenuWindow.xaml @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ContextMenuWindow.xaml.cs b/ContextMenuWindow.xaml.cs new file mode 100644 index 0000000..12694b0 --- /dev/null +++ b/ContextMenuWindow.xaml.cs @@ -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 modeOptions; + private readonly List llmOptions; + private bool optionsSelected = false; + + public ContextMenuWindow() + { + // Initialize lists in constructor + modeOptions = new List + { + 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 + { + 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(); + } + } +} \ No newline at end of file diff --git a/MenuSettings.cs b/MenuSettings.cs new file mode 100644 index 0000000..60ad3b1 --- /dev/null +++ b/MenuSettings.cs @@ -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(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(); + } + } +} \ No newline at end of file diff --git a/OcrTextProcessor.cs b/OcrTextProcessor.cs index 131e6cb..441930d 100644 --- a/OcrTextProcessor.cs +++ b/OcrTextProcessor.cs @@ -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); diff --git a/Program.cs b/Program.cs index 73b85ef..df1645f 100644 --- a/Program.cs +++ b/Program.cs @@ -34,6 +34,7 @@ namespace GTPCorrgir Traducir_a_Italiano, Traducir_a_Espanol, OCRaTexto, + Menu, } public Dictionary nombreLLM = new Dictionary @@ -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; } } diff --git a/Properties/launchSettings.json b/Properties/launchSettings.json new file mode 100644 index 0000000..e4dc929 --- /dev/null +++ b/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "GTPCorrgir": { + "commandName": "Project", + "commandLineArgs": "--Menu" + } + } +} \ No newline at end of file diff --git a/ScreenCaptureWindow.cs b/ScreenCaptureWindow.cs index 0e259f1..6619815 100644 --- a/ScreenCaptureWindow.cs +++ b/ScreenCaptureWindow.cs @@ -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; + } } } \ No newline at end of file diff --git a/gtpask.cs b/gtpask.cs index e3cf91b..b84f888 100644 --- a/gtpask.cs +++ b/gtpask.cs @@ -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 };