-
Notifications
You must be signed in to change notification settings - Fork 7
OneShotモードをホットキー実行として復活 #670
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| using System.Drawing; | ||
| using WindowTranslator.Modules.Ocr; | ||
|
|
||
| namespace WindowTranslator.Tests; | ||
|
|
||
| public class OcrObservationSelectorTests | ||
| { | ||
| [Fact] | ||
| public void OneShotReturnsCurrentObservationsWithoutCallingTracker() | ||
| { | ||
| TextRect[] observations = [new("current", 10, 20, 100, 30, 18, false)]; | ||
| var tracker = new RecordingTracker | ||
| { | ||
| Result = [new("previous", 1, 2, 3, 4, 5, false)], | ||
| }; | ||
|
|
||
| IReadOnlyList<TextRect> result = OcrObservationSelector.Select( | ||
| observations, | ||
| new Size(1920, 1080), | ||
| tracker, | ||
| true); | ||
|
|
||
| Assert.False(tracker.WasCalled); | ||
| Assert.Equal(observations, result); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void ContinuousModeReturnsTrackerResult() | ||
| { | ||
| TextRect[] tracked = [new("tracked", 11, 22, 101, 31, 19, false)]; | ||
| var tracker = new RecordingTracker { Result = tracked }; | ||
|
|
||
| IReadOnlyList<TextRect> result = OcrObservationSelector.Select( | ||
| [new("current", 10, 20, 100, 30, 18, false)], | ||
| new Size(1920, 1080), | ||
| tracker, | ||
| false); | ||
|
|
||
| Assert.True(tracker.WasCalled); | ||
| Assert.Same(tracked, result); | ||
| } | ||
|
|
||
| private sealed class RecordingTracker : IOcrTextTracker | ||
| { | ||
| public bool WasCalled { get; private set; } | ||
| public required IReadOnlyList<TextRect> Result { get; init; } | ||
|
|
||
| public IReadOnlyList<TextRect> Update(IEnumerable<TextRect> observations, Size imageSize) | ||
| { | ||
| this.WasCalled = true; | ||
| return this.Result; | ||
| } | ||
|
|
||
| public void Reset() | ||
| { | ||
| } | ||
| } | ||
| } |
|
Freeesia marked this conversation as resolved.
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,13 @@ | ||
| using System.Runtime.InteropServices; | ||
| using System.Windows; | ||
| using System.Windows.Interop; | ||
| using System.Windows.Threading; | ||
| using CommunityToolkit.Mvvm.Messaging; | ||
| using Microsoft.Extensions.Options; | ||
| using Windows.Win32.Foundation; | ||
| using Windows.Win32.UI.Input.KeyboardAndMouse; | ||
| using Windows.Win32.UI.WindowsAndMessaging; | ||
| using WindowTranslator.Extensions; | ||
| using WindowTranslator.Stores; | ||
| using static Windows.Win32.PInvoke; | ||
|
|
||
|
|
@@ -16,18 +20,30 @@ public partial class CaptureMainWindow | |
| { | ||
| private readonly IProcessInfoStore processInfo; | ||
| private readonly DispatcherTimer timer = new(); | ||
| private readonly bool isOneShotMode; | ||
| private readonly HOT_KEY_MODIFIERS shortcutModifiers; | ||
| private readonly int shortcutKey; | ||
| private IntPtr windowHandle; | ||
|
|
||
| public CaptureMainWindow(IProcessInfoStore processInfo) | ||
| public CaptureMainWindow(IProcessInfoStore processInfo, IOptionsSnapshot<TargetSettings> targetSettings) | ||
| { | ||
| InitializeComponent(); | ||
| this.processInfo = processInfo; | ||
| this.isOneShotMode = targetSettings.Value.IsOneShotMode; | ||
| (this.shortcutModifiers, this.shortcutKey) = targetSettings.Value.OverlayShortcut.ToHotKey(); | ||
| this.timer.Interval = TimeSpan.FromMilliseconds(10); | ||
| this.timer.Tick += (s, e) => CheckTargetWindow(); | ||
| } | ||
|
|
||
| private void Window_Loaded(object sender, RoutedEventArgs e) | ||
| { | ||
| this.timer.Start(); | ||
| if (this.isOneShotMode) | ||
|
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ホットキーの登録はOneShotかどうかに関わらず必要では?本当にオーバーレイと実装揃ってる?
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ご指摘のとおり、Capture表示のホットキー登録はOneShot固有の変更として入れるべきではありませんでした。今回の変更範囲とは関係ないため、 |
||
| { | ||
| this.windowHandle = new WindowInteropHelper(this).Handle; | ||
| RegisterHotKey(new(this.windowHandle), 0, this.shortcutModifiers, (uint)this.shortcutKey); | ||
| HwndSource.FromHwnd(this.windowHandle).AddHook(WndProc); | ||
| } | ||
| StrongReferenceMessenger.Default.Register<CaptureMainWindow, CloseMessage>(this, CloseIfViewModel); | ||
| } | ||
|
|
||
|
|
@@ -45,9 +61,22 @@ protected override void OnClosed(EventArgs e) | |
| { | ||
| base.OnClosed(e); | ||
| this.timer.Stop(); | ||
| if (this.isOneShotMode) | ||
| { | ||
| UnregisterHotKey(new(this.windowHandle), 0); | ||
| } | ||
| StrongReferenceMessenger.Default.Unregister<CloseMessage>(this); | ||
| } | ||
|
|
||
| private nint WndProc(nint hwnd, int msg, nint wParam, nint lParam, ref bool handled) | ||
| { | ||
| if (msg == WM_HOTKEY && this.DataContext is CaptureMainViewModel viewModel) | ||
| { | ||
| viewModel.RequestOneShot(); | ||
| } | ||
| return 0; | ||
| } | ||
|
|
||
| private static void CloseIfViewModel(CaptureMainWindow w, CloseMessage m) | ||
| { | ||
| if (w.DataContext == m.ViewModel) | ||
|
|
||
|
Freeesia marked this conversation as resolved.
Outdated
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| using System.Drawing; | ||
|
|
||
| namespace WindowTranslator.Modules.Ocr; | ||
|
|
||
| internal static class OcrObservationSelector | ||
| { | ||
| public static IReadOnlyList<TextRect> Select( | ||
| IEnumerable<TextRect> observations, | ||
| Size imageSize, | ||
| IOcrTextTracker tracker, | ||
| bool isOneShotMode) | ||
| { | ||
| var current = observations.ToArray(); | ||
| return isOneShotMode ? current : tracker.Update(current, imageSize); | ||
| } | ||
| } |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Uh oh!
There was an error while loading. Please reload this page.