C# 按ctrl+;并将其保存到一个texbox

C# 按ctrl+;并将其保存到一个texbox,c#,save,clipboard,copy-paste,C#,Save,Clipboard,Copy Paste,我想我把剪贴板弄错了,但我想知道或得到一个技巧,我需要如何实现这一点。我想让这个程序在后台运行,每次我复制一些东西,它都会出现在程序中。这样,如果我想回到过去,看看我10分钟前复制的内容,我会在程序中找到它。所以我想我需要把它保存在一个文本文件中。我是如何实现这一点的 当剪贴板更改时,C#通常无法引发事件。您可以从剪贴板读取数据,也可以忙着等待轮询剪贴板,但这些对我来说似乎不是最优的 然而,只要使用一点extern,您就应该能够得到您想要的东西。在子类形式的类中: /// <summary

我想我把剪贴板弄错了,但我想知道或得到一个技巧,我需要如何实现这一点。我想让这个程序在后台运行,每次我复制一些东西,它都会出现在程序中。这样,如果我想回到过去,看看我10分钟前复制的内容,我会在程序中找到它。所以我想我需要把它保存在一个文本文件中。我是如何实现这一点的

当剪贴板更改时,C#通常无法引发事件。您可以从剪贴板读取数据,也可以忙着等待轮询剪贴板,但这些对我来说似乎不是最优的

然而,只要使用一点
extern
,您就应该能够得到您想要的东西。在子类
形式
的类中:

/// <summary>
/// Message id for data being copied to the clipboard
/// </summary>
/// <value>776</value>
private const int WM_DRAWCLIPBOARD = 0x0308;
/// <summary>
/// Message id for a window being removed from the viewer chain
/// </summary>
/// <value>781</value>
private const int WM_CHANGECBCHAIN = 0x030D;
/// <summary>
/// Message id for the window being destroyed
/// </summary>
/// <value>2</value>
private const int WM_DESTROY = 0x0002;
/// <summary>
/// The next window in the clipboard viewer chain
/// </summary>
private IntPtr nextClipboardViewer;

/// <summary>
/// Adds the specified window to the chain of clipboard viewers. Clipboard viewer windows receive a <c>WM_DRAWCLIPBOARD</c>
/// message whenever the content of the clipboard changes.
/// </summary>
/// <param name="hWnd">A handle to the window to be added to the clipboard chain.</param>
/// <returns>If the function succeeds, the return value identifies the next window in the clipboard viewer chain. If an
/// error occurs or there are no other windows in the clipboard viewer chain, the return value is <c>null</c>.</returns>
[DllImport("User32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SetClipboardViewer(IntPtr hWnd);
/// <summary>
/// Removes a specified window from the chain of clipboard viewers.
/// </summary>
/// <param name="hWndRemove">A handle to the window to be removed from the chain. The handle must have been passed to the
/// <see cref="SetClipboardViewer"/> function.</param>
/// <param name="hWndNewNext">A handle to the window that follows the <paramref name="hWndRemove"/> window in the clipboard
/// viewer chain. (This is the handle returned by <see cref="SetClipboardViewer"/>, unless the sequence was changed in response
/// to a <c>WM_CHANGECBCHAIN</c> message.)</param>
/// <returns>The return value indicates the result of passing the <c>WM_CHANGECBCHAIN</c> message to the windows in the
/// clipboard viewer chain. Because a window in the chain typically returns <c>false</c> when it processes <c>WM_CHANGECBCHAIN</c>,
/// the return value from <see cref="ChangeClipboardChain"/> is typically <c>false</c>. If there is only one window in the chain,
/// the return value is typically <c>true</c>.</returns>
[DllImport("User32.dll", CharSet = CharSet.Auto)]
public static extern bool ChangeClipboardChain(IntPtr hWndRemove, IntPtr hWndNewNext);
/// <summary>
/// Sends the specified message to a window or windows. The <c>SendMessage</c> function calls the window
/// procedure for the specified window and does not return until the window procedure has processed the message.
/// </summary>
/// <param name="hwnd">A handle to the window whose window procedure will receive the message.</param>
/// <param name="wMsg">The message to be sent.</param>
/// <param name="wParam">Additional message-specific information.</param>
/// <param name="lParam">Additional message-specific information.</param>
/// <returns>The return value specifies the result of the message processing; it depends on the message sent.</returns>
[DllImport("User32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam);

/// <inheritdoc/>
protected override void WndProc(ref Message m)
{
    if (m.Msg == WM_DRAWCLIPBOARD)
    {
        // The user copied something to the clipboard
        IDataObject clipData = Clipboard.GetDataObject();
        if (clipData.GetDataPresent(DataFormats.Text))
        {
            // Copied data is text
        }

        SendMessage(nextClipboardViewer, m.Msg, m.WParam, m.LParam);
    }
    // Handle necessary native clipboard stuff
    else if (m.Msg == WM_DESTROY)
    {
        // Remove MyForm from the clipboard chain
        ChangeClipboardChain(this.Handle, nextClipboardViewer);
    }
    else if (m.Msg == WM_CHANGECBCHAIN)
    {
        if (m.WParam == nextClipboardViewer)
        {
            nextClipboardViewer = m.LParam;
        }
        else
        {
            SendMessage(nextClipboardViewer, m.Msg, m.WParam, m.LParam);
        }
    }
    else
    {
        base.WndProc(ref m);
    }
}

private void MyForm_Load(object sender, EventArgs e)
{
    // Include MyForm in the clipboard chain
    nextClipboardViewer = SetClipboardViewer(this.Handle);
}
//
///正在复制到剪贴板的数据的消息id
/// 
/// 776
私有常量int WM_DRAWCLIPBOARD=0x0308;
/// 
///正在从查看器链中删除的窗口的消息id
/// 
/// 781
私有常量int WM_CHANGECBCHAIN=0x030D;
/// 
///正在销毁的窗口的消息id
/// 
/// 2
私有常量int WM_DESTROY=0x0002;
/// 
///剪贴板查看器链中的下一个窗口
/// 
私有IntPtr nextClipboardViewer;
/// 
///将指定的窗口添加到剪贴板查看器链中。剪贴板查看器窗口接收WM_DRAWCLIPBOARD
///每当剪贴板的内容发生更改时发送消息。
/// 
///要添加到剪贴板链的窗口句柄。
///如果函数成功,返回值将标识剪贴板查看器链中的下一个窗口。如果
///发生错误或剪贴板查看器链中没有其他窗口,返回值为空。
[DllImport(“User32.dll”,CharSet=CharSet.Auto)]
公共静态外部IntPtr SetClipboardViewer(IntPtr hWnd);
/// 
///从剪贴板查看器链中删除指定的窗口。
/// 
///要从链条上拆下的车窗把手。该句柄必须已传递给
///功能。
///剪贴板中跟随窗口的窗口句柄
///观众链。(这是返回的句柄,除非响应中更改了序列
///到WM_CHANGECBCHAIN消息。)
///返回值表示将WM_CHANGECBCHAIN消息传递到中的窗口的结果
///剪贴板查看器链。因为链中的窗口在处理WM_CHANGECBCHAIN时通常返回false,
///中的返回值通常为false。如果链中只有一个窗口,
///返回值通常为true。
[DllImport(“User32.dll”,CharSet=CharSet.Auto)]
公共静态外部bool changebloardchain(IntPtr hWndRemove、IntPtr hWndNewNext);
/// 
///将指定的消息发送到一个或多个窗口。SendMessage函数调用窗口
///过程,直到窗口过程处理完消息后才返回。
/// 
///其窗口过程将接收消息的窗口的句柄。
///要发送的消息。
///其他特定于消息的信息。
///其他特定于消息的信息。
///返回值指定消息处理的结果;这取决于发送的消息。
[DllImport(“User32.dll”,CharSet=CharSet.Auto)]
公共静态外部IntPtr SendMessage(IntPtr hwnd、int wMsg、IntPtr wParam、IntPtr lParam);
/// 
受保护的覆盖无效WndProc(参考消息m)
{
如果(m.Msg==WM_)
{
//用户将某些内容复制到剪贴板
IDataObject clipData=剪贴板.GetDataObject();
if(clipData.GetDataPresent(DataFormats.Text))
{
//复制的数据是文本
}
SendMessage(nextClipboardViewer、m.Msg、m.WParam、m.LParam);
}
//处理必要的本地剪贴板内容
else if(m.Msg==WM_DESTROY)
{
//从剪贴板链中删除MyForm
ChangeClipboardChain(this.Handle,nextClipboardViewer);
}
else if(m.Msg==WM_CHANGECBCHAIN)
{
if(m.WParam==nextClipboardViewer)
{
nextClipboardViewer=m.LParam;
}
其他的
{
SendMessage(nextClipboardViewer、m.Msg、m.WParam、m.LParam);
}
}
其他的
{
基准WndProc(参考m);
}
}
私有void MyForm_加载(对象发送方,事件参数e)
{
//将MyForm包含在剪贴板链中
nextClipboardViewer=SetClipboardViewer(this.Handle);
}

确保
MyForm\u Load
作为一个适当的事件添加到
表单上(最容易从设计器窗口中添加)。

这个问题太麻烦了:))删除它是最好的方法,第二个最好的方法是尝试改进它。该程序必须不断轮询剪贴板中的内容。它还必须针对非文本内容进行准备。应该是可能的。签出一些已经这样做的开源程序:阅读MSDN上的主题,了解它是如何工作的,以及如何侦听新的剪贴板数据。然后看看你是否想把它翻译成C#。。。(或者你会得到更好的搜索词…)只是一个小提示。通过在WndProc()中捕获WM_DESTROY并将自己从其中的链中移除,您可以摆脱订阅FormClosing()事件的需要。很高兴知道!我承认,我从自己编写的现有应用程序中提取了这段代码,删除了一些无关的部分。在我的应用程序中,我在
\u Load
\u FormClosing
中执行其他操作。WM_DESTROY的值是多少?
private const int WM_DESTROY=0x2