Буфер обміну C #


90

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


а клас управління? Де?

Це частина WinForms.
Контанго

Відповіді:


73

Я думаю, вам доведеться використовувати деякий 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;
        // ... 
   }
}

(Ще багато чого слід зробити; передача речей по ланцюжку буфера обміну та скасування реєстрації вашого погляду, але це можна отримати зі статті )


Це працює лише в першій відкритій формі ... скажімо, якщо у мене є MyForm1 і myForm2, тож я відкриваю myForm1, тоді MyForm2, подія ClipboardChanged буде піднята лише в MyForm1. Я маю на увазі, у програмі MDI ...
serhio

Посилання мертве. Будь-яка резервна копія, про яку ви знаєте? +1 тим не менше.
Патрік Хофман,

1
Для ледачих людей: Налаштуйте таймер, який тикає на 1 мс. Потім з кожним галочкою перевіряйте, чи змінився вміст вашого буфера обміну. Ці гачки піднімають попередження про віруси та трояни на моєму комп’ютері.
C4d

1
Він проходить кожні вікна MSG в формі і зробити це так важко налагоджувати код

Подібним чином, SharpClipboard як бібліотека може бути більш корисним, оскільки він інкапсулює ті самі функції в одну бібліотеку тонких компонентів. Потім ви можете отримати доступ до його ClipboardChangedподії та виявити різні формати даних, коли вони вирізані / скопійовані.
Віллі Кімура

78

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

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

    /// <summary>
    /// Clipboard contents changed.
    /// </summary>
    public event EventHandler<ClipboardChangedEventArgs> 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;
    }
}
}

2
Чудова робота! Однак ваш код виклику подій не є безпечним для потоків. Вам слід або створити локальну копію, або ініціювати подію з порожнім делегатом. Ви також забули ключове слово "подія" у визначенні ClipboardChanged :)
Охад Шнайдер,

1
@ohadsc Дякую за виправлення. Наскільки мені відомо, WndProc викликається в потоці інтерфейсу користувача. Оскільки клас походить від Control, клієнти також повинні викликати його в потоці інтерфейсу користувача.
dbkk

Це працює лише в першій відкритій формі ... скажімо, якщо у мене є MyForm1 і myForm2, тож я відкриваю myForm1, тоді MyForm2, подія ClipboardChanged буде піднята лише в MyForm1 ... я маю на увазі в програмі MDI ...
serhio

Якось ваш виклик SetClipboardViewer встановлює код помилки Win32 1400: "Недійсний дескриптор вікна.". Але це все одно працює. Мені це здається трохи дивним.
metacircle

1
SharpClipboard як бібліотека може принести більшу користь, оскільки він інкапсулює ті самі функції в одну тонку бібліотеку компонентів. Потім ви можете отримати доступ до його ClipboardChangedподії та виявити різні формати даних, коли вони вирізані / скопійовані.
Віллі Кімура

26

Я мав цей виклик у WPF і в підсумку застосував підхід, описаний нижче. Для віконних форм є чудові приклади в інших місцях цієї відповіді, наприклад, елемент керування ClipboardHelper.

Для WPF ми не можемо замінити WndProc, тому нам потрібно явно підключити його за допомогою виклику HwndSource AddHook, використовуючи джерело з вікна. Прослуховувач буфера обміну все ще використовує власний виклик взаємодії 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!


1
Якщо хтось не знає, що означає ClipboardChanged?.Invokeбачити Використання нового нульового умовного оператора в C # 6 , розділ Інші сценарії
marbel82

11

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

ApplicationCommands.Paste.CanExecuteChanged += new EventHandler(Paste_CanExecuteChanged);

private void Paste_CanExecuteChanged(object sender, EventArgs e) {
  ourVariable= Clipboard.ContainsText();
}

Ми фактично контролюємо CanExecute за власною командою таким чином. Працює для того, що нам потрібно, і, можливо, це допоможе іншим.


Чудове рішення, адже це так просто ... Дякую!
okieh

1
Це фантастичне рішення конкретної проблеми ввімкнення або вимкнення команди вставлення. На жаль, він не охоплює конкретний сценарій "текст змінено" і не запускається, наприклад, при копіюванні тексту з декількох різних рядків.
Колін Дабріц

11

Є кілька способів зробити це, але це мій улюблений і працює для мене. Я створив бібліотеку класів, щоб інші могли додати проект та включити DLL, а потім просто зателефонувати до нього та використовувати його де завгодно у своїх програмах.

Ця відповідь була зроблена за допомогою цієї .

  1. Створіть проект "Бібліотека класів" та назвіть його 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
    {
        /// <summary>Specifies the standard ANSI text format. This static field is read-only.
        /// </summary>
        /// <filterpriority>1</filterpriority>
        Text,
        /// <summary>Specifies the standard Windows Unicode text format. This static field
        /// is read-only.</summary>
        /// <filterpriority>1</filterpriority>
        UnicodeText,
        /// <summary>Specifies the Windows device-independent bitmap (DIB) format. This static
        /// field is read-only.</summary>
        /// <filterpriority>1</filterpriority>
        Dib,
        /// <summary>Specifies a Windows bitmap format. This static field is read-only.</summary>
        /// <filterpriority>1</filterpriority>
        Bitmap,
        /// <summary>Specifies the Windows enhanced metafile format. This static field is
        /// read-only.</summary>
        /// <filterpriority>1</filterpriority>
        EnhancedMetafile,
        /// <summary>Specifies the Windows metafile format, which Windows Forms does not
        /// directly use. This static field is read-only.</summary>
        /// <filterpriority>1</filterpriority>
        MetafilePict,
        /// <summary>Specifies the Windows symbolic link format, which Windows Forms does
        /// not directly use. This static field is read-only.</summary>
        /// <filterpriority>1</filterpriority>
        SymbolicLink,
        /// <summary>Specifies the Windows Data Interchange Format (DIF), which Windows Forms
        /// does not directly use. This static field is read-only.</summary>
        /// <filterpriority>1</filterpriority>
        Dif,
        /// <summary>Specifies the Tagged Image File Format (TIFF), which Windows Forms does
        /// not directly use. This static field is read-only.</summary>
        /// <filterpriority>1</filterpriority>
        Tiff,
        /// <summary>Specifies the standard Windows original equipment manufacturer (OEM)
        /// text format. This static field is read-only.</summary>
        /// <filterpriority>1</filterpriority>
        OemText,
        /// <summary>Specifies the Windows palette format. This static field is read-only.
        /// </summary>
        /// <filterpriority>1</filterpriority>
        Palette,
        /// <summary>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.</summary>
        /// <filterpriority>1</filterpriority>
        PenData,
        /// <summary>Specifies the Resource Interchange File Format (RIFF) audio format,
        /// which Windows Forms does not directly use. This static field is read-only.</summary>
        /// <filterpriority>1</filterpriority>
        Riff,
        /// <summary>Specifies the wave audio format, which Windows Forms does not directly
        /// use. This static field is read-only.</summary>
        /// <filterpriority>1</filterpriority>
        WaveAudio,
        /// <summary>Specifies the Windows file drop format, which Windows Forms does not
        /// directly use. This static field is read-only.</summary>
        /// <filterpriority>1</filterpriority>
        FileDrop,
        /// <summary>Specifies the Windows culture format, which Windows Forms does not directly
        /// use. This static field is read-only.</summary>
        /// <filterpriority>1</filterpriority>
        Locale,
        /// <summary>Specifies text consisting of HTML data. This static field is read-only.
        /// </summary>
        /// <filterpriority>1</filterpriority>
        Html,
        /// <summary>Specifies text consisting of Rich Text Format (RTF) data. This static
        /// field is read-only.</summary>
        /// <filterpriority>1</filterpriority>
        Rtf,
        /// <summary>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.</summary>
        /// <filterpriority>1</filterpriority>
        CommaSeparatedValue,
        /// <summary>Specifies the Windows Forms string class format, which Windows Forms
        /// uses to store string objects. This static field is read-only.</summary>
        /// <filterpriority>1</filterpriority>
        StringFormat,
        /// <summary>Specifies a format that encapsulates any type of Windows Forms object.
        /// This static field is read-only.</summary>
        /// <filterpriority>1</filterpriority>
        Serializable,
    }
}
  1. В інших проектах клацніть правою кнопкою миші рішення та додайте -> Вихід із проекту -> ClipboardHelper.csproj
  2. У своєму проекті перейдіть і клацніть правою кнопкою посилання -> Додати посилання -> Рішення -> Виберіть ClipboardHelper.
  3. У файлі вашого класу типу проекту використовуйте 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...
            }
    }
    

6

Я вважаю, що одне з попередніх рішень не перевіряє наявність нуля в методі 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);
    }

    /// <summary>
    /// Clipboard contents changed.
    /// </summary>
    public event EventHandler<ClipboardChangedEventArgs> 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;
        }
    }
}

Він ніколи не має значення null, оскільки його встановлює конструктор. Єдине, що я б зробив інакше, - це викликати base.Dispose()метод dispose.
jedmao

У всякому разі. Для цілей перевірки, як ви перерахували, вам слід використовувати IntPtr.Zero для NULL (зауважте, що це не еквівалентно C # null) stackoverflow.com/questions/1456861/…
walter

1
ChangeClipboardChain виконується завжди при виході у всіх зразках msdn
walter

Мета - вивести себе з мережі перегляду буфера обміну
Уолтер

6

SharpClipboard як бібліотека може принести більше користі, оскільки він інкапсулює ті самі функції в одну тонку бібліотеку компонентів. Потім ви можете отримати доступ до його ClipboardChangedподії та виявити різні формати даних, коли вони вирізані / скопійовані.

Ви можете вибрати різні формати даних, які ви хочете контролювати:

var clipboard = new SharpClipboard();

clipboard.ObservableFormats.Texts = true;
clipboard.ObservableFormats.Files = true;
clipboard.ObservableFormats.Images = true;
clipboard.ObservableFormats.Others = true;

Ось приклад використання його ClipboardChangedподії:

private void ClipboardChanged(Object sender, ClipboardChangedEventArgs e)
{
    // Is the content copied of text type?
    if (e.ContentType == SharpClipboard.ContentTypes.Text)
    {
        // Get the cut/copied text.
        Debug.WriteLine(clipboard.ClipboardText);
    }

    // Is the content copied of image type?
    else if (e.ContentType == SharpClipboard.ContentTypes.Image)
    {
        // Get the cut/copied image.
        Image img = clipboard.ClipboardImage;
    }

    // Is the content copied of file type?
    else if (e.ContentType == SharpClipboard.ContentTypes.Files)
    {
        // Get the cut/copied file/files.
        Debug.WriteLine(clipboard.ClipboardFiles.ToArray());

        // ...or use 'ClipboardFile' to get a single copied file.
        Debug.WriteLine(clipboard.ClipboardFile);
    }

    // If the cut/copied content is complex, use 'Other'.
    else if (e.ContentType == SharpClipboard.ContentTypes.Other)
    {
        // Do something with 'e.Content' here...
    }
}

Ви також можете дізнатися програму, в якій відбулася подія вирізання / копіювання, разом із її деталями:

private void ClipboardChanged(Object sender, SharpClipboard.ClipboardChangedEventArgs e)
{
    // Gets the application's executable name.
    Debug.WriteLine(e.SourceApplication.Name);
    // Gets the application's window title.
    Debug.WriteLine(e.SourceApplication.Title);
    // Gets the application's process ID.
    Debug.WriteLine(e.SourceApplication.ID.ToString());
    // Gets the application's executable path.
    Debug.WriteLine(e.SourceApplication.Path);
}

Є також інші події, такі як MonitorChanged подія, яка прослуховується, коли моніторинг буфера обміну вимкнено, це означає, що ви можете ввімкнути або вимкнути моніторинг буфера обміну під час виконання.

На додаток до всього цього, оскільки це компонент, ви можете використовувати його в Дизайнерському перегляді , перетягуючи його до форми Windows, що робить надзвичайно легким для кожного налаштування його параметрів та роботу з вбудованими подіями.

SharpClipboard, здається, є найкращим варіантом для сценаріїв моніторингу буфера обміну в .NET.


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

        private void Form1_Load(object sender, EventArgs e)
        {
            _ClipboardViewerNext = SetClipboardViewer(this.Handle);
        }

        protected override void WndProc(ref System.Windows.Forms.Message m)
        {
            const int WM_DRAWCLIPBOARD = 0x308;

            switch (m.Msg)
            {
                case WM_DRAWCLIPBOARD:
                    //Clipboard is Change 
                    //your code..............
                    break; 
                default:
                    base.WndProc(ref m);
                    break;
            }
        }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.