diff --git a/CHANGELOG.md b/CHANGELOG.md
index 838069f..fe725a7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,25 @@
Alle noemenswaardige wijzigingen in kniip staan in dit bestand. De nieuwste versie staat bovenaan.
+## 2.0.0 - 2026-11-10
+
+### Nieuw
+
+- **OCR (tekst herkennen).**\
+ Lees tekst van het scherm en kopieer hem. Naast de knoppen voor een schermafdruk en een screencast staat nu de knop **OCR**, met hetzelfde icoon als in het Knipprogramma. Klik erop, sleep een rechthoek, en de tekst daarin opent in een apart venster. Daar pas je hem aan en kopieer je alles, of alleen wat je selecteert. De editor gaat tijdens het kiezen even opzij en komt daarna terug.
+ - Druk in de editor op Ctrl+Shift+T om de tekst van het geopende knipsel te lezen, met je aantekeningen erbij.
+ - Je vindt OCR ook in het menu van het icoon in het systeemvak, onder **OCR (tekst herkennen)...**. Geef het in de instellingen onder **Sneltoetsen** een eigen sneltoets.
+ - kniip gebruikt de tekstherkenning van Windows, in de talen van je Windows-account. Vindt Windows geen taal voor tekstherkenning, dan staat in het venster hoe je er een toevoegt.
+- **Verloop in elke richting.**\
+ De richting van een verloop als achtergrond kies je nu met een draaiknop in plaats van uit vier vaste richtingen. Klik op de knop naast de kleuren en sleep de knop rond de cirkel. Je ziet het verloop meteen meedraaien.
+ - Hij klikt vast op de acht hoofdrichtingen. Houd Shift ingedrukt voor stappen van 15°, of Alt om niet vast te klikken. Je kunt ook de hoek in graden typen, of scrollen boven de knop.
+ - **Vanuit het midden** staat nu als knop onder de cirkel.
+ - Elke nieuwe richting is één stap in **Ongedaan maken**, ook als je lang sleept.
+
+### Gewijzigd
+
+- Het blokjespatroon achter transparante delen is lichter en daardoor rustiger om naar te kijken.
+
## 1.1.9 - 2026-11-10
### Gewijzigd
diff --git a/README.md b/README.md
index ad9bc14..e8cf0d6 100644
--- a/README.md
+++ b/README.md
@@ -34,7 +34,7 @@ kniip is een annotatie-editor die naast het Windows Knipprogramma werkt. Maak ee
| Versie | Installer |
| ------ | --------- |
-| 1.1.9 | [Kniip-Setup-1.1.9.exe](https://git.hibbit.net/rogier/kniip/releases/download/1.1.9/Kniip-Setup-1.1.9.exe) |
+| 2.0.0 | [Kniip-Setup-2.0.0.exe](https://git.hibbit.net/rogier/kniip/releases/download/2.0.0/Kniip-Setup-2.0.0.exe) |
Oudere versies vind je bij [alle releases](https://git.hibbit.net/rogier/kniip/releases).
@@ -80,7 +80,7 @@ Vereisten:
Bouwen:
```powershell
-.\build.ps1 # versie 1.1.9
+.\build.ps1 # versie 2.0.0
.\build.ps1 -Version 1.2.0 # andere versie
```
diff --git a/build.ps1 b/build.ps1
index 7bac010..1d14df6 100644
--- a/build.ps1
+++ b/build.ps1
@@ -12,7 +12,7 @@
# .\build.ps1 -SkipTest -> zonder testexe
param(
- [string]$Version = "1.1.9",
+ [string]$Version = "2.0.0",
[string]$Runtime = "win-x64",
[switch]$SkipTest
)
diff --git a/installer/Kniip.iss b/installer/Kniip.iss
index b392a4d..d598a69 100644
--- a/installer/Kniip.iss
+++ b/installer/Kniip.iss
@@ -5,7 +5,7 @@
#define AppName "kniip"
#define AppExe "Kniip.exe"
#ifndef AppVersion
- #define AppVersion "1.1.9"
+ #define AppVersion "2.0.0"
#endif
#ifndef PublishDir
#define PublishDir "..\artifacts\publish"
diff --git a/src/Kniip/App.xaml.cs b/src/Kniip/App.xaml.cs
index e294fe2..0cbef51 100644
--- a/src/Kniip/App.xaml.cs
+++ b/src/Kniip/App.xaml.cs
@@ -21,6 +21,9 @@ namespace Kniip;
public partial class App : Application
{
+ /// Waar een rechthoekknipsel heen gaat: naar de editor of naar tekstherkenning.
+ private enum SnipTarget { Editor, Ocr }
+
private SingleInstance? _singleInstance;
private TrayIcon? _tray;
private SettingsWindow? _settingsWindow;
@@ -28,6 +31,8 @@ public partial class App : Application
private readonly List _snipWindows = new();
private List _snipSnapshot = new();
private CountdownWindow? _snipCountdown;
+ private SnipTarget _snipTarget;
+ private Action? _snipFinished;
private uint? _ignoredClipboardSequence;
public static App Instance => (App)Current;
@@ -94,6 +99,7 @@ public partial class App : Application
_tray.OpenFileRequested += OpenFileWithDialog;
_tray.SnipRequested += BeginRegionSnip;
_tray.WindowSnipRequested += BeginWindowSnip;
+ _tray.TextRecognitionRequested += () => BeginTextSnip();
_tray.SetCaptureDelay(Settings.CaptureDelaySeconds);
_tray.CaptureDelayChanged += seconds =>
{
@@ -205,6 +211,11 @@ public partial class App : Application
timer.Tick += (_, _) =>
{
timer.Stop();
+ if (_snipCountdown == null && _snipWindows.Count == 0)
+ {
+ _snipTarget = SnipTarget.Editor;
+ }
+
BeginSnip(pickWindow: false);
};
timer.Start();
@@ -216,8 +227,34 @@ public partial class App : Application
/// Bevriest alle schermen (na de ingestelde vertraging) en laat een venster aanklikken; het resultaat opent in de editor.
public void BeginWindowSnip() => BeginDelayedSnip(pickWindow: true);
- private void BeginDelayedSnip(bool pickWindow)
+ /// Als een rechthoekknipsel, maar de herkende tekst opent in een apart venster in plaats van de editor.
+ /// Na het kiezen of annuleren, vóórdat het tekstvenster opent; bijvoorbeeld om de editor terug te zetten.
+ public void BeginTextSnip(Action? finished = null)
{
+ if (_snipCountdown != null || _snipWindows.Count > 0 || Recorder.Stage == RecordingStage.Selecting)
+ {
+ finished?.Invoke();
+ return;
+ }
+
+ _snipFinished = finished;
+ BeginDelayedSnip(pickWindow: false, SnipTarget.Ocr);
+ }
+
+ private void RunSnipFinished()
+ {
+ Action? finished = _snipFinished;
+ _snipFinished = null;
+ finished?.Invoke();
+ }
+
+ private void BeginDelayedSnip(bool pickWindow, SnipTarget target = SnipTarget.Editor)
+ {
+ if (_snipCountdown == null && _snipWindows.Count == 0)
+ {
+ _snipTarget = target;
+ }
+
if (_snipCountdown != null)
{
return;
@@ -243,7 +280,11 @@ public partial class App : Application
};
timer.Start();
};
- countdown.Cancelled += EndCountdown;
+ countdown.Cancelled += () =>
+ {
+ EndCountdown();
+ RunSnipFinished();
+ };
_snipCountdown = countdown;
ApplyHotkeys();
countdown.Start();
@@ -326,7 +367,14 @@ public partial class App : Application
_snipWindows.Clear();
List snapshot = _snipSnapshot;
_snipSnapshot = new();
- if (image != null)
+ SnipTarget target = _snipTarget;
+ _snipTarget = SnipTarget.Editor;
+ RunSnipFinished();
+ if (image != null && target == SnipTarget.Ocr)
+ {
+ BringToFront(OcrResultWindow.Open(image));
+ }
+ else if (image != null)
{
string? windowName = area is { } a ? PhysicalWindow.ProgramNameAt(snapshot, a) : null;
OpenEditor(image, windowName);
@@ -356,6 +404,7 @@ public partial class App : Application
Bind(Settings.RecordHotkey, () => Recorder.Toggle(ScreencastFormat.Mp4));
Bind(Settings.GifHotkey, () => Recorder.Toggle(ScreencastFormat.Gif));
Bind(Settings.ClipboardHotkey, OpenFromClipboard);
+ Bind(Settings.OcrHotkey, () => BeginTextSnip());
if (_snipCountdown is { } countdown)
{
// Alleen tijdens het aftellen; daarna moet Esc gewoon naar het actieve programma.
@@ -366,7 +415,8 @@ public partial class App : Application
}
_tray?.SetHotkeys(HotkeyDisplay(Settings.SnipHotkey), HotkeyDisplay(Settings.WindowHotkey),
- HotkeyDisplay(Settings.RecordHotkey), HotkeyDisplay(Settings.GifHotkey), HotkeyDisplay(Settings.ClipboardHotkey));
+ HotkeyDisplay(Settings.RecordHotkey), HotkeyDisplay(Settings.GifHotkey), HotkeyDisplay(Settings.ClipboardHotkey),
+ HotkeyDisplay(Settings.OcrHotkey));
}
/// Start een screencast: eerst het gebied kiezen, daarna de knoppenbalk.
diff --git a/src/Kniip/Editor/AnnotationSurface.cs b/src/Kniip/Editor/AnnotationSurface.cs
index 62c0560..175d5ce 100644
--- a/src/Kniip/Editor/AnnotationSurface.cs
+++ b/src/Kniip/Editor/AnnotationSurface.cs
@@ -15,7 +15,7 @@ public sealed class AnnotationSurface : FrameworkElement
private static readonly Brush GhostHandleBrush = RenderHelpers.Freeze(new SolidColorBrush(Color.FromArgb(170, 255, 255, 255)));
private static readonly Brush CropShadeBrush = RenderHelpers.Freeze(new SolidColorBrush(Color.FromArgb(120, 0, 0, 0)));
private static readonly Brush CheckerLight = RenderHelpers.Freeze(new SolidColorBrush(Colors.White));
- private static readonly Brush CheckerDark = RenderHelpers.Freeze(new SolidColorBrush(Color.FromRgb(0xD9, 0xD9, 0xD9)));
+ private static readonly Brush CheckerDark = RenderHelpers.Freeze(new SolidColorBrush(Color.FromRgb(0xEF, 0xEF, 0xEF)));
public static readonly Color GuideColor = Color.FromRgb(0, 180, 255);
private static readonly Brush GuideBrush = RenderHelpers.Freeze(new SolidColorBrush(GuideColor));
diff --git a/src/Kniip/Editor/CanvasBackground.cs b/src/Kniip/Editor/CanvasBackground.cs
index a33e2cb..c8dc5c8 100644
--- a/src/Kniip/Editor/CanvasBackground.cs
+++ b/src/Kniip/Editor/CanvasBackground.cs
@@ -7,21 +7,23 @@ namespace Kniip.Editor;
public enum BackgroundKind { None, Color, Gradient, Image }
-public enum GradientDirection { Vertical, Horizontal, Diagonal, Radial }
+public enum GradientDirection { Linear, Radial }
///
/// Wat er onder het knipsel ligt; alleen zichtbaar waar het knipsel transparant is.
/// De kleuren en afbeelding blijven bewaard bij het wisselen van soort.
///
+/// Richting van een lineair verloop in graden, met de klok mee vanaf boven: 90 = naar rechts, 180 = naar onder.
public sealed record CanvasBackground(
BackgroundKind Kind,
Color Color,
Color Color2,
GradientDirection Direction,
+ double Angle,
BitmapSource? Image)
{
public static readonly CanvasBackground Default = new(
- BackgroundKind.None, Colors.White, Color.FromRgb(0x00, 0x78, 0xD4), GradientDirection.Vertical, null);
+ BackgroundKind.None, Colors.White, Color.FromRgb(0x00, 0x78, 0xD4), GradientDirection.Linear, 180, null);
public bool IsVisible => Kind switch
{
@@ -51,13 +53,20 @@ public sealed record CanvasBackground(
}
}
- private Brush CreateGradient() => Direction switch
+ private Brush CreateGradient()
{
- GradientDirection.Horizontal => new LinearGradientBrush(Color, Color2, new Point(0, 0.5), new Point(1, 0.5)),
- GradientDirection.Diagonal => new LinearGradientBrush(Color, Color2, new Point(0, 0), new Point(1, 1)),
- GradientDirection.Radial => new RadialGradientBrush(Color, Color2),
- _ => new LinearGradientBrush(Color, Color2, new Point(0.5, 0), new Point(0.5, 1))
- };
+ if (Direction == GradientDirection.Radial)
+ {
+ return new RadialGradientBrush(Color, Color2);
+ }
+
+ // In de eenheidsruimte van het vlak, zodat 45° van hoek naar hoek loopt; de halve lengte reikt tot in de hoeken.
+ double radians = Angle * Math.PI / 180;
+ var direction = new Vector(Math.Sin(radians), -Math.Cos(radians));
+ double half = (Math.Abs(direction.X) + Math.Abs(direction.Y)) / 2;
+ var center = new Point(0.5, 0.5);
+ return new LinearGradientBrush(Color, Color2, center - direction * half, center + direction * half);
+ }
/// Afbeelding zo schalen dat ze het hele vlak vult; wat uitsteekt valt weg.
private static Rect Cover(double imageWidth, double imageHeight, Rect area)
diff --git a/src/Kniip/Editor/ColorPickerButton.xaml b/src/Kniip/Editor/ColorPickerButton.xaml
index d8c5490..9cbce52 100644
--- a/src/Kniip/Editor/ColorPickerButton.xaml
+++ b/src/Kniip/Editor/ColorPickerButton.xaml
@@ -7,7 +7,7 @@
-
+
diff --git a/src/Kniip/Editor/EditorWindow.xaml b/src/Kniip/Editor/EditorWindow.xaml
index 2c2b0cc..73f517f 100644
--- a/src/Kniip/Editor/EditorWindow.xaml
+++ b/src/Kniip/Editor/EditorWindow.xaml
@@ -288,7 +288,7 @@
-
+
@@ -326,32 +326,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -466,6 +440,15 @@
+
@@ -724,8 +707,7 @@
ToolTip="Achtergrond onder de transparante delen" SelectionChanged="BackgroundKind_Changed" />
-
+