2010-02-09 3 views
38

Я хочу иметь эту функцию в моей программе на C#: когда пользователь делает Ctrl + C или копировать в любом месте (т. Е. При изменении содержимого буфера обмена), моя программа получит уведомление и проверит, соответствует ли контент определенным критериям , если это так, стать активной программой и обрабатывать контент и т. д.Как отслеживать изменения содержимого буфера обмена в C#?

Я могу получить содержимое из System.Windows.Forms.Clipboard, однако я не знаю, как отслеживать изменения содержимого из буфера обмена.

При использовании ОС Windows Vista,   или более поздней версии, используйте AddClipboardFormatListener как в ответ Джона Knoeller, за ОС Windows XP  , я должен использовать более старый, более хрупкий SetClipboardViewer API, как и в принятом ответе.

+1

Как это сделать в WPF здесь: http://stackoverflow.com/a/33018459/2122718 – marbel82

ответ

12

Вы можете использовать SetClipboardViewer, предоставляемый win32 API (через p/invoke).

Вот страница, которая содержит код, чтобы установить один в C#: http://www.codeguru.com/csharp/.net/net_general/tipstricks/article.php/c7315/

+9

SetClipboardViewer - это хрупкий, более старый API, вы не должны использовать его в новом коде. вместо этого используйте AddClipboardFormatListener. –

16

Вы можете сделать это с помощью PInvoke к Win32 API AddClipboardFormatListener

Слушатель является дескриптор окна (Form.Handle), и форма будет уведомлен об изменениях с WM_CLIPBOARDUPDATE уведомления

Это более надежную замену для старого API SetClipboardViewer.

+0

Спасибо. но на странице msdn минимальное требование к ОС для этого API - это Vista. это правда? (Я все еще под XP, хотя на самом деле, мои пользователи тоже будут использовать XP.) – Weiming

+2

Да, минимальным требованием является Vista. Если вы находитесь на XP, у вас нет выбора, кроме как использовать SetClipboarViewer. Имейте в виду, что SetClipboardViewer является хрупким, хотя у вас не должно быть проблем, если код _your_ правильный, и вы являетесь _only_ viewer. –

+0

Хорошо, я буду очень осторожен. В противном случае ваш ответ был бы лучшим. Благодаря! – Weiming

45

Я написал небольшую утилиту класса, которая использует функцию AddClipboardFormatListener function с Message-only окна, чтобы сделать именно это.

/// <summary> 
/// Provides notifications when the contents of the clipboard is updated. 
/// </summary> 
public sealed class ClipboardNotification 
{ 
    /// <summary> 
    /// Occurs when the contents of the clipboard is updated. 
    /// </summary> 
    public static event EventHandler ClipboardUpdate; 

    private static NotificationForm _form = new NotificationForm(); 

    /// <summary> 
    /// Raises the <see cref="ClipboardUpdate"/> event. 
    /// </summary> 
    /// <param name="e">Event arguments for the event.</param> 
    private static void OnClipboardUpdate(EventArgs e) 
    { 
     var handler = ClipboardUpdate; 
     if (handler != null) 
     { 
      handler(null, e); 
     } 
    } 

    /// <summary> 
    /// Hidden form to recieve the WM_CLIPBOARDUPDATE message. 
    /// </summary> 
    private class NotificationForm : Form 
    { 
     public NotificationForm() 
     { 
      NativeMethods.SetParent(Handle, NativeMethods.HWND_MESSAGE); 
      NativeMethods.AddClipboardFormatListener(Handle); 
     } 

     protected override void WndProc(ref Message m) 
     { 
      if (m.Msg == NativeMethods.WM_CLIPBOARDUPDATE) 
      { 
       OnClipboardUpdate(null); 
      } 
      base.WndProc(ref m); 
     } 
    } 
} 

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); 

    // See http://msdn.microsoft.com/en-us/library/ms633541%28v=vs.85%29.aspx 
    // See http://msdn.microsoft.com/en-us/library/ms649033%28VS.85%29.aspx 
    [DllImport("user32.dll", SetLastError = true)] 
    public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent); 
} 

Этот класс предполагает, что уведомления всегда необходимы в течение всего срока службы приложений, однако он может быть изменен, чтобы обеспечить возможность отказаться от подписки через RemoveClipboardFormatListener function при необходимости.

+0

Ницца. Вы когда-либо обновляли это, чтобы включить XP? – tofutim

+0

@tofutim Нет, я не уверен, какой API доступен на машинах XP, которые могут это сделать – Justin

+0

[это для XP] (http://stackoverflow.com/a/2226957/3331861) –

Смежные вопросы