Est-il un presse-papiers modifiée ou mise à jour de l'événement que je peux y accéder par le biais de C#?
Réponses
Trop de publicités?Pour être complet, voici la commande que j'utilise dans le code de production. Il suffit de glisser de la designer et double-cliquez pour créer le gestionnaire d'événements.
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;
}
}
}
Je pense que vous aurez à utiliser certains p/invoke:
[DllImport("User32.dll", CharSet=CharSet.Auto)]
public static extern IntPtr SetClipboardViewer(IntPtr hWndNewViewer);
Voir cet article sur comment configurer un presse-papiers moniteur en c#
Fondamentalement, vous inscrivez votre application comme un presse-papiers à l'aide de
_ClipboardViewerNext = SetClipboardViewer(this.Handle);
et puis, vous recevrez l' WM_DRAWCLIPBOARD
message, vous pouvez gérer en substituant WndProc
:
protected override void WndProc(ref Message m)
{
switch ((Win32.Msgs)m.Msg)
{
case Win32.Msgs.WM_DRAWCLIPBOARD:
// Handle clipboard changed
break;
// ...
}
}
(Il n'y a plus à faire; les choses qui passent le long du presse-papiers et de la chaîne d'annulation de l'enregistrement de votre point de vue, mais vous pouvez obtenir de l'article)
Ok, donc c'est un vieux post, mais nous avons trouvé une solution qui me semble très simple par rapport à l'ensemble des réponses. Nous sommes à l'utilisation de WPF et nous voulions avoir notre propre Commandes personnalisées (dans un ContextMenu) activer et désactiver si le presse-papiers contient du texte. Il y a déjà un ApplicationCommands.Couper, Copier et Coller et ces commandes répondent correctement à la presse-papiers en train de changer. Donc, nous avons ajouté la suite de Gestionnaire d'événements.
ApplicationCommands.Paste.CanExecuteChanged += new EventHandler(Paste_CanExecuteChanged);
private void Paste_CanExecuteChanged(object sender, EventArgs e) {
ourVariable= Clipboard.ContainsText();
}
Nous sommes réellement le contrôle de la CanExecute sur notre propre Commande de cette façon. Fonctionne pour ce que nous avions besoin et peut-être que ça aidera d'autres.
Découvrez la SetClipboardViewer, ChangeClipboardChain et SendMessage appels d'API.
Voici un bon article qui explique comment le piège presse-papiers les notifications de changement. Et un autre.
Je crois que l'une des premières solutions ne vérifie pas pour un nul sur la méthode 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;
}
}
}