From 9b9ac362614bf7ae9cbf305131236c3e48d57440 Mon Sep 17 00:00:00 2001 From: R0GGER Date: Mon, 9 Nov 2026 00:38:41 +0100 Subject: [PATCH] 1.1.2 Co-authored-by: Cursor --- CHANGELOG.md | 6 +++ README.md | 4 +- build.ps1 | 2 +- installer/Kniip.iss | 2 +- src/Kniip/Editor/ImageExporter.cs | 84 ++++++++++++++++++++++++++++++ src/Kniip/Interop/NativeMethods.cs | 31 +++++++++++ src/Kniip/Kniip.csproj | 2 +- 7 files changed, 126 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f191c3..f5695b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ Alle noemenswaardige wijzigingen in kniip staan in dit bestand. De nieuwste versie staat bovenaan. +## 1.1.2 - 2026-11-09 + +### Opgelost + +- **Link kopiƫren na uploaden.** Na het uploaden kon kniip de link soms niet op het klembord zetten en meldde dan dat het klembord bezet was. Dat gebeurde vooral als de klembordgeschiedenis van Windows (Win+V) of een ander klembordprogramma actief is. kniip zet de link nu op een directere manier op het klembord en probeert het langer opnieuw. Dit geldt ook voor het uploaden van screencasts en de test-upload in de instellingen. + ## 1.1.1 - 2026-11-09 ### Gewijzigd diff --git a/README.md b/README.md index eabfc8d..067d441 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ kniip is een annotatie-editor die naast het Windows Knipprogramma werkt. Maak ee | Versie | Installer | | ------ | --------- | -| 1.1.1 | [Kniip-Setup-1.1.1.exe](https://git.hibbit.net/rogier/kniip/releases/download/1.1.1/Kniip-Setup-1.1.1.exe) | +| 1.1.2 | [Kniip-Setup-1.1.2.exe](https://git.hibbit.net/rogier/kniip/releases/download/1.1.2/Kniip-Setup-1.1.2.exe) | Oudere versies vind je bij [alle releases](https://git.hibbit.net/rogier/kniip/releases). @@ -70,7 +70,7 @@ Vereisten: Bouwen: ```powershell -.\build.ps1 # versie 1.1.1 +.\build.ps1 # versie 1.1.2 .\build.ps1 -Version 1.2.0 # andere versie ``` diff --git a/build.ps1 b/build.ps1 index 3f12bfe..e3a2d5e 100644 --- a/build.ps1 +++ b/build.ps1 @@ -7,7 +7,7 @@ # .\build.ps1 -Version 1.2.0 param( - [string]$Version = "1.1.1", + [string]$Version = "1.1.2", [string]$Runtime = "win-x64" ) diff --git a/installer/Kniip.iss b/installer/Kniip.iss index 8fa36d7..75b02f6 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.1" + #define AppVersion "1.1.2" #endif #ifndef PublishDir #define PublishDir "..\artifacts\publish" diff --git a/src/Kniip/Editor/ImageExporter.cs b/src/Kniip/Editor/ImageExporter.cs index f80475b..d3914b2 100644 --- a/src/Kniip/Editor/ImageExporter.cs +++ b/src/Kniip/Editor/ImageExporter.cs @@ -4,9 +4,11 @@ using System.IO; using System.Runtime.InteropServices; using System.Threading; using System.Windows; +using System.Windows.Interop; using System.Windows.Media; using System.Windows.Media.Imaging; using Kniip.Capture; +using Kniip.Interop; namespace Kniip.Editor; @@ -68,13 +70,95 @@ internal static class ClipboardWriter return TrySet(data); } + /// + /// Tekst gaat rechtstreeks via Win32 op het klembord. De OLE-route van WPF moet het klembord + /// daarna nog leegspoelen, en dat mislukt zodra een klembordbeheerder het meteen opent. + /// public static bool SetText(string text) { + if (TrySetUnicodeText(text)) + { + return true; + } + var data = new DataObject(); data.SetText(text); return TrySet(data); } + private static HwndSource? _owner; + + private static IntPtr OwnerHandle + { + get + { + // Een venster als eigenaar is verplicht: zonder eigenaar weigert SetClipboardData na EmptyClipboard. + _owner ??= new HwndSource(new HwndSourceParameters("KniipClipboardWriter") + { + ParentWindow = NativeMethods.HWND_MESSAGE, + WindowStyle = 0 + }); + return _owner.Handle; + } + } + + private static bool TrySetUnicodeText(string text) + { + IntPtr owner = OwnerHandle; + for (int attempt = 0; attempt < 20; attempt++) + { + if (NativeMethods.OpenClipboard(owner)) + { + try + { + return NativeMethods.EmptyClipboard() && PutUnicodeText(text); + } + finally + { + NativeMethods.CloseClipboard(); + } + } + + Thread.Sleep(50); + } + + return false; + } + + private static bool PutUnicodeText(string text) + { + IntPtr handle = NativeMethods.GlobalAlloc(NativeMethods.GMEM_MOVEABLE, (UIntPtr)((text.Length + 1) * 2)); + if (handle == IntPtr.Zero) + { + return false; + } + + IntPtr target = NativeMethods.GlobalLock(handle); + if (target == IntPtr.Zero) + { + NativeMethods.GlobalFree(handle); + return false; + } + + try + { + Marshal.Copy(text.ToCharArray(), 0, target, text.Length); + Marshal.WriteInt16(target, text.Length * 2, 0); + } + finally + { + NativeMethods.GlobalUnlock(handle); + } + + if (NativeMethods.SetClipboardData(NativeMethods.CF_UNICODETEXT, handle) == IntPtr.Zero) + { + NativeMethods.GlobalFree(handle); + return false; + } + + return true; + } + private static bool TrySet(DataObject data) { for (int attempt = 0; attempt < 5; attempt++) diff --git a/src/Kniip/Interop/NativeMethods.cs b/src/Kniip/Interop/NativeMethods.cs index 8e969ce..4ded58a 100644 --- a/src/Kniip/Interop/NativeMethods.cs +++ b/src/Kniip/Interop/NativeMethods.cs @@ -26,6 +26,37 @@ internal static class NativeMethods [DllImport("user32.dll")] public static extern uint GetClipboardSequenceNumber(); + public const uint CF_UNICODETEXT = 13; + public const uint GMEM_MOVEABLE = 0x0002; + + [DllImport("user32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool OpenClipboard(IntPtr hWndNewOwner); + + [DllImport("user32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool CloseClipboard(); + + [DllImport("user32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool EmptyClipboard(); + + [DllImport("user32.dll", SetLastError = true)] + public static extern IntPtr SetClipboardData(uint format, IntPtr hMem); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern IntPtr GlobalAlloc(uint flags, UIntPtr bytes); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern IntPtr GlobalLock(IntPtr hMem); + + [DllImport("kernel32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool GlobalUnlock(IntPtr hMem); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern IntPtr GlobalFree(IntPtr hMem); + [DllImport("user32.dll")] public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint processId); diff --git a/src/Kniip/Kniip.csproj b/src/Kniip/Kniip.csproj index 8b40609..5637159 100644 --- a/src/Kniip/Kniip.csproj +++ b/src/Kniip/Kniip.csproj @@ -18,7 +18,7 @@ app.manifest kniip Annotatie-editor naast het Windows Knipprogramma - 1.1.1 + 1.1.2 nl;en $(NoWarn);WFAC010