I'm new to Notepad++ plugin development and I wrote a little command to navigate between files, much like the "jump to definition" function you have for many programming tools.
I'm using this template: https://github.com/npp-plugins/plugintemplate
I have managed to write a command that analyses the word under the cursor and subsequently opens another file, setting the cursor there to a position corresponding to the word found.
I open the file using NPPM_DOOPEN and I set the cursor using SCI_GOTOLINE. This works fine. What does not work, is scrolling to make this line visible and topmost with SCI_SETFIRSTVISIBLELINE.
How do I do that?
Without avail, I've tried a lot of other functions (like SCI_SCROLLCARET, SCI_SETSEL) and I have tried to react to NPPN_BUFFERACTIVATED. While I do get the event (NPPN_BUFFERACTIVATED), it still seems too early. When I send SCI_SETFIRSTVISIBLELINE on a file already open, then Notepad++ jumps correctly.
How to reproduce:
Download the plugin template from above, open PluginDefinition.cpp, there you will find two commands. Empty the body of one them and add:
std::wstring filepath = L"PATH TO A LONG TEXT FILE";
::SendMessage(nppData._nppHandle, NPPM_DOOPEN, 0, (LPARAM)filepath.c_str()); // works
int which = -1;
::SendMessage(nppData._nppHandle, NPPM_GETCURRENTSCINTILLA, 0, (LPARAM)&which);
HWND curScintilla = (which == 0) ? nppData._scintillaMainHandle : ppData._scintillaSecondHandle;
int line = 300; // go to line 300
::SendMessage(curScintilla, SCI_GOTOLINE, line - 1, 0); // works
::SendMessage(curScintilla, SCI_SETFIRSTVISIBLELINE, line - 1, 0); // does NOT work
//::SendMessage(curScintilla, SCI_SCROLLCARET, 0, 0); // works sometimes
I believe NPPM_DOOPEN is asynchronous. When it returns, the Scintilla editor isn't loaded at that time. So, SCI_SETFIRSTVISIBLELINE does work, but only if the file was already open.
You need to wait until Notepad++ finishes loading before triggering scroll & jump messages.
#include <windows.h>
#include <string>
#include "PluginDefinition.h"
extern NppData nppData;
static std::wstring g_filepath;
static int g_targetLine = 0;
static UINT_PTR g_timerId = 0;
VOID CALLBACK ScrollToLineProc(HWND, UINT, UINT_PTR, DWORD) {
KillTimer(NULL, g_timerId);
int wh = -1;
::SendMessage(nppData._nppHandle, NPPM_GETCURRENTSCINTILLA, 0, (LPARAM)&wh);
if (wh == -1) return;
HWND curScintilla = (wh == 0) ? nppData._scintillaMainHandle : nppData._scintillaSecondHandle;
wchar_t currentFile[MAX_PATH];
::SendMessage(nppData._nppHandle, NPPM_GETFULLCURRENTPATH, MAX_PATH, (LPARAM)currentFile);
if (_wcsicmp(currentFile, g_filepath.c_str()) != 0) return;
::SendMessage(curScintilla, SCI_GOTOLINE, g_targetLine - 1, 0);
::SendMessage(curScintilla, SCI_SETFIRSTVISIBLELINE, g_targetLine - 1, 0);
::SendMessage(curScintilla, SCI_SCROLLCARET, 0, 0);
}
void jumpToFile() {
g_filepath = L"PATH TO A LONG TEXT FILE";
g_targetLine = 300;
if (::SendMessage(nppData._nppHandle, NPPM_DOOPEN, 0, (LPARAM)g_filepath.c_str())) {
g_timerId = SetTimer(NULL, 0, 150, ScrollToLineProc);
}
}
void commandMenuInit() {
setCommand(0, TEXT("Jump to File"), jumpToFile, NULL, false);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With