Проблема
Для второй версии монитора буфера обмена (с которой мы будем разбираться в следующем посте) мы создадимprotected override void WndProc(ref Message m) { switch (m.Msg) { case WM_DRAWCLIPBOARD: // содержимое буфера обмена изменилось { // реагируем на изменение буфера ClipboardChanged(); // пересылаем сообщение следующему окну в цепочке SendMessage(nextClipboardViewer, WM_DRAWCLIPBOARD, IntPtr.Zero, IntPtr.Zero); break; } case WM_CHANGECBCHAIN: // цепочка приложений, подписанных на WM_DRAWCLIPBOARD изменилась { if (m.WParam == nextClipboardViewer) { // окно, которому мы передавали WM_DRAWCLIPBOARD, удалено из // цепочки, и нам нужно обновить переменную nextClipboardViewer = m.LParam; } else { // просто передаем новости дальше SendMessage(nextClipboardViewer, WM_CHANGECBCHAIN, m.WParam, m.LParam); } m.Result = IntPtr.Zero; // уведомляем систему об обработке сообщения break; } default: // поведение для остальных сообщений - по умолчанию { base.WndProc(ref m); break; } } }Аналогом класса Form в Windows Forms является класс Window, в котором нет метода WndProc, который мы могли бы переопределить. Возвращаемся в Windows Forms? Нет, решение
Решение
Для решения нашей задачи предназначен замечательный класс HwndSource, который находится в пространстве имен System.Windows.Interop. HwndSource — класс, который представляетpublic void AddHook(HwndSourceHook hook); public void RemoveHook(HwndSourceHook hook);Эти методы позволяют соответственно установить и удалить
public delegate IntPtr HwndSourceHook( IntPtr hwnd, // дескриптор окна int msg, // сообщение Windows IntPtr wParam, // параметры IntPtr lParam, // сообщения ref bool handled // обработано ли сообщение )Чтобы создать экземпляр класса HwndSource, мы можем воспользоваться его конструктором и создать новое окно, сообщения которому мы и будем перехватывать. Однако, можно сделать и
В этом моменте я допустил ошибку, вызвав FromVisual в конструкторе формы. В момент вызова окно ещё не было полностью инициализировано, и результатом стало исключение. После этой попытки я переопределил вызов OnSourceInitialized и завершил инициализвцию HwndSource в нём.
Код
Полный код перехвата сообщений Windows выглядит так:public partial class MainWindow : Window { private const int WM_DRAWCLIPBOARD = 0x0308; private HwndSource hwndSource; // функция-перехватчик private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { if (msg == WM_DRAWCLIPBOARD) { // обрабатываем сообщение } return IntPtr.Zero; } public MainWindow() { InitializeComponent(); } protected override void OnSourceInitialized(EventArgs e) { base.OnSourceInitialized(e); // создаем экземпляр HwndSource hwndSource = PresentationSource.FromVisual(this) as HwndSource; // и устанавливаем перехватчик hwndSource.AddHook(WndProc); } }HwndSource Class (System.Windows.Interop)
HwndSourceHook delegate (System.Windows.Interop)
Добрый день, почему то не работает данный код...
ReplyDeleteСообщения приходят... но заветного M_DRAWCLIPBOARD
при вставке в буфер обмена нового текста так и нет.. И в чем же проблема?