Событие буфера обмена C #

Есть ли изменение буфера обмена или обновленное событие, через которое я могу получить доступ через C #?

7 Solutions collect form web for “Событие буфера обмена C #”

Я думаю, вам придется использовать p / invoke:

[DllImport("User32.dll", CharSet=CharSet.Auto)] public static extern IntPtr SetClipboardViewer(IntPtr hWndNewViewer); 

См. Эту статью о том, как настроить монитор буфера обмена в c #

В основном вы регистрируете свое приложение в качестве средства просмотра буфера обмена, используя

 _ClipboardViewerNext = SetClipboardViewer(this.Handle); 

и затем вы получите сообщение WM_DRAWCLIPBOARD , которое вы можете обработать, переопределив WndProc :

 protected override void WndProc(ref Message m) { switch ((Win32.Msgs)m.Msg) { case Win32.Msgs.WM_DRAWCLIPBOARD: // Handle clipboard changed break; // ... } } 

(Еще многое предстоит сделать: прохождение вещей по цепочке буфера обмена и снятие регистрации с вашего вида, но вы можете получить это из статьи )

Для полноты, вот контроль, который я использую в производственном коде. Просто перетащите из конструктора и дважды щелкните, чтобы создать обработчик событий.

 using System; using System.ComponentModel; using System.Runtime.InteropServices; using System.Windows.Forms; using System.Drawing; namespace ClipboardAssist { // Must inherit Control, not Component, in order to have Handle [DefaultEvent("ClipboardChanged")] public partial class ClipboardMonitor : Control { IntPtr nextClipboardViewer; public ClipboardMonitor() { this.BackColor = Color.Red; this.Visible = false; nextClipboardViewer = (IntPtr)SetClipboardViewer((int)this.Handle); } ///  /// Clipboard contents changed. ///  public event EventHandler ClipboardChanged; protected override void Dispose(bool disposing) { ChangeClipboardChain(this.Handle, nextClipboardViewer); } [DllImport("User32.dll")] protected static extern int SetClipboardViewer(int hWndNewViewer); [DllImport("User32.dll", CharSet = CharSet.Auto)] public static extern bool ChangeClipboardChain(IntPtr hWndRemove, IntPtr hWndNewNext); [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern int SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam); protected override void WndProc(ref System.Windows.Forms.Message m) { // defined in winuser.h const int WM_DRAWCLIPBOARD = 0x308; const int WM_CHANGECBCHAIN = 0x030D; switch (m.Msg) { case WM_DRAWCLIPBOARD: OnClipboardChanged(); SendMessage(nextClipboardViewer, m.Msg, m.WParam, m.LParam); break; case WM_CHANGECBCHAIN: if (m.WParam == nextClipboardViewer) nextClipboardViewer = m.LParam; else SendMessage(nextClipboardViewer, m.Msg, m.WParam, m.LParam); break; default: base.WndProc(ref m); break; } } void OnClipboardChanged() { try { IDataObject iData = Clipboard.GetDataObject(); if (ClipboardChanged != null) { ClipboardChanged(this, new ClipboardChangedEventArgs(iData)); } } catch (Exception e) { // Swallow or pop-up, not sure // Trace.Write(e.ToString()); MessageBox.Show(e.ToString()); } } } public class ClipboardChangedEventArgs : EventArgs { public readonly IDataObject DataObject; public ClipboardChangedEventArgs(IDataObject dataObject) { DataObject = dataObject; } } } 

У меня была эта задача в WPF, и я использовал этот подход, описанный ниже. Для оконных форм есть отличные примеры в другом месте этого ответа, такие как элемент управления ClipboardHelper.

Для WPF мы не можем переопределить WndProc, поэтому мы должны явно подключить его с помощью вызова HwndSource AddHook, используя Source из windows. Слушатель буфера обмена по-прежнему использует встроенный вызов вызова AddClipboardFormatListener.

Родные методы:

 internal static class NativeMethods { // See http://msdn.microsoft.com/en-us/library/ms649021%28v=vs.85%29.aspx public const int WM_CLIPBOARDUPDATE = 0x031D; public static IntPtr HWND_MESSAGE = new IntPtr(-3); // See http://msdn.microsoft.com/en-us/library/ms632599%28VS.85%29.aspx#message_only [DllImport("user32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool AddClipboardFormatListener(IntPtr hwnd); } 

Класс менеджера буфера обмена:

 using System.Windows; using System.Windows.Interop; public class ClipboardManager { public event EventHandler ClipboardChanged; public ClipboardManager(Window windowSource) { HwndSource source = PresentationSource.FromVisual(windowSource) as HwndSource; if(source == null) { throw new ArgumentException( "Window source MUST be initialized first, such as in the Window's OnSourceInitialized handler." , nameof(windowSource)); } source.AddHook(WndProc); // get window handle for interop IntPtr windowHandle = new WindowInteropHelper(windowSource).Handle; // register for clipboard events NativeMethods.AddClipboardFormatListener(windowHandle); } private void OnClipboardChanged() { ClipboardChanged?.Invoke(this, EventArgs.Empty); } private static readonly IntPtr WndProcSuccess = IntPtr.Zero; private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { if (msg == NativeMethods.WM_CLIPBOARDUPDATE) { OnClipboardChanged(); handled = true; } return WndProcSuccess; } } 

Это используется в окне WPF, добавляя событие в OnSourceInitialized или позже, например событие Window.Loaded или во время работы. (когда у нас достаточно информации, чтобы использовать собственные перехватчики):

 public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } protected override void OnSourceInitialized(EventArgs e) { base.OnSourceInitialized(e); // Initialize the clipboard now that we have a window soruce to use var windowClipboardManager = new ClipboardManager(this); windowClipboardManager.ClipboardChanged += ClipboardChanged; } private void ClipboardChanged(object sender, EventArgs e) { // Handle your clipboard update here, debug logging example: if (Clipboard.ContainsText()) { Debug.WriteLine(Clipboard.GetText()); } } } 

Я использую этот подход в проекте анализа элемента Path of Exile, поскольку игра выдает информацию о позиции через буфер обмена, когда вы нажимаете Ctrl-C.

https://github.com/ColinDabritz/PoeItemAnalyzer

Надеюсь, это поможет кому-то с обработкой изменения буфера обмена WPF!

Хорошо, так что это старый пост, но мы нашли решение, которое кажется очень простым по сравнению с текущим набором ответов. Мы используем WPF, и мы хотели, чтобы наши собственные пользовательские команды (в ContextMenu) включали и отключали, если в буфере обмена содержится текст. Уже есть ApplicationCommands.Cut, Copy и Paste, и эти команды правильно реагируют на изменение буфера обмена. Поэтому мы просто добавили следующий EventHandler.

 ApplicationCommands.Paste.CanExecuteChanged += new EventHandler(Paste_CanExecuteChanged); private void Paste_CanExecuteChanged(object sender, EventArgs e) { ourVariable= Clipboard.ContainsText(); } 

Фактически мы контролируем CanExecute на нашей собственной команде. Работы для того, что нам нужно, и, возможно, это поможет другим.

Есть несколько способов сделать это, но это мой любимый и работает для меня. Я создал библиотеку classов, чтобы другие могли добавить проект и включить DLL, а затем просто вызвать его и использовать его там, где они хотят в своих приложениях.

Этот ответ был сделан с помощью этого .

  1. Создайте проект библиотеки classов и назовите его ClipboardHelper.
  2. Замените имя Class1 на ClipboardMonitor.
  3. Добавьте в него код ниже.
  4. Добавьте ссылку System.Windows.Forms.

Дополнительные шаги под кодом.

 using System; using System.Windows.Forms; using System.Threading; using System.Runtime.InteropServices; namespace ClipboardHelper { public static class ClipboardMonitor { public delegate void OnClipboardChangeEventHandler(ClipboardFormat format, object data); public static event OnClipboardChangeEventHandler OnClipboardChange; public static void Start() { ClipboardWatcher.Start(); ClipboardWatcher.OnClipboardChange += (ClipboardFormat format, object data) => { if (OnClipboardChange != null) OnClipboardChange(format, data); }; } public static void Stop() { OnClipboardChange = null; ClipboardWatcher.Stop(); } class ClipboardWatcher : Form { // static instance of this form private static ClipboardWatcher mInstance; // needed to dispose this form static IntPtr nextClipboardViewer; public delegate void OnClipboardChangeEventHandler(ClipboardFormat format, object data); public static event OnClipboardChangeEventHandler OnClipboardChange; // start listening public static void Start() { // we can only have one instance if this class if (mInstance != null) return; var t = new Thread(new ParameterizedThreadStart(x => Application.Run(new ClipboardWatcher()))); t.SetApartmentState(ApartmentState.STA); // give the [STAThread] attribute t.Start(); } // stop listening (dispose form) public static void Stop() { mInstance.Invoke(new MethodInvoker(() => { ChangeClipboardChain(mInstance.Handle, nextClipboardViewer); })); mInstance.Invoke(new MethodInvoker(mInstance.Close)); mInstance.Dispose(); mInstance = null; } // on load: (hide this window) protected override void SetVisibleCore(bool value) { CreateHandle(); mInstance = this; nextClipboardViewer = SetClipboardViewer(mInstance.Handle); base.SetVisibleCore(false); } [DllImport("User32.dll", CharSet = CharSet.Auto)] private static extern IntPtr SetClipboardViewer(IntPtr hWndNewViewer); [DllImport("User32.dll", CharSet = CharSet.Auto)] private static extern bool ChangeClipboardChain(IntPtr hWndRemove, IntPtr hWndNewNext); [DllImport("user32.dll", CharSet = CharSet.Auto)] private static extern int SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam); // defined in winuser.h const int WM_DRAWCLIPBOARD = 0x308; const int WM_CHANGECBCHAIN = 0x030D; protected override void WndProc(ref Message m) { switch (m.Msg) { case WM_DRAWCLIPBOARD: ClipChanged(); SendMessage(nextClipboardViewer, m.Msg, m.WParam, m.LParam); break; case WM_CHANGECBCHAIN: if (m.WParam == nextClipboardViewer) nextClipboardViewer = m.LParam; else SendMessage(nextClipboardViewer, m.Msg, m.WParam, m.LParam); break; default: base.WndProc(ref m); break; } } static readonly string[] formats = Enum.GetNames(typeof(ClipboardFormat)); private void ClipChanged() { IDataObject iData = Clipboard.GetDataObject(); ClipboardFormat? format = null; foreach (var f in formats) { if (iData.GetDataPresent(f)) { format = (ClipboardFormat)Enum.Parse(typeof(ClipboardFormat), f); break; } } object data = iData.GetData(format.ToString()); if (data == null || format == null) return; if (OnClipboardChange != null) OnClipboardChange((ClipboardFormat)format, data); } } } public enum ClipboardFormat : byte { /// Specifies the standard ANSI text format. This static field is read-only. ///  /// 1 Text, /// Specifies the standard Windows Unicode text format. This static field /// is read-only. /// 1 UnicodeText, /// Specifies the Windows device-independent bitmap (DIB) format. This static /// field is read-only. /// 1 Dib, /// Specifies a Windows bitmap format. This static field is read-only. /// 1 Bitmap, /// Specifies the Windows enhanced metafile format. This static field is /// read-only. /// 1 EnhancedMetafile, /// Specifies the Windows metafile format, which Windows Forms does not /// directly use. This static field is read-only. /// 1 MetafilePict, /// Specifies the Windows symbolic link format, which Windows Forms does /// not directly use. This static field is read-only. /// 1 SymbolicLink, /// Specifies the Windows Data Interchange Format (DIF), which Windows Forms /// does not directly use. This static field is read-only. /// 1 Dif, /// Specifies the Tagged Image File Format (TIFF), which Windows Forms does /// not directly use. This static field is read-only. /// 1 Tiff, /// Specifies the standard Windows original equipment manufacturer (OEM) /// text format. This static field is read-only. /// 1 OemText, /// Specifies the Windows palette format. This static field is read-only. ///  /// 1 Palette, /// Specifies the Windows pen data format, which consists of pen strokes /// for handwriting software, Windows Forms does not use this format. This static /// field is read-only. /// 1 PenData, /// Specifies the Resource Interchange File Format (RIFF) audio format, /// which Windows Forms does not directly use. This static field is read-only. /// 1 Riff, /// Specifies the wave audio format, which Windows Forms does not directly /// use. This static field is read-only. /// 1 WaveAudio, /// Specifies the Windows file drop format, which Windows Forms does not /// directly use. This static field is read-only. /// 1 FileDrop, /// Specifies the Windows culture format, which Windows Forms does not directly /// use. This static field is read-only. /// 1 Locale, /// Specifies text consisting of HTML data. This static field is read-only. ///  /// 1 Html, /// Specifies text consisting of Rich Text Format (RTF) data. This static /// field is read-only. /// 1 Rtf, /// Specifies a comma-separated value (CSV) format, which is a common interchange /// format used by spreadsheets. This format is not used directly by Windows Forms. /// This static field is read-only. /// 1 CommaSeparatedValue, /// Specifies the Windows Forms string class format, which Windows Forms /// uses to store string objects. This static field is read-only. /// 1 StringFormat, /// Specifies a format that encapsulates any type of Windows Forms object. /// This static field is read-only. /// 1 Serializable, } } 
  1. В ваших других проектах щелкните правой кнопкой мыши по решению и выберите Add -> Exiting Project -> ClipboardHelper.csproj
  2. В своем проекте перейдите по ссылке «Ссылки» -> «Добавить ссылку» -> «Решение» -> «Выбрать буфер обмена».
  3. В вашем файле classа типа проекта используется ClipboardHelper.
  4. Теперь вы можете ввести ClipboardMonitor.Start или .Stop или .OnClipboardChanged

     using ClipboardHelper; namespace Something.Something.DarkSide { public class MainWindow { public MainWindow() { InitializeComponent(); Loaded += MainWindow_Loaded; } void MainWindow_Loaded(object sender, RoutedEventArgs e) { ClipboardMonitor.OnClipboardChange += ClipboardMonitor_OnClipboardChange; ClipboardMonitor.Start(); } private void ClipboardMonitor_OnClipboardChange(ClipboardFormat format, object data) { // Do Something... } } 

Я считаю, что одно из ранних решений не проверяет нуль на методе dispose:

 using System; using System.ComponentModel; using System.Runtime.InteropServices; using System.Windows.Forms; using System.Drawing; namespace ClipboardAssist { // Must inherit Control, not Component, in order to have Handle [DefaultEvent("ClipboardChanged")] public partial class ClipboardMonitor : Control { IntPtr nextClipboardViewer; public ClipboardMonitor() { this.BackColor = Color.Red; this.Visible = false; nextClipboardViewer = (IntPtr)SetClipboardViewer((int)this.Handle); } ///  /// Clipboard contents changed. ///  public event EventHandler ClipboardChanged; protected override void Dispose(bool disposing) { if(nextClipboardViewer != null) ChangeClipboardChain(this.Handle, nextClipboardViewer); } [DllImport("User32.dll")] protected static extern int SetClipboardViewer(int hWndNewViewer); [DllImport("User32.dll", CharSet = CharSet.Auto)] public static extern bool ChangeClipboardChain(IntPtr hWndRemove, IntPtr hWndNewNext); [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern int SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam); protected override void WndProc(ref System.Windows.Forms.Message m) { // defined in winuser.h const int WM_DRAWCLIPBOARD = 0x308; const int WM_CHANGECBCHAIN = 0x030D; switch (m.Msg) { case WM_DRAWCLIPBOARD: OnClipboardChanged(); SendMessage(nextClipboardViewer, m.Msg, m.WParam, m.LParam); break; case WM_CHANGECBCHAIN: if (m.WParam == nextClipboardViewer) nextClipboardViewer = m.LParam; else SendMessage(nextClipboardViewer, m.Msg, m.WParam, m.LParam); break; default: base.WndProc(ref m); break; } } void OnClipboardChanged() { try { IDataObject iData = Clipboard.GetDataObject(); if (ClipboardChanged != null) { ClipboardChanged(this, new ClipboardChangedEventArgs(iData)); } } catch (Exception e) { // Swallow or pop-up, not sure // Trace.Write(e.ToString()); MessageBox.Show(e.ToString()); } } } public class ClipboardChangedEventArgs : EventArgs { public readonly IDataObject DataObject; public ClipboardChangedEventArgs(IDataObject dataObject) { DataObject = dataObject; } } } 

вот хороший пример использования AddClipboardFormatListener .

Для этого нам нужно вывести команду AddClipboardFormatListener и RemoveClipboardFormatListener .

 ///  /// Places the given window in the system-maintained clipboard format listener list. ///  [DllImport("user32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] static extern bool AddClipboardFormatListener(IntPtr hwnd); ///  /// Removes the given window from the system-maintained clipboard format listener list. ///  [DllImport("user32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] static extern bool RemoveClipboardFormatListener(IntPtr hwnd); ///  /// Sent when the contents of the clipboard have changed. ///  private const int WM_CLIPBOARDUPDATE = 0x031D; 

Затем нам нужно добавить наше окно в список прослушивателя формата буфера обмена, вызвав метод AddClipboardFormatListener с дескриптором нашего windows в качестве параметра. Поместите следующий код в конструктор формы основного windows или любые его события загрузки.

 AddClipboardFormatListener(this.Handle); // Add our window to the clipboard's format listener list. 

Переопределите метод WndProc чтобы мы могли поймать при отправке WM_CLIPBOARDUPDATE .

 protected override void WndProc(ref Message m) { base.WndProc(ref m); if (m.Msg == WM_CLIPBOARDUPDATE) { IDataObject iData = Clipboard.GetDataObject(); // Clipboard's data. /* Depending on the clipboard's current data format we can process the data differently. * Feel free to add more checks if you want to process more formats. */ if (iData.GetDataPresent(DataFormats.Text)) { string text = (string)iData.GetData(DataFormats.Text); // do something with it } else if (iData.GetDataPresent(DataFormats.Bitmap)) { Bitmap image = (Bitmap)iData.GetData(DataFormats.Bitmap); // do something with it } } } 

Наконец, перед закрытием формы обязательно удалите главное окно из списка прослушивателей формата буфера обмена.

 private void Form1_FormClosing(object sender, FormClosingEventArgs e) { RemoveClipboardFormatListener(this.Handle); // Remove our window from the clipboard's format listener list. } 
Interesting Posts

изменение источника iframe с помощью jquery

Как установить Apache2 DocumentRoot в общую папку Vboxsf VirtualBox? (Разрешение разрешено?)

Рекомендовать мне хороший видеоформат для кодирования моего видео

Fast String Hashing Алгоритм с низкими коэффициентами столкновений с 32-битным целым

Как добавить собственную библиотеку в «java.library.path» с запуском Eclipse (вместо того, чтобы переопределять его)

Как рассчитать диапазон IP-адресов, когда заданы IP-адрес и сетевая маска?

Сочетание клавиш в Windows 7 с центральным окном

Как найти индекс элемента списка в Swift?

R.exe, Rcmd.exe, Rscript.exe и Rterm.exe: какая разница?

Как найти историю переноса файлов Windows 7?

Как удалить необязательные параметры загрузочного устройства?

Как использовать конструкторы базового classа и оператор присваивания в C ++?

CentOS 7 VirtualBox без доступа в Интернет

Как правильно использовать пространства имен в C ++?

Как определить и переключиться на кадр в веб-seleniumе, когда кадр не имеет идентификатора

Давайте будем гением компьютера.