Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Run Emmet commands via other plugins or add them to NPP context menu #5

Open
ArkadiuszMichalski opened this issue Feb 28, 2016 · 9 comments

Comments

@ArkadiuszMichalski
Copy link
Contributor

Emmet has own menu (in old style) so we can't add his options to NPP context menu or run them with other plugins. I test this variants without any positive results:

  • NPPExec, use npp_menucommand Emmet|Wrap With Abbreviationd, find this item but not invoke
  • Python Script, use notepad.runMenuCommand('Emmet', 'Wrap with Abbreviation'), like above, find this item but not invoke
  • editing contextMenu.xml file without success

The only solution what I found is write script for WSH (.js or .vbs) with send keys (shortcut for Emment commands) and run this script with above tools. But it needs to define shortcut for any actions or other scripts (created via jN) which is inconvenient.

Any advice how can I solve this?

@eight04
Copy link
Owner

eight04 commented Feb 28, 2016

You may have to ask jN's author. It sounds like you need to execute some menu commands in jN with other plugins.

@eight04 eight04 closed this as completed Apr 3, 2016
@eight04
Copy link
Owner

eight04 commented Apr 3, 2016

I saw this a minute ago. We can leak an object to global and create some public interface, but I don't know if other plugins can access jN's global.

@eight04 eight04 reopened this Apr 3, 2016
@ArkadiuszMichalski
Copy link
Contributor Author

Other plugin maybe not, but scripts created via JN should have access to all globals. But I see other problem, how can I reconstruct (get access) to command by their names (not ids), I mean both the command directly from the editor and the plugins. In contextMenu.xml file it's not a problem, but Editor.runMenuCmd() operate only on build-in menu command of Notepad++, so I can't rebuild original context menu.

@eight04
Copy link
Owner

eight04 commented Apr 4, 2016

You mean you want to execute the command of other plugins with jN script?

@ArkadiuszMichalski
Copy link
Contributor Author

Yes, but only this what we see in Plugins menu because it's possible in orginal context menu. But I don't even know how can I do this with other NPP built-in command, for example when I record macro I don't have any id for them so I must use in contextMenu.xml all entire path names, like MenuEntryName="Macro" MenuItemName="MyMacro".

Look this comment: sieukrem/jn-npp-plugin#28 (comment)
Unfortunately there is no any example so I don't know how can I use this API with jN script (
if it's possible).

@eight04
Copy link
Owner

eight04 commented Apr 4, 2016

(function(){
    require("lib/User32.dll.js");

    if (!User32.GetMenuItemInfoW) {
        // https://msdn.microsoft.com/de-de/library/windows/desktop/ms647980%28v=vs.85%29.aspx
        // HMENU, UINT, BOOL, LPMENUITEMINFO
        User32.Define("GetMenuItemInfoW", "UINT", "UINT", "BOOL", "LONG_PTR");
    }

    // https://github.com/notepad-plus-plus/notepad-plus-plus/blob/master/PowerEditor/src/MISC/PluginsManager/Notepad_plus_msgs.h#L100
    var NPPM_GETMENUHANDLE = 0x0400 + 1000 + 25,
        NPPPLUGINMENU = 0;

    var menuHandle = User32.SendMessageW(Editor.handle, NPPM_GETMENUHANDLE, NPPPLUGINMENU , 0);

    // https://msdn.microsoft.com/de-de/library/windows/desktop/ms647578(v=vs.85).aspx
    // read buff to object
    function readMII(buff) {
        return {
            cbSize: User32.NativeLibrary.readDWord(buff, 0),
            fMask: User32.NativeLibrary.readDWord(buff, 4),
            fType: User32.NativeLibrary.readDWord(buff, 8),
            fState: User32.NativeLibrary.readDWord(buff, 12),
            wID: User32.NativeLibrary.readDWord(buff, 16),
            hSubMenu: User32.NativeLibrary.readDWord(buff, 20),
            hbmpChecked: User32.NativeLibrary.readDWord(buff, 24),
            hbmpUnchecked: User32.NativeLibrary.readDWord(buff, 28),
            dwItemData: User32.NativeLibrary.readDWord(buff, 32),
            dwTypeData: User32.NativeLibrary.readBSTR(buff, 36),
            cch: User32.NativeLibrary.readDWord(buff, 40),
            hbmpItem: User32.NativeLibrary.readDWord(buff, 44)
        };
    }

    // Create buffer for MenuItemInfo.
    var miiBuff = User32.NativeLibrary.alloc(4 * 12);
    // Set sbSize
    User32.NativeLibrary.writeDWord(miiBuff, 0, 4 * 12);
    // Set dwTypeData to null
    User32.NativeLibrary.writeDWord(miiBuff, 36, 0);
    // Set cch to 0
    User32.NativeLibrary.writeDWord(miiBuff, 40, 0);
    // Set fMask to retrieve menu text
    var MIIM_STRING = 0x00000040;
    User32.NativeLibrary.writeDWord(miiBuff, 4, MIIM_STRING);

    // Get cch
    var result = User32.GetMenuItemInfoW(menuHandle, 0, true, miiBuff);
    if (!result) {
        throw "Failed!";
    }

    // Create text buffer
    var textBuff = User32.NativeLibrary.alloc(readMII(miiBuff).cch + 1);
    User32.NativeLibrary.writeDWord(miiBuff, 36, textBuff);

    // Get text
    var result = User32.GetMenuItemInfoW(menuHandle, 0, true, miiBuff);
    if (!result) {
        throw "Failed!";
    }

    alert(JSON.stringify(textBuff));
})();

This script should get the text on the first item of main menu. But the result text seems wrong, I always lost the last character.

@sieukrem
Copy link

sieukrem commented Apr 6, 2016

You did good job. I adapted your code a little bit.

 ( function(){
    require("lib/User32.dll.js"); 

    if (!User32.GetMenuItemInfoW) {
        // https://msdn.microsoft.com/de-de/library/windows/desktop/ms647980%28v=vs.85%29.aspx
        // HMENU, UINT, BOOL, LPMENUITEMINFO
        User32.Define("GetMenuItemInfoW", "UINT", "UINT", "BOOL", "LONG_PTR");
    }

    // https://github.com/notepad-plus-plus/notepad-plus-plus/blob/master/PowerEditor/src/MISC/PluginsManager/Notepad_plus_msgs.h#L100
    var NPPM_GETMENUHANDLE = 0x0400 + 1000 + 25,
        NPPPLUGINMENU = 0;

    var menuHandle = User32.SendMessageW(Editor.handle, NPPM_GETMENUHANDLE, NPPPLUGINMENU , 0);

    // https://msdn.microsoft.com/de-de/library/windows/desktop/ms647578(v=vs.85).aspx
    // read buff to object
    function readMII(buff) {
        return {
            cbSize: User32.NativeLibrary.readDWord(buff, 0),
            fMask: User32.NativeLibrary.readDWord(buff, 4),
            fType: User32.NativeLibrary.readDWord(buff, 8),
            fState: User32.NativeLibrary.readDWord(buff, 12),
            wID: User32.NativeLibrary.readDWord(buff, 16),
            hSubMenu: User32.NativeLibrary.readDWord(buff, 20),
            hbmpChecked: User32.NativeLibrary.readDWord(buff, 24),
            hbmpUnchecked: User32.NativeLibrary.readDWord(buff, 28),
            dwItemData: User32.NativeLibrary.readDWord(buff, 32),
            dwTypeData: User32.NativeLibrary.readBSTR(buff, 36),
            cch: User32.NativeLibrary.readDWord(buff, 40),
            hbmpItem: User32.NativeLibrary.readDWord(buff, 44)
        };
    }

    // Create buffer for MenuItemInfo.
    var miiBuff = User32.NativeLibrary.alloc(4 * 12);
    // Set sbSize
    User32.NativeLibrary.writeDWord(miiBuff, 0, 4 * 12);
    // Set dwTypeData to null
    User32.NativeLibrary.writeDWord(miiBuff, 36, 0);
    // Set cch to 0
    User32.NativeLibrary.writeDWord(miiBuff, 40, 0);
    // Set fMask to retrieve menu text
    var MIIM_STRING = 0x00000040;
    User32.NativeLibrary.writeDWord(miiBuff, 4, MIIM_STRING);

    // Get cch
    var result = User32.GetMenuItemInfoW(menuHandle, 0, true, miiBuff);
    if (!result) {
        throw "Failed!";
    }

    User32.NativeLibrary.writeDWord(miiBuff, 40, readMII(miiBuff).cch+1);

    // Create text buffer
    var textBuff = User32.NativeLibrary.alloc((readMII(miiBuff).cch-1));
    User32.NativeLibrary.writeDWord(miiBuff, 36, textBuff);

    // Get text
    var result = User32.GetMenuItemInfoW(menuHandle, 0, true, miiBuff);
    if (!result) {
        throw "Failed!";
    }

    alert(textBuff);
})();

@ArkadiuszMichalski
Copy link
Contributor Author

I try this and stuck:

  • above code return plugin name, like "jN Notepad++ Plugin" but how get access to plugin command name (string) which are located in submenu? Even I get command name (string) how can I run them via jN?
  • also I try access to NPP menu by changing NPPPLUGINMENU = 0; to NPPPLUGINMENU = 1; and once again get wrong value, and, as above, don't know how get access to name from submenu (like File>New, File>Open..., File>Close More>Close All to the Left) and finally run them.

@eight04
Copy link
Owner

eight04 commented Apr 7, 2016

https://msdn.microsoft.com/de-de/library/windows/desktop/ms647578(v=vs.85).aspx
increment cch

I didn't read that 😵

To get the item of submenu, maybe by retrieving hSubMenu? haven't tried. To run command, you need the command ID of the menu item. I guess it is wID.

With above code by replacing NPPPLUGINMENU with 1, I can get the first item name of main menu.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants