Updated clipboard event multiple times

I am trying to create a global clipboard with multiple values. I used a stack to store values. I am using WinProc()

to grab a global copy operation when I push a value onto the stack. Likewise, I am using the Windows keyboard hook to capture the Ctrl-V (Paste) operation. The code for both functions is shown below. I copied and modified the code from this .

        private int KbHookProc(int nCode, IntPtr wParam, IntPtr lParam)
    {
        if (nCode >= 0)
        {
            var hookStruct = (KbLLHookStruct)Marshal.PtrToStructure(lParam, typeof(KbLLHookStruct));

            // Quick and dirty check. You may need to check if this is correct. See GetKeyState for more info.
            bool ctrlDown = GetKeyState(VK_LCONTROL) != 0 || GetKeyState(VK_RCONTROL) != 0;

            if (ctrlDown && hookStruct.vkCode == 0x56) // Ctrl+V
            {
                if (clipBoardStack.Count > 0)
                {
                    lock (this)
                    {
                        localChange = true;
                        RemoveClipboardFormatListener(this.Handle);     // Remove our window from the clipboard format listener list.
                        System.Threading.Thread.Sleep(200);
                        Clipboard.SetText(clipBoardStack.Pop());
                        AddClipboardFormatListener(this.Handle);
                        System.Threading.Thread.Sleep(200);
                    }

                }

            }
        }

        // Pass to other keyboard handlers. Makes the Ctrl+V pass through.
        return CallNextHookEx(_hookHandle, nCode, wParam, lParam);
    }

      

My WinProc override looks like this. I also copied it from SO but don't remember the link.

        protected override void WndProc(ref Message m)
    {
        base.WndProc(ref m);

        if (m.Msg == WM_CLIPBOARDUPDATE)
        {
            if (!localChange)//Only store the data in stack when it comes from outside. Just to prevent the side effect of Paste Operation
            {
                IDataObject iData = Clipboard.GetDataObject();      // Clipboard data.

                if (iData.GetDataPresent(DataFormats.Text))
                {
                    lock (this)
                    {
                        string text = (string)iData.GetData(DataFormats.Text);
                        clipBoardStack.Push(text);                            
                    }
                }
            }
            else
            {
                localChange = false;
            }
        }

      

The copy operation works well. It fills the stack, but when I use an insert operation it fires the WM_CLIPBOARDUPDATE event. Which makes the stack fill up again with the most recent value.

I think that when I change the value of the Clipboard in the Paste intercept, it fires the WM_CLIPBOARDUPDATE event. I tried unregistering the list, I tried using the flag variable 'localChange', I tried using block () but nothing works.

What can be done to solve it.

+3


source to share


2 answers


You can still listen to clipboard updates, but you need to ignore them when you create them. that is, do not respond to your own echo.

You may be able to use the owner of the clipboard, or you can enter a private clipboard format to "mark" it as yours. Here is an article (long time ago) explaining how to do this, which is designed to tell clipboard viewers NOT to commit data. http://www.clipboardextender.com/developing-clipboard-aware-programs-for-windows/ignoring-clipboard-updates-with-the-cf_clipboard_viewer_ignore-clipboard-format



The main idea of ​​this article is to create a private clipboard format CF_CLIPBOARD_VIEWER_IGNORE and simultaneously add it to the clipboard (in the same open / update / close sequence) where you put the real data. Programs like web browsers, word processors, notepads, etc. don't care. But clipboard viewers (such as your own or mine ClipMate) will see the CF_CLIPBOARD_VIEWER_IGNORE format present on the clipboard and then ignore the data. It is also a way for applications such as password managers to avoid cluttering the clipboard managers with sensitive data.

+3


source


You can register a HotKey (Ctrl-V) with the system so that the system can send control to the HotKey handler in your application. There you can refresh your clipboard.

Since HotKey registration will force the system to notify only your app, so you have control over what you do with the ClipBoard. Later, you will have to send the Ctrl-V combination to the destination (intended) application. This will simulate as if the paste command was issued by the user to the target application.



The downside to this is that you will need to know which application has focus in order to send the keyboard shortcut later.

+1


source







All Articles