Way to tell if clipboard has column-block in it before pasting?
-
Hello all,
Is there a way to tell if clipboard has column-block in it without actually pasting? I’m speaking in a Pythonscript context…can I tell before I do an editor.paste() function call if what I will be pasting is something that was a column-block selection at the point it was copied to the clipboard?
Thanks!
-
more or less - depends what exactly should be done.
What comes first into my mind is using editor.selectionIsRectangle.
If it returns True it is column mode but this of course means the selection is
still active.If this doesn’t answer your question you may provide more infos how your script
should work exactly.Cheers
Claudia -
Thank you for your reply. I was thinking in terms of possibly the selection being made some time ago, i.e., not currently active, maybe there is another selection currently active for drag-and-drop movement purpose…the point is, nothing has been copied to the clipboard since the column block was. So the column block is still there, and N++ knows it…but can I also know it from my script somehow?
-
actually I think npp doesn’t know it but scintilla does.
In theory you should be able to do it
- Install a clipboard watcher (ctypes and windows api required)
- whenever clipboard data changes, check if selection was rectangle
But I still don’t get the point why it is necessary to do it as scintilla is handling it for you.
Cheers
Claudia -
Hi Claudia, I forgot about this for a while. :(
But now I’m interested again.
I looked up how to install a clipboard viewer in the chain using C and the Windows API, and I am a little familiar with Python’s ctypes, but I don’t really see how to put it all together. The first thing I’m confused on is the hwnd I would use…but I’m sure there’s more. Can you possibly show me how to do this? TIA…
-
Hi Alan,
I guess it is the hwnd from npp which you can get by using FindWindow API call.
and in order to receive the WM_CHANGECBCHAIN and WM_DRAWCLIPBOARD messages
you need to register a hook like I did here.Don’t forget to pass the message to the next viewer in chain like described in this example.
Note, there is also an win32clipboard module available which could make it more easy just make sure
it is installed in a directory which is resolved by sys.path.I’m kinda unsure how a “linux” clipboard would act but let me know if I should give it a try.
Cheers
Claudia -
@Alan-Kilborn & @Claudia-Frank ,
Here’s HookForClipboardUpdate.py that provides the desired functionality.
import ctypes, os from ctypes.wintypes import LONG, HWND, UINT, WPARAM, LPARAM SetWindowLong = ctypes.windll.user32.SetWindowLongA CallWindowProc = ctypes.windll.user32.CallWindowProcA FindWindow = ctypes.windll.user32.FindWindowA AddClipboardFormatListener = ctypes.windll.user32.AddClipboardFormatListener RemoveClipboardFormatListener = ctypes.windll.user32.RemoveClipboardFormatListener IsClipboardFormatAvailable = ctypes.windll.user32.IsClipboardFormatAvailable WndProcType = ctypes.WINFUNCTYPE(LONG, HWND, UINT, WPARAM, LPARAM) GWL_WNDPROC = -4 WM_CLIPBOARDUPDATE = 0x31D CF_TEXT = 1 CF_UNICODETEXT = 13 class Hook(): def __init__(self): self.nppHandle = FindWindow('Notepad++', None) def register(self): self.newWndProc = WndProcType(self.MyWndProc) self.oldWndProc = SetWindowLong(self.nppHandle, GWL_WNDPROC, self.newWndProc) console.editor.setProperty('oldWndProc', self.oldWndProc) AddClipboardFormatListener(self.nppHandle) print "registered" def unregister(self): self.prevWndProc = console.editor.getProperty('oldWndProc') dummy = SetWindowLong(self.nppHandle, GWL_WNDPROC, int(self.prevWndProc)) RemoveClipboardFormatListener(self.nppHandle) print "unregistered" def MyWndProc(self, hWnd, msg, wParam, lParam): if msg == WM_CLIPBOARDUPDATE: self.clipboardUpdate() return CallWindowProc(self.oldWndProc, hWnd, msg, wParam, lParam) def clipboardUpdate(self): print "got clipboard update" if IsClipboardFormatAvailable(CF_TEXT) or IsClipboardFormatAvailable(CF_UNICODETEXT): print "clipboard contains text" print "selection is {}rectangular".format('' if editor.selectionIsRectangle() else 'NOT ') _hook = Hook() if console.editor.getProperty('Hookstatus') != '1': console.editor.setProperty('Hookstatus', '1') _hook.register() else: console.editor.setProperty('Hookstatus', '0') _hook.unregister()
@Alan-Kilborn , at the point where the above program prints whether or not the clipboard text is rectangular or not, set a global variable that reflects the setting, that your other script(s) can then query.
If this (or ANY) posting was useful, don’t post a “thanks”, just upvote ( click the
^
in the^ 0 v
area on the right ). -
This post is deleted! -
-
@Alan-Kilborn said in Way to tell if clipboard has column-block in it before pasting?:
Is there a way to tell if clipboard has column-block in it without actually pasting?
I came across this question while searching for an answer to the same question (though for C++, not python).
I knew the notion that Scintilla just remembers what was last copied had to be wrong — it’s stored in the clipboard somehow. Two simple tests demonstrate this:
-
Select and copy a rectangular selection in Notepad++. Close Notepad++. Open it again, open a file with multiple lines of text already in it and paste. The paste is rectangular.
-
Select and copy a column selection in Visual Studio. Open Notepad++, open a file with multiple lines of text already in it and paste. The paste is rectangular.
The answer is that both Scintilla and Visual Studio indicate a column selection by registering an additional clipboard format as a signal.
This code hasn’t been tested thoroughly yet and probably is missing an error check or two, but roughly, it works this way:
CLIPFORMAT cfColumnSelect = static_cast<CLIPFORMAT>(RegisterClipboardFormat(L"MSDEVColumnSelect")); if (IsClipboardFormatAvailable(cfColumnSelect) && OpenClipboard(0)) { HANDLE clipboardHandle = GetClipboardData(CF_UNICODETEXT); wchar_t* clipboardData = static_cast<wchar_t*>(GlobalLock(clipboardHandle)); std::wstring clipboardString(clipboardData); GlobalUnlock(clipboardHandle); CloseClipboard(); // clipboard data is in clipboardString; examine here as needed }
-
-
@Coises said:
Curiously, because this current topic is really focused on “Way to tell if clipboard has column-block in it before pasting?” (from its title), it doesn’t, until @Coises posted, reference
MSDEVColumnSelect
.However, these topics do:
- https://community.notepad-plus-plus.org/topic/17272 Mar 11, 2019, 1:28 PM posting
- https://community.notepad-plus-plus.org/topic/19643 Jul 9, 2020, 1:56 PM (in script listing)
And, Scintilla code discusses it, too, HERE.