Copying file itself into clipboard in Notepad++
-
It can be achieved, but you’d need to use a scripting plugin for Notepad++.
I’ve seen some script code for doing it, but I can’t find a reference to it right now.
I do remember that it involves setting the clipboard data to CF_HDROP format, but that’s about all I can recall.Maybe @Ekopalypse has a working example?
-
@Alexander-Anisimov said in Copying file itself into clipboard in Notepad++:
Hi, there is a command in Hotkeys to copy path to file or filename, and a hotkey can be attributed to that action.
A question: is there a way to copy a file itself, not the path to it? but puttin a file itself (putting it into clipboard) - without leaving Notepad++?Do you want to do a
Ctrl+A
(select-all), and thenCtrl+C
(Copy) or are you seeking something where the path to a file is loaded into the clipboard as withEdit / Copy to Clipboard / Copy Current Full File Path
? Or do you want both the full path plus the file data loaded into a single clipboard element? If both then what’s the delimiter between the path and data? All of these are achievable with Notepad++ plus the Python plugin. -
@mkupper I have an example, I’ve set up a hotkey Ctrl+T to put filepath of a file into clipboard, I need a similar thing for putting the actual file into clipboard, not it’s filepath.
-
are you seeking something where the path to a file is loaded into the clipboard as with Edit / Copy to Clipboard / Copy Current Full File Path? Or do you want both the full path plus the file data loaded into a single clipboard element?
No and no.
What OP wants is analogous to what happens in Windows Explorer when you issue a “Copy” there.
What happens when you issue a “Copy” in Windows Explorer?
Well, nothing you can see, until you “Paste”.
But how can Windows Explorer paste if it doesn’t remember the copy somehow?
The answer is that it puts non-textual “reference(s)” into the clipboard so that it can find these files later.If you issue a “Copy” in Windows Explorer, then activate Notepad++ and “Paste”, does it do anything? Does it paste the pathname of the copied file? No, because what is in the clipboard is not text.
So…OP wants to have an active tab in Notepad++ that he issues some sort of new “copy file” command on (which does NOT copy the text of the file path and does NOT copy the textual contents of the file), then, e.g. activate Windows Explorer, navigate to a folder, issue a “paste” and have the file appear there in the file system.
-
Thank you @Alan-Kilborn. Using “Copy” from Windows Explorer puts 16 blobs of data on the clipboard. I don’t know Python well enough to know if it’s able to generate the blobs or if it would have to be done using a Notepad++ plugin.
A Notepad++ plugin that comes close to what you need is NppExport. It already has code that formats the Notepad++ text into a variety of Windows clipboard formats.
Copy of text from Notepad++,
using Notepad++'s “Get full file path”, and
usingeditor.copyText()
from PythonScript within Notepad++ all generate the same set of four blobs:CountClipboardFormats() returns 4 EnumClipboardFormats() results: Format# Format# NameLen Format Name 13 / 0x000D, 0, $CF_UNICODETEXT$ 16 / 0x0010, 0, $CF_LOCALE$ 1 / 0x0001, 0, $CF_TEXT$ 7 / 0x0007, 0, $CF_OEMTEXT$
Copy of a file from Windows Explorer generates:
CountClipboardFormats() returns 16 EnumClipboardFormats() results: Format# Format# NameLen Format Name 49161 / 0xC009, 10, $DataObject$ 49344 / 0xC0C0, 18, $Shell IDList Array$ 49905 / 0xC2F1, 20, $DataObjectAttributes$ 49981 / 0xC33D, 38, $DataObjectAttributesRequiringElevation$ 15 / 0x000F, 0, $CF_HDROP$ 49367 / 0xC0D7, 15, $DropDescription$ 49158 / 0xC006, 8, $FileName$ 49267 / 0xC073, 12, $FileContents$ 49159 / 0xC007, 9, $FileNameW$ 49348 / 0xC0C4, 20, $FileGroupDescriptorW$ 49362 / 0xC0D2, 20, $DropEffectFolderList$ 49370 / 0xC0DA, 11, $UIDisplayed$ 49345 / 0xC0C1, 20, $Shell Object Offsets$ 49353 / 0xC0C9, 20, $Preferred DropEffect$ 49369 / 0xC0D9, 9, $AsyncFlag$ 49171 / 0xC013, 16, $Ole Private Data$
Someone wanting to emulate Windows Explorer’s copy function would need to figure out the internal format of each of those blobs. It’s still a “project” to figure all that out but I would add the code to the
NppExport
plugin which you can then activate via a keyboard shortcut. Hopefully, the author of NppExport will make the source code available. At present it only seems to be a pre-compiled DLL. -
I’m sorry but I think you are still (mostly) way off base. :-(
OK, since @Ekopalypse hasn’t chimed in, I’m going to go ahead and post this code that I think originated with him and somehow made its way to me, possibly via a third party.
I’m not sure about anything, because I (unusually) have no extra notes about it. :-(I tested this script code and it worked for me under PythonScript 3.x, but I can see some possible holes in the script just giving it a glance-over, so users beware.
It copies the active tab to the clipboard as a file.
import ctypes from ctypes import wintypes CF_HDROP = 15 GHND = 66 OpenClipboard = ctypes.windll.user32.OpenClipboard OpenClipboard.argtypes = [ wintypes.HWND ] OpenClipboard.restype = wintypes.BOOL EmptyClipboard = ctypes.windll.user32.EmptyClipboard EmptyClipboard.argtypes = [] EmptyClipboard.restype = wintypes.BOOL SetClipboardData = ctypes.windll.user32.SetClipboardData SetClipboardData.argtypes = [ wintypes.UINT, wintypes.HANDLE ] SetClipboardData.restype = wintypes.HANDLE CloseClipboard = ctypes.windll.user32.CloseClipboard CloseClipboard.argtypes = [] CloseClipboard.restype = wintypes.BOOL GlobalLock = ctypes.windll.kernel32.GlobalLock GlobalLock.argtypes = [ wintypes.HGLOBAL ] GlobalLock.restype = wintypes.LPVOID GlobalAlloc = ctypes.windll.kernel32.GlobalAlloc GlobalAlloc.argtypes = [wintypes.UINT, ctypes.c_size_t] GlobalAlloc.restype = wintypes.HGLOBAL GlobalUnlock = ctypes.windll.kernel32.GlobalUnlock GlobalUnlock.argtypes = [ wintypes.HGLOBAL ] GlobalUnlock.restype = wintypes.BOOL memcpy = ctypes.cdll.msvcrt.memcpy memcpy.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_size_t] class POINT(ctypes.Structure): _fields_ = [ ('x', wintypes.LONG), ('y', wintypes.LONG) ] class DROPFILES(ctypes.Structure): _fields_ = [ ('pFiles', wintypes.DWORD), ('pt', POINT), ('fNC', wintypes.BOOL), ('fWide', wintypes.BOOL), ] def dump_mem(addr, size): mem = list((ctypes.c_ubyte * size).from_address(addr)) print(mem) def main(): path = ctypes.create_unicode_buffer(notepad.getCurrentFilename()) path_size = ctypes.sizeof(path) df_size = ctypes.sizeof(DROPFILES) total_size = df_size + path_size df = DROPFILES() df.pFiles = df_size df.fWide = True h_global_mem = GlobalAlloc(GHND, total_size) # allocate enough memory to hold the df struct and the full path if h_global_mem: lp_global_mem = GlobalLock(h_global_mem) # lock and get the pointer to the memory memcpy(lp_global_mem, addressof(df), df_size) # first copy the df struct memcpy(lp_global_mem+df_size, addressof(path), path_size) # now copy the full path name dump_mem(lp_global_mem, total_size) GlobalUnlock(h_global_mem) res = OpenClipboard(0) if res: EmptyClipboard() SetClipboardData(CF_HDROP, h_global_mem) CloseClipboard() else: print('ERROR OpenClipboard', res) else: print('ERROR GlobalAlloc', h_global_mem) main()
-
@Alan-Kilborn Is that for Python 3? I got an error with Python 2.7:
Python 2.7.18 (v2.7.18:8d21aa21f2, Apr 20 2020, 13:19:08) [MSC v.1500 32 bit (Intel)] Initialisation took 375ms Ready. Traceback (most recent call last): File "C:\Users\MKupper\AppData\Roaming\Notepad++\plugins\Config\PythonScript\scripts\FileClipboard.py", line 84, in <module> main() File "C:\Users\MKupper\AppData\Roaming\Notepad++\plugins\Config\PythonScript\scripts\FileClipboard.py", line 69, in main memcpy(lp_global_mem, addressof(df), df_size) # first copy the df struct NameError: global name 'addressof' is not defined
-
@Alan-Kilborn - Sorry I’m late to the party, but real life is keeping me very busy at the moment. :-(
I looked through my script, but no, it doesn’t seem to be mine … maybe it’s one of the scripts that fell victim to my hard disk failure and that I hadn’t backed up. But I can’t really remember that I ever needed this either. Anyway … but your script works :)@mkupper - Python doesn’t know where to look for the method. Change
addressof
t0ctypes.addressof
and Iassume
it will work with PS2 too. -
Given the above geneltmen’s exposition, it look slike it does not worth it, and any solution would be too complex to implement for this. Probably just use right mouse button -> open file folder, then ctrl+c
Thanks everybody
-
@Alexander-Anisimov said in Copying file itself into clipboard in Notepad++:
any solution would be too complex to implement for this
Hmm, solution provided.
Set up the ability to run the given script, then assign whatever free keycombo you want for it.
There are details about using scripting HERE. -
@Alan-Kilborn said in Copying file itself into clipboard in Notepad++:
@Alexander-Anisimov said in Copying file itself into clipboard in Notepad++:
any solution would be too complex to implement for this
Hmm, solution provided.
The solution that was provided only puts an
CF_HDROP
format blob into the clipboard. On my WIndows 11 machine that’s not enough information to then do aPaste
in Windows Explorer and for a copy of the file to appear. However, if the OP only needs or desires an CF_HDROP then yes, the PythonScript provided does that.If someone wants or needs for Notepad++ to better emulate the behavior for when someone does a copy/paste of files from one Windows Explorer window to another then the solution will need to include more blobs in the package that’s uploaded into the clipboard. On my Windows 11 machine a “Copy” uploads the 16 blobs that I mentioned in a previous post to this forum thread. Some of those 16 are likely redundant meaning we don’t need all 16 for a paste to work. CF_HDROP is one of the pre-defined clipboard blobs and thus is among the low hanging fruit of the 16. Many of the blobs that Windows Explorer uses are not pre-defined. To inject them into the clipboard as part of a package of blobs you need to first translate the blob name, which is well known, into the current blob numbers being used by Windows Explorer and you add them to the clipboard using the numbers.
The blob numbers change from time to time. For example, today I did a copy from Windows Explorer and while the list of blobs looks the same as what I got a couple of days ago I see that
$DataObjectAttributes$ changed from 49905/0xC2F1 to 49647/0xC1EF and
$DataObjectAttributesRequiringElevation$ changed from 49981/0xC33D to 49997/0xC34D.In looking over the list I believe the numbers assigned to 15 of the 16 blobs will change from time to time. The only one that’s constant is CF_HDROP (blob format number 15/0x000F) which is pre-defined. The numbers change because Windows Explorer (explorer.exe) registers the blob names with the clipboard system and gets a blob number or handle for that name back from the clipboard when you log in. Other background processes also are registering names with the clipboard system and getting handles to them. Blob handle numbers can, and likely will, change when you reboot a machine.
-
@mkupper said in Copying file itself into clipboard in Notepad++:
On my WIndows 11 machine that’s not enough information to then do a Paste in Windows Explorer and for a copy of the file to appear.
Well, exactly that worked for me. And I think it worked for Ekopalypse based on what he said.
When I run the script to “copy” the data, Ditto (a clipboard manager) shows:
(Note that when I took the screenshot, the file-copy was Ditto entry number 2, not 1.)
It sure LOOKS like the copy was a file, from the Ditto data. I’m not sure what the funky characters are, likely binary data that Ditto isn’t interpreting for good presentation to the user.But I’m not “selling” the script as appropriate for everyone; I didn’t write it and haven’t looked super-hard at it. As I said, I was reluctant to post it in the first place, given I didn’t know its origins (I still think it was an Eko creation!).
If some feel the script isn’t robust or doesn’t work, feel free to take on the task of improving it.