I named this little program FishClip, as an homage to the short fish memory myth 😀 What good this program is? This gif should explain everything:
FishClip allows you to access your previous clipboard content. I wrote this last year because i had the task at work, to insert some data into a new database with dirrefent frontend and this tool helped me alot giving me a second Clipboard.
For the problem, how to paste the older Clipboard text, i used the keyboard shortcut: “CTRL + B” , because it is just next to V in the keyboardlayout, but the “B” can be interpreted as the first letter of “BACK” aswell 😛
This program is a perfect usage example of our SuperKeylogger component, wherewith i implemented the listening and reacting to the keyboard shortcut.
Download Sources inc. Binary
Some details about the implementation:
For manipulating the clipboard, these lines do the magic:
[...] System.Windows.Forms.Clipboard.SetDataObject(OldClipBoard); SendKeys.SendWait("^v"); //sends crtl v to the active appl. System.Windows.Forms.Clipboard.SetDataObject(CurrentClipBoard); [...] |
That was pretty simple but for getting informed about clipboard changes and buffering them in the “OldClipBoard” variable, i needed to register the program as a Clipboard viewer:
[...] /// <summary> /// Register this form as a Clipboard Viewer application /// </summary> private void RegisterClipboardViewer() { _ClipboardViewerNext = RAD.ClipMon.Win32.User32.SetClipboardViewer(this.Handle); } ... and overrode the WndProc method, to handle the Clipboard Event: ... protected override void WndProc(ref Message m) { switch ((RAD.ClipMon.Win32.Msgs)m.Msg) { // // The WM_DRAWCLIPBOARD message is sent to the first window // in the clipboard viewer chain when the content of the // clipboard changes. This enables a clipboard viewer // window to display the new content of the clipboard. // case RAD.ClipMon.Win32.Msgs.WM_DRAWCLIPBOARD: if (!itsME) { if (CurrentClipBoard == null) { //CurrentClipBoard = Clipboard.GetDataObject(); CurrentClipBoard = (string)Clipboard.GetDataObject().GetData(DataFormats.Text); } else { OldClipBoard = (string)CurrentClipBoard.Clone(); CurrentClipBoard = (string)Clipboard.GetDataObject().GetData(DataFormats.Text); //CurrentClipBoard = Clipboard.GetDataObject(); } } //GetClipboardData(); // // Each window that receives the WM_DRAWCLIPBOARD message // must call the SendMessage function to pass the message // on to the next window in the clipboard viewer chain. // RAD.ClipMon.Win32.User32.SendMessage(_ClipboardViewerNext, m.Msg, m.WParam, m.LParam); break; // // The WM_CHANGECBCHAIN message is sent to the first window // in the clipboard viewer chain when a window is being // removed from the chain. // case RAD.ClipMon.Win32.Msgs.WM_CHANGECBCHAIN: // When a clipboard viewer window receives the WM_CHANGECBCHAIN message, // it should call the SendMessage function to pass the message to the // next window in the chain, unless the next window is the window // being removed. In this case, the clipboard viewer should save // the handle specified by the lParam parameter as the next window in the chain. // // wParam is the Handle to the window being removed from // the clipboard viewer chain // lParam is the Handle to the next window in the chain // following the window being removed. if (m.WParam == _ClipboardViewerNext) { // If wParam is the next clipboard viewer then it // is being removed so update pointer to the next // window in the clipboard chain // _ClipboardViewerNext = m.LParam; } else { RAD.ClipMon.Win32.User32.SendMessage(_ClipboardViewerNext, m.Msg, m.WParam, m.LParam); } break; default: // // Let the form process the messages that we are // not interested in // base.WndProc(ref m); break; } } [...] |
Download Sources for more info.