Handling Ctrl+C in a c++ plugin dialog
-
I know this borders on a generic Win32 coding question, so it’s borderline off-topic. But I’m trying to figure out how to handle Ctrl+C to copy elements from the (as I said I would here)
I am using the main C++ plugintemplate coding style (so more c-like than c++, so not with a separate class for each dialog, just the old-fashioned callback dialog-proc).
My searches have suggested either using TranslateAccelerator (with accelerators defined in the RC file), or just handling WM_KEYDOWN in my dialog procedure.
TranslateAccelerator seems to need to be called from the main message loop (in the GetMessage/TranslateMessage/DispatchMessage) – but I think that’s controlled outside the plugin (at least, the plugintemplate doesn’t have that explicit message loop), so I don’t think that’s a viable option for a plugin (unless I’ve misunderstood, which is quite possible).
So I thought WM_KEYDOWN was a better bet. But when I add that
case WM_KEYDOWN:
to my dialog-proc function, that message never gets received by my procedure, whether I typeCtrl+C
or just a normal keyboard character. I am guessing I am missing something (like some flag in the RC file definition for the dialog and/or the listbox control), but if so, I cannot find it; or maybe it’s a fundamental concept or something else I need to do.If I cannot get past this, I will just add a “copy selected error” button. But
Ctrl+C
would be so much more elegant, so I was hoping a more-experienced plugin programmer could chime in with how to make it work, or at least give me some hints that my internet searches haven’t turned up yet. -
@PeterJones
The reason your DialogProc doesn’t see WM_KEYDOWN is keyboard focus. Windows sends keyboard messages directly to the control that is currently active—in this case, your list control. The parent dialog is never notified.Since your plugin can’t access the main Notepad++ message loop to use accelerators, the correct approach is to tap directly into the message stream of the list control itself. This is what subclassing is for. It lets you create a small, specialized message handler that inspects messages for your control before the default behavior kicks in. It’s a clean, safe, and officially sanctioned way to extend control functionality.
The most robust implementation is a subclass procedure that is completely self-contained. It handles the specific key combination you’re interested in and even cleans itself up automatically when the control is destroyed. This makes your code more modular and easier to maintain.
Here is what such a procedure looks like. It’s the only piece of complex code you need.
static LRESULT CALLBACK ListBoxSubclassProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) { // Check for the universal Ctrl+C signal (works on all keyboard layouts) if (uMsg == WM_CHAR && wParam == 0x03) { CopySelectionFromControl(hWnd); // Your function to copy text return 0; // Event handled } // When the control is destroyed, it automatically removes this subclass if (uMsg == WM_NCDESTROY) { RemoveWindowSubclass(hWnd, ListBoxSubclassProc, uIdSubclass); } // For all other messages, just pass them to the default handler return DefSubclassProc(hWnd, uMsg, wParam, lParam); }
This procedure is activated with a single line in your DialogProc’s WM_INITDIALOG case: SetWindowSubclass(hListBox, ListBoxSubclassProc, 0, 0);. That’s it. Because the subclass cleans itself up, you don’t even need to add code to WM_DESTROY.
-
Well, that got me farther. With some keystrokes, like a normal letter, or a key-combo that’s not assigned to anything in Notepad++ (like
Shift+Ctrl+C
), it will call that subclass function and see the uMsg==WM_CHAR. ButCtrl+C
doesn’t trigger it; and if I try a shortcut that does something obviousl in N++, likeAlt+C
(for the Column Editor).But that reminded me of the recent conversation about shortcut mappings, and so I tried sending the appropriate NPPM_MODELESSDIALOG arguments during my plugin’s init & destroy, and now it can capture
Ctrl+C
(or any other shortcut).Thank you