클립 보드 이벤트 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;
// ...
}
}
(해야 할 일이 더 있습니다. 클립 보드 체인을 따라 전달하고보기 등록을 취소하지만 기사 에서 얻을 수 있습니다. )
완전성을 위해 프로덕션 코드에서 사용하는 컨트롤이 있습니다. 디자이너에서 드래그하고 두 번 클릭하여 이벤트 처리기를 만듭니다.
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;
}
}
}
저는 WPF에서이 문제를 겪었고 아래에 설명 된 접근 방식을 사용했습니다. Windows 양식의 경우이 답변의 다른 곳에 ClipboardHelper 컨트롤과 같은 훌륭한 예제가 있습니다.
WPF의 경우 WndProc를 재정의 할 수 없으므로 창에서 Source를 사용하여 HwndSource AddHook 호출로 명시 적으로 연결해야합니다. 클립 보드 리스너는 여전히 AddClipboardFormatListener 기본 interop 호출을 사용합니다.
기본 방법 :
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;
}
}
이것은 Window.Loaded 이벤트와 같은 OnSourceInitialized 이상의 이벤트를 추가하거나 작업 중에 WPF 창에서 사용됩니다. (기본 후크를 사용하기에 충분한 정보가있는 경우) :
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());
}
}
}
Ctrl-C를 누르면 게임이 클립 보드를 통해 항목 정보를 노출하므로 Path of Exile 항목 분석기 프로젝트에서이 접근 방식을 사용하고 있습니다.
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를 제어하고 있습니다. 우리가 필요로하는 것을 위해 일하고 어쩌면 다른 사람들을 도울 것입니다.
이를 수행하는 방법에는 여러 가지가 있지만 이것은 내가 가장 좋아하는 방법이며 나를 위해 작동합니다. 다른 사람들이 프로젝트를 추가하고 DLL을 포함시킨 다음 단순히 호출하여 애플리케이션 내에서 원하는 곳에서 사용할 수 있도록 클래스 라이브러리를 만들었습니다.
이 답변은의 도움으로 만들어진 이 하나 .
- 클래스 라이브러리 프로젝트를 만들고 이름을 ClipboardHelper로 지정합니다.
- Class1 이름을 ClipboardMonitor로 바꿉니다.
- 아래 코드를 추가하십시오.
- 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,
}
}
- 다른 프로젝트에서 솔루션을 마우스 오른쪽 버튼으로 클릭하고 추가-> 프로젝트 종료-> ClipboardHelper.csproj
- 프로젝트에서 참조-> 참조 추가-> 솔루션-> ClipboardHelper를 선택하십시오.
- ClipboardHelper를 사용하여 프로젝트 유형의 클래스 파일에서.
이제 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 메서드에서 null을 확인하지 않는다고 생각합니다.
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;
}
}
}
라이브러리로서의 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 Form으로 끌어서 놓는 방식으로 사용할 수 있으므로 누구나 쉽게 옵션을 사용자 지정하고 기본 이벤트로 작업 할 수 있습니다.
SharpClipboard 는 .NET의 클립 보드 모니터링 시나리오에 가장 적합한 옵션 인 것 같습니다.
[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;
}
}
참고 URL : https://stackoverflow.com/questions/621577/clipboard-event-c-sharp
'IT story' 카테고리의 다른 글
열린 파일에서 read ()를 두 번 호출 할 수없는 이유는 무엇입니까? (0) | 2020.09.15 |
---|---|
jquery로 숨겨진 입력 값 설정 (0) | 2020.09.15 |
Google Maps API v3에서 하나의 InfoWindow 만 열어 둡니다. (0) | 2020.09.15 |
학교 시간표를 만드는 알고리즘 (0) | 2020.09.15 |
Eclipse에서 코드 블록을 축소하는 방법은 무엇입니까? (0) | 2020.09.15 |