Я хочу отслеживать изменения в буфере обмена (только текст). Я пытаюсь найти некоторые решения и нашел следующие вопросы по StackOverflow:
Но моя проблема / требование заключается в том, что я не хочу добавлять зависимость к Windows .Forms ни WPF (мое приложение является консольным приложением). Я пытаюсь посмотреть доступные методы в user32.dll. Я написал код, который создает окно и стили окна. Переопределите метод WndPr c для пользовательского, а затем добавьте прослушиватель в изменения буфера обмена. Функция WndProcFunction была вызвана 4 раза для следующих сообщений:
- WM_GETMINMAXINFO
- WM_NCCREATE
- WM_NCCALCSIZE
- WM_CREATE
Но когда я изменяю содержимое буфера обмена, было отправлено сообщение типа WM_CLIPBOARDUPDATE, а также любое сообщение, которое будет соответствовать WndProcFunction. Я пытаюсь использовать «старый API» (SetDashboardViewer
), но это ничего не меняет. Код выглядит следующим образом:
using PInvoke;
...
internal static class User32Ext
{
[DllImport("user32.dll", SetLastError=true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool AddClipboardFormatListener(IntPtr hwnd);
[DllImport("user32.dll", SetLastError=true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool RemoveClipboardFormatListener(IntPtr hwnd);
[DllImport("kernel32.dll")]
internal static extern uint GetLastError();
}
class Program
{
private static IntPtr _nextInChain = IntPtr.Zero;
internal static unsafe IntPtr WndProcFunction(IntPtr hwnd, User32.WindowMessage windowMessage, void* wParam1, void* lParam1)
{
if (windowMessage == User32.WindowMessage.WM_CREATE)
{
var listener = User32Ext.AddClipboardFormatListener(hwnd);
var result = User32.OpenClipboard(window);
//_nextInChain = User32Ext.SetClipboardViewer(hwnd);
}
if (windowMessage == User32.WindowMessage.WM_CLIPBOARDUPDATE)
{
var pointerToText = User32.GetClipboardData_IntPtr(1);
var text = Marshal.PtrToStringAnsi(pointerToText);
Console.WriteLine(text);
}
if (windowMessage == User32.WindowMessage.WM_DRAWCLIPBOARD)
{
if (_nextInChain != IntPtr.Zero)
{
User32.SendMessage(_nextInChain, windowMessage, wParam1, lParam1);
}
}
if (windowMessage == User32.WindowMessage.WM_CHANGECBCHAIN)
{
_nextInChain = hwnd;
//send message...
}
if (windowMessage == User32.WM_DESTROY)
{
//chain msg
User32Ext.RemoveClipboardFormatListener(hwnd);
}
return hwnd; //success
}
static void Main(string[] args)
{
unsafe
{
var hInstance = Marshal.GetHINSTANCE(typeof(Program).Module);
string name = "Test";
User32.WNDCLASSEX wndClassEx = new User32.WNDCLASSEX
{
cbSize = Marshal.SizeOf(typeof(User32.WNDCLASSEX)),
style = User32.ClassStyles.CS_GLOBALCLASS,
cbClsExtra = 0,
cbWndExtra = 0,
hbrBackground = IntPtr.Zero,
hCursor = IntPtr.Zero,
hIcon = IntPtr.Zero,
hIconSm = IntPtr.Zero,
lpszMenuName = null,
hInstance = hInstance,
lpfnWndProc = new User32.WndProc(WndProcFunction)
};
var stringPtr = Marshal.StringToHGlobalAuto(name);
wndClassEx.lpszClassName_IntPtr = stringPtr;
var register = User32.RegisterClassEx(ref wndClassEx);
var window = User32.CreateWindowEx(
User32.WindowStylesEx.WS_EX_TRANSPARENT,
name,
"Test Window",
0,
0, 0, 0, 0,
IntPtr.Zero,
IntPtr.Zero,
wndClassEx.hInstance,
IntPtr.Zero
);
User32.SetClipboardData(13, stringPtr);
...
}
}
}
Есть ли что-то, что мне все еще не хватает в коде, какой-то дополнительный слушатель? Я смотрю на коды ошибок после каждого вызова метода (ов) из user32.dll. Но все безуспешно.