Upload FastSeekWpf/App.xaml.cs
Browse files- FastSeekWpf/App.xaml.cs +27 -12
FastSeekWpf/App.xaml.cs
CHANGED
|
@@ -1,6 +1,5 @@
|
|
| 1 |
using System;
|
| 2 |
using System.Diagnostics;
|
| 3 |
-
using System.IO;
|
| 4 |
using System.Runtime.InteropServices;
|
| 5 |
using System.Threading;
|
| 6 |
using System.Windows;
|
|
@@ -17,6 +16,7 @@ public partial class App : Application
|
|
| 17 |
private volatile bool _shutdown;
|
| 18 |
private MainWindow? _mainWindow;
|
| 19 |
private Thread? _hotkeyThread;
|
|
|
|
| 20 |
|
| 21 |
private void OnStartup(object sender, StartupEventArgs e)
|
| 22 |
{
|
|
@@ -35,6 +35,9 @@ public partial class App : Application
|
|
| 35 |
_mainWindow.Show();
|
| 36 |
_mainWindow.Hide(); // Start hidden, wait for hotkey
|
| 37 |
|
|
|
|
|
|
|
|
|
|
| 38 |
// Start global hotkey thread (Alt+Space)
|
| 39 |
_hotkeyThread = new Thread(HotkeyLoop)
|
| 40 |
{
|
|
@@ -48,8 +51,14 @@ public partial class App : Application
|
|
| 48 |
private void OnExit(object sender, ExitEventArgs e)
|
| 49 |
{
|
| 50 |
_shutdown = true;
|
|
|
|
|
|
|
|
|
|
|
|
|
| 51 |
_mutex?.ReleaseMutex();
|
| 52 |
_mutex?.Dispose();
|
|
|
|
|
|
|
| 53 |
}
|
| 54 |
|
| 55 |
private void HotkeyLoop(object? param)
|
|
@@ -68,21 +77,18 @@ public partial class App : Application
|
|
| 68 |
{
|
| 69 |
while (!_shutdown)
|
| 70 |
{
|
| 71 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 72 |
{
|
| 73 |
-
|
| 74 |
-
{
|
| 75 |
-
Win32Api.PostMessageW(targetHwnd, WM_TOGGLE_WINDOW, IntPtr.Zero, IntPtr.Zero);
|
| 76 |
-
}
|
| 77 |
-
else
|
| 78 |
-
{
|
| 79 |
-
Win32Api.TranslateMessage(ref msg);
|
| 80 |
-
Win32Api.DispatchMessageW(ref msg);
|
| 81 |
-
}
|
| 82 |
}
|
| 83 |
else
|
| 84 |
{
|
| 85 |
-
|
|
|
|
| 86 |
}
|
| 87 |
}
|
| 88 |
}
|
|
@@ -91,4 +97,13 @@ public partial class App : Application
|
|
| 91 |
Win32Api.UnregisterHotKey(IntPtr.Zero, 1);
|
| 92 |
}
|
| 93 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 94 |
}
|
|
|
|
| 1 |
using System;
|
| 2 |
using System.Diagnostics;
|
|
|
|
| 3 |
using System.Runtime.InteropServices;
|
| 4 |
using System.Threading;
|
| 5 |
using System.Windows;
|
|
|
|
| 16 |
private volatile bool _shutdown;
|
| 17 |
private MainWindow? _mainWindow;
|
| 18 |
private Thread? _hotkeyThread;
|
| 19 |
+
private IntPtr _hotkeyWakeEvent;
|
| 20 |
|
| 21 |
private void OnStartup(object sender, StartupEventArgs e)
|
| 22 |
{
|
|
|
|
| 35 |
_mainWindow.Show();
|
| 36 |
_mainWindow.Hide(); // Start hidden, wait for hotkey
|
| 37 |
|
| 38 |
+
// Create manual reset event for waking GetMessageW thread
|
| 39 |
+
_hotkeyWakeEvent = CreateEventW(IntPtr.Zero, false, false, null);
|
| 40 |
+
|
| 41 |
// Start global hotkey thread (Alt+Space)
|
| 42 |
_hotkeyThread = new Thread(HotkeyLoop)
|
| 43 |
{
|
|
|
|
| 51 |
private void OnExit(object sender, ExitEventArgs e)
|
| 52 |
{
|
| 53 |
_shutdown = true;
|
| 54 |
+
// Signal wake event to unblock GetMessageW
|
| 55 |
+
if (_hotkeyWakeEvent != IntPtr.Zero)
|
| 56 |
+
SetEvent(_hotkeyWakeEvent);
|
| 57 |
+
_hotkeyThread?.Join(1000);
|
| 58 |
_mutex?.ReleaseMutex();
|
| 59 |
_mutex?.Dispose();
|
| 60 |
+
if (_hotkeyWakeEvent != IntPtr.Zero)
|
| 61 |
+
CloseHandle(_hotkeyWakeEvent);
|
| 62 |
}
|
| 63 |
|
| 64 |
private void HotkeyLoop(object? param)
|
|
|
|
| 77 |
{
|
| 78 |
while (!_shutdown)
|
| 79 |
{
|
| 80 |
+
// Blocking wait: GetMessageW sleeps until a message arrives
|
| 81 |
+
int result = Win32Api.GetMessageW(out Win32Api.MSG msg, IntPtr.Zero, 0, 0);
|
| 82 |
+
if (result == 0 || result == -1) break; // WM_QUIT or error
|
| 83 |
+
|
| 84 |
+
if (msg.message == Win32Api.WM_HOTKEY)
|
| 85 |
{
|
| 86 |
+
Win32Api.PostMessageW(targetHwnd, WM_TOGGLE_WINDOW, IntPtr.Zero, IntPtr.Zero);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 87 |
}
|
| 88 |
else
|
| 89 |
{
|
| 90 |
+
Win32Api.TranslateMessage(ref msg);
|
| 91 |
+
Win32Api.DispatchMessageW(ref msg);
|
| 92 |
}
|
| 93 |
}
|
| 94 |
}
|
|
|
|
| 97 |
Win32Api.UnregisterHotKey(IntPtr.Zero, 1);
|
| 98 |
}
|
| 99 |
}
|
| 100 |
+
|
| 101 |
+
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
| 102 |
+
private static extern IntPtr CreateEventW(IntPtr lpEventAttributes, bool bManualReset, bool bInitialState, string? lpName);
|
| 103 |
+
|
| 104 |
+
[DllImport("kernel32.dll", SetLastError = true)]
|
| 105 |
+
private static extern bool SetEvent(IntPtr hEvent);
|
| 106 |
+
|
| 107 |
+
[DllImport("kernel32.dll", SetLastError = true)]
|
| 108 |
+
private static extern bool CloseHandle(IntPtr hObject);
|
| 109 |
}
|