diff --git a/Tests/ScreenLayoutTests.cs b/Tests/ScreenLayoutTests.cs
index c095a3f3..d306134c 100644
--- a/Tests/ScreenLayoutTests.cs
+++ b/Tests/ScreenLayoutTests.cs
@@ -1,4 +1,5 @@
-using System.Windows;
+using Dapplo.Windows.User32;
+using System.Windows;
using Text_Grab;
namespace Tests;
@@ -92,7 +93,7 @@ public void SmallRectanglesContained()
double smallLeft2 = display2.CenterPoint().X - (sideLength / 2);
double smallTop2 = display2.CenterPoint().Y - (sideLength / 2);
Rect smallRect2 = new(smallLeft2, smallTop2, sideLength, sideLength);
-
+
Assert.True(display2.Contains(smallRect2));
Assert.False(display1.Contains(smallRect2));
Assert.False(display3.Contains(smallRect2));
@@ -121,7 +122,7 @@ public void SmallRectanglesContained456()
double smallLeft5 = display5.CenterPoint().X - (sideLength / 2);
double smallTop5 = display5.CenterPoint().Y - (sideLength / 2);
Rect smallRect5 = new(smallLeft5, smallTop5, sideLength, sideLength);
-
+
Assert.True(display5.Contains(smallRect5));
Assert.False(display4.Contains(smallRect5));
Assert.False(display6.Contains(smallRect5));
@@ -134,4 +135,26 @@ public void SmallRectanglesContained456()
Assert.False(display4.Contains(smallRect6));
Assert.False(display5.Contains(smallRect6));
}
+
+
+ [Fact]
+ public void CompareDapploToWinForms()
+ {
+ DisplayInfo[] dapploDisplays = Dapplo.Windows.User32.DisplayInfo.AllDisplayInfos;
+
+ System.Windows.Forms.Screen[] winFormsDisplays = System.Windows.Forms.Screen.AllScreens;
+
+ Assert.Equal(dapploDisplays.Length, winFormsDisplays.Length);
+
+ for (int i = 0; i < dapploDisplays.Length; i++)
+ {
+ Rect dapploRect = dapploDisplays[i].Bounds;
+ Rect winFormsRect = winFormsDisplays[i].Bounds.AsRect();
+
+ Point dapploCenterPoint = dapploRect.CenterPoint();
+ Point winFormsCenterPoint = winFormsRect.CenterPoint();
+
+ Assert.Equal(dapploCenterPoint, winFormsCenterPoint);
+ }
+ }
}
diff --git a/Text-Grab/Extensions/DapploExtensions.cs b/Text-Grab/Extensions/DapploExtensions.cs
new file mode 100644
index 00000000..470a6094
--- /dev/null
+++ b/Text-Grab/Extensions/DapploExtensions.cs
@@ -0,0 +1,31 @@
+using Dapplo.Windows.User32;
+using System.Windows;
+
+namespace Text_Grab.Extensions;
+public static class DapploExtensions
+{
+ public static Point ScaledCenterPoint(this DisplayInfo displayInfo)
+ {
+ Rect displayRect = displayInfo.Bounds;
+ NativeMethods.GetScaleFactorForMonitor(displayInfo.MonitorHandle, out uint scaleFactor);
+ double scaleFraction = scaleFactor / 100.0;
+ Point rawCenter = displayRect.CenterPoint();
+ Point displayScaledCenterPoint = new(rawCenter.X / scaleFraction, rawCenter.Y / scaleFraction);
+ return displayScaledCenterPoint;
+ }
+
+ public static Rect ScaledBounds(this DisplayInfo displayInfo)
+ {
+ Rect displayRect = displayInfo.Bounds;
+ NativeMethods.GetScaleFactorForMonitor(displayInfo.MonitorHandle, out uint scaleFactor);
+ double scaleFraction = scaleFactor / 100.0;
+
+ // Scale size and position
+ Rect scaledBounds = new(
+ displayRect.X / scaleFraction,
+ displayRect.Y / scaleFraction,
+ displayRect.Width / scaleFraction,
+ displayRect.Height / scaleFraction);
+ return scaledBounds;
+ }
+}
diff --git a/Text-Grab/NativeMethods.cs b/Text-Grab/NativeMethods.cs
index c12e50c6..a1feff36 100644
--- a/Text-Grab/NativeMethods.cs
+++ b/Text-Grab/NativeMethods.cs
@@ -19,4 +19,7 @@ internal static partial class NativeMethods
[LibraryImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static partial bool GetKeyboardState(byte[] keyState);
+
+ [LibraryImport("shcore.dll")]
+ public static partial void GetScaleFactorForMonitor(IntPtr hMon, out uint pScale);
}
\ No newline at end of file
diff --git a/Text-Grab/Text-Grab.csproj b/Text-Grab/Text-Grab.csproj
index 11679457..870120ac 100644
--- a/Text-Grab/Text-Grab.csproj
+++ b/Text-Grab/Text-Grab.csproj
@@ -68,11 +68,11 @@
+
-
diff --git a/Text-Grab/Utilities/WindowUtilities.cs b/Text-Grab/Utilities/WindowUtilities.cs
index 583d48f6..7437ffa8 100644
--- a/Text-Grab/Utilities/WindowUtilities.cs
+++ b/Text-Grab/Utilities/WindowUtilities.cs
@@ -1,14 +1,13 @@
-using System;
+using Dapplo.Windows.User32;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
-using Text_Grab.Properties;
+using Text_Grab.Extensions;
using Text_Grab.Views;
-// using Screen = System.Windows.Forms.Screen;
-using WpfScreenHelper;
using static OSInterop;
namespace Text_Grab.Utilities;
@@ -47,15 +46,18 @@ public static void SetWindowPosition(Window passedWindow)
couldParseAll = double.TryParse(storedPosition[2], out double parsedWid);
couldParseAll = double.TryParse(storedPosition[3], out double parsedHei);
Rect storedSize = new((int)parsedX, (int)parsedY, (int)parsedWid, (int)parsedHei);
- IEnumerable allScreens = Screen.AllScreens;
+ DisplayInfo[] allScreens = DisplayInfo.AllDisplayInfos;
WindowCollection allWindows = Application.Current.Windows;
if (parsedHei < 10 || parsedWid < 10)
return;
- foreach (Screen screen in allScreens)
- if (screen.WpfBounds.IntersectsWith(storedSize))
+ foreach (DisplayInfo screen in allScreens)
+ {
+ Rect screenRect = screen.Bounds;
+ if (screenRect.IntersectsWith(storedSize))
isStoredRectWithinScreen = true;
+ }
if (isStoredRectWithinScreen && couldParseAll)
{
@@ -71,7 +73,7 @@ public static void SetWindowPosition(Window passedWindow)
public static void LaunchFullScreenGrab(TextBox? destinationTextBox = null)
{
- IEnumerable allScreens = Screen.AllScreens;
+ DisplayInfo[] allScreens = DisplayInfo.AllDisplayInfos;
WindowCollection allWindows = Application.Current.Windows;
List allFullscreenGrab = new();
@@ -93,7 +95,7 @@ public static void LaunchFullScreenGrab(TextBox? destinationTextBox = null)
double sideLength = 40;
- foreach (Screen screen in allScreens)
+ foreach (DisplayInfo screen in allScreens)
{
FullscreenGrab fullScreenGrab = allFullscreenGrab[count];
fullScreenGrab.WindowStartupLocation = WindowStartupLocation.Manual;
@@ -102,7 +104,7 @@ public static void LaunchFullScreenGrab(TextBox? destinationTextBox = null)
fullScreenGrab.DestinationTextBox = destinationTextBox;
fullScreenGrab.WindowState = WindowState.Normal;
- Point screenCenterPoint = screen.GetCenterPoint();
+ Point screenCenterPoint = screen.ScaledCenterPoint();
fullScreenGrab.Left = screenCenterPoint.X - (sideLength / 2);
fullScreenGrab.Top = screenCenterPoint.Y - (sideLength / 2);
@@ -114,10 +116,11 @@ public static void LaunchFullScreenGrab(TextBox? destinationTextBox = null)
}
}
- public static Point GetCenterPoint(this Screen screen)
+ public static Point GetCenterPoint(this DisplayInfo screen)
{
- double x = screen.WpfBounds.Left + (screen.WpfBounds.Width / 2);
- double y = screen.WpfBounds.Top + (screen.WpfBounds.Height / 2);
+ Rect screenRect = screen.Bounds;
+ double x = screenRect.Left + (screenRect.Width / 2);
+ double y = screenRect.Top + (screenRect.Height / 2);
return new(x, y);
}
@@ -151,8 +154,8 @@ internal static async void CloseAllFullscreenGrabs()
{
if (window is FullscreenGrab fsg)
{
- if (!string.IsNullOrWhiteSpace(fsg.textFromOCR))
- stringFromOCR = fsg.textFromOCR;
+ if (!string.IsNullOrWhiteSpace(fsg.TextFromOCR))
+ stringFromOCR = fsg.TextFromOCR;
if (fsg.DestinationTextBox is not null)
{
diff --git a/Text-Grab/Views/FullscreenGrab.xaml.cs b/Text-Grab/Views/FullscreenGrab.xaml.cs
index 1a37c6ca..ccd338ef 100644
--- a/Text-Grab/Views/FullscreenGrab.xaml.cs
+++ b/Text-Grab/Views/FullscreenGrab.xaml.cs
@@ -1,4 +1,5 @@
-using System;
+using Dapplo.Windows.User32;
+using System;
using System.Collections.Generic;
using System.Drawing;
using System.Threading.Tasks;
@@ -7,6 +8,7 @@
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Media;
+using Text_Grab.Extensions;
using Text_Grab.Interfaces;
using Text_Grab.Models;
using Text_Grab.Properties;
@@ -24,16 +26,16 @@ public partial class FullscreenGrab : Window
{
#region Fields
- private System.Windows.Point clickedPoint = new System.Windows.Point();
+ private System.Windows.Point clickedPoint = new();
private TextBox? destinationTextBox;
private DpiScale? dpiScale;
private bool isComboBoxReady = false;
private bool isSelecting = false;
private bool isShiftDown = false;
- private Border selectBorder = new Border();
+ private Border selectBorder = new();
private double selectLeft;
private double selectTop;
- private System.Windows.Point shiftPoint = new System.Windows.Point();
+ private System.Windows.Point shiftPoint = new();
private double xShiftDelta;
private double yShiftDelta;
private HistoryInfo? historyInfo;
@@ -69,8 +71,8 @@ public TextBox? DestinationTextBox
}
public bool IsFreeze { get; set; } = false;
- public string? textFromOCR { get; set; }
- private System.Windows.Forms.Screen? currentScreen { get; set; }
+ public string? TextFromOCR { get; set; }
+ private DisplayInfo? CurrentScreen { get; set; }
#endregion Properties
@@ -263,7 +265,6 @@ private void GetDpiAdjustedRegionOfSelectBorder(out DpiScale dpi, out double pos
{
System.Windows.Point absPosPoint = this.GetAbsolutePosition();
dpi = VisualTreeHelper.GetDpi(this);
- int firstScreenBPP = System.Windows.Forms.Screen.AllScreens[0].BitsPerPixel;
posLeft = Canvas.GetLeft(selectBorder) + (absPosPoint.X / dpi.PixelsPerDip);
posTop = Canvas.GetTop(selectBorder) + (absPosPoint.Y / dpi.PixelsPerDip);
@@ -361,7 +362,7 @@ private static async Task LoadOcrLanguages(ComboBox languagesComboBox, bool usin
haveSetLastLang = true;
if (tesseractIncompatibleElements is not null)
- foreach (var element in tesseractIncompatibleElements)
+ foreach (FrameworkElement element in tesseractIncompatibleElements)
element.Visibility = Visibility.Collapsed;
}
@@ -420,12 +421,12 @@ private void PanSelection(System.Windows.Point movingPoint)
double leftValue = selectLeft + xShiftDelta;
double topValue = selectTop + yShiftDelta;
- if (currentScreen is not null && dpiScale is not null)
+ if (CurrentScreen is not null && dpiScale is not null)
{
- double currentScreenLeft = currentScreen.Bounds.Left; // Should always be 0
- double currentScreenRight = currentScreen.Bounds.Right / dpiScale.Value.DpiScaleX;
- double currentScreenTop = currentScreen.Bounds.Top; // Should always be 0
- double currentScreenBottom = currentScreen.Bounds.Bottom / dpiScale.Value.DpiScaleY;
+ double currentScreenLeft = CurrentScreen.Bounds.Left; // Should always be 0
+ double currentScreenRight = CurrentScreen.Bounds.Right / dpiScale.Value.DpiScaleX;
+ double currentScreenTop = CurrentScreen.Bounds.Top; // Should always be 0
+ double currentScreenBottom = CurrentScreen.Bounds.Bottom / dpiScale.Value.DpiScaleY;
leftValue = Math.Clamp(leftValue, currentScreenLeft, (currentScreenRight - selectBorder.Width));
topValue = Math.Clamp(topValue, currentScreenTop, (currentScreenBottom - selectBorder.Height));
@@ -444,9 +445,7 @@ private void PlaceGrabFrameInSelectionRect()
// Then place it where the user just drew the region
// Add space around the window to account for Titlebar
// bottom bar and width of GrabFrame
- DpiScale dpi;
- double posLeft, posTop;
- GetDpiAdjustedRegionOfSelectBorder(out dpi, out posLeft, out posTop);
+ GetDpiAdjustedRegionOfSelectBorder(out DpiScale dpi, out double posLeft, out double posTop);
GrabFrame grabFrame = new()
{
@@ -510,11 +509,14 @@ private void RegionClickCanvas_MouseDown(object sender, MouseButtonEventArgs e)
Canvas.SetLeft(selectBorder, clickedPoint.X);
Canvas.SetTop(selectBorder, clickedPoint.Y);
- var screens = System.Windows.Forms.Screen.AllScreens;
- System.Drawing.Point formsPoint = new((int)clickedPoint.X, (int)clickedPoint.Y);
- foreach (var scr in screens)
- if (scr.Bounds.Contains(formsPoint))
- currentScreen = scr;
+ DisplayInfo[] screens = DisplayInfo.AllDisplayInfos;
+ System.Windows.Point formsPoint = new((int)clickedPoint.X, (int)clickedPoint.Y);
+ foreach (DisplayInfo scr in screens)
+ {
+ Rect bound = scr.ScaledBounds();
+ if (bound.Contains(formsPoint))
+ CurrentScreen = scr;
+ }
}
private void RegionClickCanvas_MouseMove(object sender, MouseEventArgs e)
@@ -532,13 +534,13 @@ private void RegionClickCanvas_MouseMove(object sender, MouseEventArgs e)
isShiftDown = false;
- var left = Math.Min(clickedPoint.X, movingPoint.X);
- var top = Math.Min(clickedPoint.Y, movingPoint.Y);
+ double left = Math.Min(clickedPoint.X, movingPoint.X);
+ double top = Math.Min(clickedPoint.Y, movingPoint.Y);
selectBorder.Height = Math.Max(clickedPoint.Y, movingPoint.Y) - top;
selectBorder.Width = Math.Max(clickedPoint.X, movingPoint.X) - left;
- selectBorder.Height = selectBorder.Height + 2;
- selectBorder.Width = selectBorder.Width + 2;
+ selectBorder.Height += 2;
+ selectBorder.Width += 2;
clippingGeometry.Rect = new Rect(
new System.Windows.Point(left, top),
@@ -553,7 +555,7 @@ private async void RegionClickCanvas_MouseUp(object sender, MouseButtonEventArgs
return;
isSelecting = false;
- currentScreen = null;
+ CurrentScreen = null;
CursorClipper.UnClipCursor();
RegionClickCanvas.ReleaseMouseCapture();
clippingGeometry.Rect = new Rect(
@@ -568,25 +570,16 @@ private async void RegionClickCanvas_MouseUp(object sender, MouseButtonEventArgs
movingPoint.X = Math.Round(movingPoint.X);
movingPoint.Y = Math.Round(movingPoint.Y);
- double correctedLeft = Left;
- double correctedTop = Top;
-
- if (correctedLeft < 0)
- correctedLeft = 0;
-
- if (correctedTop < 0)
- correctedTop = 0;
-
double xDimScaled = Canvas.GetLeft(selectBorder) * m.M11;
double yDimScaled = Canvas.GetTop(selectBorder) * m.M22;
- Rectangle regionScaled = new Rectangle(
+ Rectangle regionScaled = new(
(int)xDimScaled,
(int)yDimScaled,
(int)(selectBorder.Width * m.M11),
(int)(selectBorder.Height * m.M22));
- textFromOCR = string.Empty;
+ TextFromOCR = string.Empty;
if (NewGrabFrameMenuItem.IsChecked is true)
{
@@ -596,9 +589,7 @@ private async void RegionClickCanvas_MouseUp(object sender, MouseButtonEventArgs
try { RegionClickCanvas.Children.Remove(selectBorder); } catch { }
- Language? selectedOcrLang = LanguagesComboBox.SelectedItem as Language;
-
- if (selectedOcrLang is null)
+ if (LanguagesComboBox.SelectedItem is not Language selectedOcrLang)
selectedOcrLang = LanguageUtilities.GetOCRLanguage();
string tessTag = string.Empty;
@@ -608,22 +599,22 @@ private async void RegionClickCanvas_MouseUp(object sender, MouseButtonEventArgs
bool isSmallClick = (regionScaled.Width < 3 || regionScaled.Height < 3);
- bool isSingleLine = SingleLineMenuItem is null ? false : SingleLineMenuItem.IsChecked;
- bool isTable = TableMenuItem is null ? false : TableMenuItem.IsChecked;
+ bool isSingleLine = SingleLineMenuItem is not null && SingleLineMenuItem.IsChecked;
+ bool isTable = TableMenuItem is not null && TableMenuItem.IsChecked;
if (isSmallClick)
{
BackgroundBrush.Opacity = 0;
- textFromOCR = await OcrUtilities.GetClickedWordAsync(this, new System.Windows.Point(xDimScaled, yDimScaled), selectedOcrLang);
+ TextFromOCR = await OcrUtilities.GetClickedWordAsync(this, new System.Windows.Point(xDimScaled, yDimScaled), selectedOcrLang);
}
else if (isTable)
- textFromOCR = await OcrUtilities.GetRegionsTextAsTableAsync(this, regionScaled, selectedOcrLang);
+ TextFromOCR = await OcrUtilities.GetRegionsTextAsTableAsync(this, regionScaled, selectedOcrLang);
else
- textFromOCR = await OcrUtilities.GetRegionsTextAsync(this, regionScaled, selectedOcrLang, tessTag);
+ TextFromOCR = await OcrUtilities.GetRegionsTextAsync(this, regionScaled, selectedOcrLang, tessTag);
if (DefaultSettings.UseHistory && !isSmallClick)
{
- GetDpiAdjustedRegionOfSelectBorder(out DpiScale dpi, out double posLeft, out double posTop);
+ GetDpiAdjustedRegionOfSelectBorder(out _, out double posLeft, out double posTop);
Rect historyRect = new()
{
@@ -641,13 +632,13 @@ private async void RegionClickCanvas_MouseUp(object sender, MouseButtonEventArgs
CaptureDateTime = DateTimeOffset.Now,
PositionRect = historyRect,
IsTable = TableToggleButton.IsChecked!.Value,
- TextContent = textFromOCR,
+ TextContent = TextFromOCR,
ImageContent = Singleton.Instance.CachedBitmap,
SourceMode = TextGrabMode.Fullscreen,
};
}
- if (!string.IsNullOrWhiteSpace(textFromOCR))
+ if (!string.IsNullOrWhiteSpace(TextFromOCR))
{
if (SendToEditTextToggleButton.IsChecked is true && destinationTextBox is null)
{
@@ -656,7 +647,7 @@ private async void RegionClickCanvas_MouseUp(object sender, MouseButtonEventArgs
}
OutputUtilities.HandleTextFromOcr(
- textFromOCR,
+ TextFromOCR,
isSingleLine,
isTable,
destinationTextBox);
@@ -707,8 +698,8 @@ private async void Window_Loaded(object sender, RoutedEventArgs e)
{
WindowState = WindowState.Maximized;
FullWindow.Rect = new System.Windows.Rect(0, 0, Width, Height);
- this.KeyDown += FullscreenGrab_KeyDown;
- this.KeyUp += FullscreenGrab_KeyUp;
+ KeyDown += FullscreenGrab_KeyDown;
+ KeyUp += FullscreenGrab_KeyUp;
SetImageToBackground();
@@ -725,10 +716,10 @@ private async void Window_Loaded(object sender, RoutedEventArgs e)
Topmost = false;
#endif
- List tesseractIncompatibleFrameworkElements = new()
- {
+ List tesseractIncompatibleFrameworkElements =
+ [
TableMenuItem, TableToggleButton
- };
+ ];
await LoadOcrLanguages(LanguagesComboBox, usingTesseract, tesseractIncompatibleFrameworkElements);
isComboBoxReady = true;
@@ -740,12 +731,12 @@ private void Window_Unloaded(object sender, RoutedEventArgs e)
{
BackgroundImage.Source = null;
BackgroundImage.UpdateLayout();
- currentScreen = null;
+ CurrentScreen = null;
dpiScale = null;
- textFromOCR = null;
+ TextFromOCR = null;
- this.Loaded -= Window_Loaded;
- this.Unloaded -= Window_Unloaded;
+ Loaded -= Window_Loaded;
+ Unloaded -= Window_Unloaded;
RegionClickCanvas.MouseDown -= RegionClickCanvas_MouseDown;
RegionClickCanvas.MouseMove -= RegionClickCanvas_MouseMove;
@@ -767,14 +758,14 @@ private void Window_Unloaded(object sender, RoutedEventArgs e)
SettingsButton.Click -= SettingsMenuItem_Click;
CancelButton.Click -= CancelMenuItem_Click;
- this.KeyDown -= FullscreenGrab_KeyDown;
- this.KeyUp -= FullscreenGrab_KeyUp;
+ KeyDown -= FullscreenGrab_KeyDown;
+ KeyUp -= FullscreenGrab_KeyUp;
}
private void StandardModeToggleButton_Click(object sender, RoutedEventArgs e)
{
bool isActive = CheckIfCheckingOrUnchecking(sender);
- WindowUtilities.FullscreenKeyDown(Key.N, isActive);
+ WindowUtilities.FullscreenKeyDown(Key.N, isActive);
SelectSingleToggleButton(sender);
if (isActive)