มีการเปลี่ยนแปลงคลิปบอร์ดหรืออัปเดตเหตุการณ์ที่ฉันสามารถเข้าถึงผ่าน C # ได้หรือไม่
มีการเปลี่ยนแปลงคลิปบอร์ดหรืออัปเดตเหตุการณ์ที่ฉันสามารถเข้าถึงผ่าน 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;
// ...
}
}
(ยังมีอีกมากที่ต้องทำส่งผ่านสิ่งต่างๆไปตามห่วงโซ่คลิปบอร์ดและยกเลิกการลงทะเบียนมุมมองของคุณ แต่คุณสามารถรับได้จากบทความ )
ClipboardChanged
เหตุการณ์และตรวจจับรูปแบบข้อมูลต่างๆเมื่อถูกตัด / คัดลอก
เพื่อความสมบูรณ์นี่คือการควบคุมที่ฉันใช้ในรหัสการผลิต เพียงลากจากตัวออกแบบและดับเบิลคลิกเพื่อสร้างตัวจัดการเหตุการณ์
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;
}
}
}
ClipboardChanged
เหตุการณ์และตรวจจับรูปแบบข้อมูลต่างๆเมื่อถูกตัด / คัดลอก
ฉันมีความท้าทายนี้ใน WPF และลงเอยด้วยวิธีการที่อธิบายไว้ด้านล่าง สำหรับรูปแบบ windows มีตัวอย่างที่ยอดเยี่ยมที่อื่นในคำตอบนี้เช่นการควบคุม ClipboardHelper
สำหรับ WPF เราไม่สามารถแทนที่ WndProc ได้ดังนั้นเราจึงต้องเชื่อมต่ออย่างชัดเจนด้วยการเรียก HwndSource AddHook โดยใช้ Source จากหน้าต่าง ผู้ฟังคลิปบอร์ดยังคงใช้การโทร interop แบบเนทีฟของ 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!
ClipboardChanged?.Invoke
ดูการใช้ใหม่ Null เงื่อนไขประกอบการใน C # 6ส่วนสถานการณ์อื่น ๆ
โอเคนี่เป็นโพสต์เก่า แต่เราพบวิธีแก้ปัญหาที่ดูเหมือนง่ายมากเมื่อเทียบกับชุดคำตอบปัจจุบัน เรากำลังใช้ WPF และเราต้องการให้คำสั่งที่กำหนดเอง (ใน ContextMenu) เปิดใช้งานและปิดใช้งานหากคลิปบอร์ดมีข้อความ มี ApplicationCommands อยู่แล้วตัดคัดลอกและวางและคำสั่งเหล่านี้ตอบสนองอย่างถูกต้องต่อการเปลี่ยนแปลงคลิปบอร์ด ดังนั้นเราจึงเพิ่ม EventHandler ต่อไปนี้
ApplicationCommands.Paste.CanExecuteChanged += new EventHandler(Paste_CanExecuteChanged);
private void Paste_CanExecuteChanged(object sender, EventArgs e) {
ourVariable= Clipboard.ContainsText();
}
จริงๆแล้วเรากำลังควบคุม CanExecute ด้วยคำสั่งของเราเองด้วยวิธีนี้ ใช้ได้ผลกับสิ่งที่เราต้องการและบางทีมันอาจจะช่วยคนอื่นได้
มีหลายวิธีในการทำสิ่งนี้ แต่นี่เป็นสิ่งที่ฉันชอบและเหมาะกับฉัน ฉันได้สร้างไลบรารีคลาสเพื่อให้ผู้อื่นสามารถเพิ่มโปรเจ็กต์และรวม DLL จากนั้นก็โทรหาและใช้งานได้ทุกที่ที่ต้องการภายในแอปพลิเคชันของตน
คำตอบนี้ถูกสร้างขึ้นมาด้วยความช่วยเหลือของคนนี้
ขั้นตอนเพิ่มเติมภายใต้รหัส
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,
}
}
ตอนนี้คุณสามารถพิมพ์ 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...
}
}
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
ฉันเชื่อว่าหนึ่งในวิธีแก้ปัญหาก่อนหน้านี้ไม่ได้ตรวจสอบค่าว่างในวิธีการกำจัด:
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;
}
}
}
base.Dispose()
ใช้วิธีการกำจัด
[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;
}
}