102 lines
2.7 KiB
C#
102 lines
2.7 KiB
C#
using System;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
using System.Windows.Threading;
|
|
|
|
namespace AxCopilot.Services;
|
|
|
|
public class FileDialogWatcher : IDisposable
|
|
{
|
|
private delegate void WinEventDelegate(nint hWinEventHook, uint eventType, nint hwnd, int idObject, int idChild, uint idEventThread, uint dwmsEventTime);
|
|
|
|
private const uint EVENT_OBJECT_SHOW = 32770u;
|
|
|
|
private const uint EVENT_OBJECT_CREATE = 32768u;
|
|
|
|
private const uint WINEVENT_OUTOFCONTEXT = 0u;
|
|
|
|
private const uint WINEVENT_SKIPOWNPROCESS = 2u;
|
|
|
|
private nint _hook;
|
|
|
|
private WinEventDelegate? _delegate;
|
|
|
|
private bool _disposed;
|
|
|
|
private readonly Dispatcher _dispatcher;
|
|
|
|
public event EventHandler<nint>? FileDialogOpened;
|
|
|
|
[DllImport("user32.dll")]
|
|
private static extern nint SetWinEventHook(uint eventMin, uint eventMax, nint hmodWinEventProc, WinEventDelegate lpfnWinEventProc, uint idProcess, uint idThread, uint dwFlags);
|
|
|
|
[DllImport("user32.dll")]
|
|
private static extern bool UnhookWinEvent(nint hWinEventHook);
|
|
|
|
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
|
|
private static extern int GetClassName(nint hWnd, StringBuilder lpClassName, int nMaxCount);
|
|
|
|
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
|
|
private static extern int GetWindowText(nint hWnd, StringBuilder lpString, int nMaxCount);
|
|
|
|
[DllImport("user32.dll")]
|
|
private static extern bool IsWindowVisible(nint hWnd);
|
|
|
|
public FileDialogWatcher()
|
|
{
|
|
_dispatcher = Dispatcher.CurrentDispatcher;
|
|
}
|
|
|
|
public void Start()
|
|
{
|
|
if (_hook == IntPtr.Zero)
|
|
{
|
|
_delegate = OnWinEvent;
|
|
_hook = SetWinEventHook(32770u, 32770u, IntPtr.Zero, _delegate, 0u, 0u, 2u);
|
|
}
|
|
}
|
|
|
|
public void Stop()
|
|
{
|
|
if (_hook != IntPtr.Zero)
|
|
{
|
|
UnhookWinEvent(_hook);
|
|
_hook = IntPtr.Zero;
|
|
}
|
|
}
|
|
|
|
private void OnWinEvent(nint hWinEventHook, uint eventType, nint hwnd, int idObject, int idChild, uint idEventThread, uint dwmsEventTime)
|
|
{
|
|
if (hwnd == IntPtr.Zero || idObject != 0 || !IsWindowVisible(hwnd))
|
|
{
|
|
return;
|
|
}
|
|
StringBuilder stringBuilder = new StringBuilder(256);
|
|
GetClassName(hwnd, stringBuilder, 256);
|
|
string text = stringBuilder.ToString();
|
|
if (text != "#32770")
|
|
{
|
|
return;
|
|
}
|
|
StringBuilder stringBuilder2 = new StringBuilder(256);
|
|
GetWindowText(hwnd, stringBuilder2, 256);
|
|
string text2 = stringBuilder2.ToString();
|
|
if (text2.Contains("열기") || text2.Contains("Open") || text2.Contains("저장") || text2.Contains("Save") || text2.Contains("다른 이름") || text2.Contains("Browse") || text2.Contains("폴더") || text2.Contains("Folder"))
|
|
{
|
|
_dispatcher.BeginInvoke((Delegate)(Action)delegate
|
|
{
|
|
this.FileDialogOpened?.Invoke(this, hwnd);
|
|
}, Array.Empty<object>());
|
|
}
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
if (!_disposed)
|
|
{
|
|
_disposed = true;
|
|
Stop();
|
|
}
|
|
}
|
|
}
|