剪贴板侦听器事件被调用两次

时间:2012-04-29 16:17:50

标签: c# clipboard

我想在剪贴板中保存更改。所以我注册了我的应用程序以获得剪贴板发生的所有更改。

使用

    [DllImport("User32.dll")]
    protected static extern bool AddClipboardFormatListener(int hwnd);

然后

protected override void WndProc(ref Message m)
    {
switch (m.Msg)
        {
            case WM_CLIPBOARDUPDATE:
                OnClipboardChanged();
                break;
             ...
        }
     }

private void OnClipboardChanged()
{
    if (Clipboard.ContainsText())
        {
         MessageBox.Show(Clipboard.GetText().ToString());
        }
}

问题是: 从visual studio或firefox等应用程序复制文本时,OnClipboardChanged()函数有时会被调用两次或三次。

我认为那些应用程序会将数据写入不同格式的剪贴板,这就是为什么函数不止一次被调用。 但是,如果因为多次调用OnClipboardChanged(),我将如何阻止保存相同的数据呢?

2 个答案:

答案 0 :(得分:7)

因为他们多次打开/关闭剪贴板。我以前见过这样的疯狂。复制图表时,Excel用于执行24个单独的操作 而不是这个(伪代码):

openClipboard
for each format {
  place data on clipboard(format)
}
closeClipboard

他们可能会这样做:

for each format {
  openClipboard
  place data on clipboard(format)
  closeClipboard
}

更新:通常的缓解策略是避免对每次更新做出反应,并在经过合理的“结算时间”后对LAST更新作出反应而不再进行剪贴板通知。 500毫秒通常是足够的。

答案 1 :(得分:0)

防止多次呼叫剪贴板

private int _i = 0;
private int i
{
    get
    {
        async void setI()
        {
            await Task.Run(() =>
            {
                Thread.Sleep(20);
                i = 0;
            }
            );
        }
        setI();
        return _i;
    }
    set
    {
        _i = value;
    }
}
private IntPtr HwndHandler(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam, ref bool handled)
{
    if (msg == WM_CLIPBOARDUPDATE)
    {
        if(i<1)
        {
            this.ClipboardUpdate?.Invoke(this, new EventArgs());
            i++;
        }
    }
    handled = false;
    return IntPtr.Zero;
}