• Login
Community
  • Login

Page side by side preview/ feature request

Scheduled Pinned Locked Moved General Discussion
20 Posts 5 Posters 1.0k Views
Loading More Posts
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A
    Alan Kilborn
    last edited by Alan Kilborn Feb 14, 2021, 12:02 AM Feb 14, 2021, 12:01 AM

    Here’s a barebones PythonScript that shows how this could work:

    notepad.menuCommand(MENUCOMMAND.VIEW_CLONE_TO_ANOTHER_VIEW)
    editor2.setFirstVisibleLine(editor1.getFirstVisibleLine() + editor1.linesOnScreen())
    notepad.menuCommand(MENUCOMMAND.VIEW_SYNSCROLLV)
    

    Because Notepad++'s View menu’s Synchronize Vertical Scrolling choice is a toggle, however, the above only works if it is currently off. This is a problem with a few Notepad++ menu commands and scripts.

    I wonder if @Ekopalypse has some ideas about some script code that can read the status of a checkable menu item? Ideally it would depend only upon command-id (e.g. 44035 in this case) and not the text of the menu item (to avoid problems with using N++ in a different localization).

    E 2 Replies Last reply Feb 14, 2021, 1:25 PM Reply Quote 1
    • E
      Ekopalypse @Alan Kilborn
      last edited by Feb 14, 2021, 1:25 PM

      @Alan-Kilborn

      I ASSUME i can be done using GetMenuItemInfoW and MENUITEMINFOW . Will follow up later, probably tomorrow.

      1 Reply Last reply Reply Quote 1
      • E
        Ekopalypse @Alan Kilborn
        last edited by Feb 14, 2021, 2:27 PM

        @Alan-Kilborn

        A quick one, just tested with py3.
        Now I need to shutdown before I get into trouble with my family boss. :-)

        import os
        import ctypes
        from ctypes import wintypes
        
        user32 = ctypes.WinDLL('user32')
        
        MFS_ENABLED = 0x0
        MFS_DISABLED = 0x3
        MIIM_STATE = 1
        MIIM_ID = 2
        MIIM_SUBMENU = 4
        MIIM_STRING = 64
        MFT_STRING = 0
        MFS_ENABLED = 0
        
        MF_BYPOSITION = 0x00000400
        MF_POPUP = 0x00000010
        
        class MENUITEMINFO(ctypes.Structure):
            ''' Implements the winapi MENUITEMINFO structure'''
            _fields_ = [('cbSize', wintypes.UINT),
                        ('fMask',  wintypes.UINT),
                        ('fType',  wintypes.UINT),
                        ('fState',  wintypes.UINT),
                        ('wID',  wintypes.UINT),
                        ('hSubMenu',  wintypes.HMENU),
                        ('hbmpChecked',  wintypes.HBITMAP),
                        ('hbmpUnchecked', wintypes.HBITMAP),
                        ('dwItemData',  wintypes.LPVOID),
                        ('dwTypeData',  wintypes.LPWSTR),
                        ('cch',  wintypes.UINT),
                        ('hbmpItem',  wintypes.HBITMAP),]
        
        main_menu = notepad.getMenuHandle(1)
        view_menu = user32.GetSubMenu(main_menu, 3)
        menu_items = user32.GetMenuItemCount(view_menu)
        print(menu_items)
        
        for pos in range(menu_items):
            mii = MENUITEMINFO()
            mii.cbSize = ctypes.sizeof(mii)
            mii.fMask = MIIM_ID | MIIM_STATE
            # mii.fType = None
            mii.dwTypeData = None
            lpmii = ctypes.byref(mii)
        
            user32.GetMenuItemInfoW(view_menu, pos, True, lpmii)
            for field in mii._fields_:
                if mii.wID == 44035:
                    print('State:', mii.fState)
                    break
        
        A 2 Replies Last reply Feb 14, 2021, 4:11 PM Reply Quote 4
        • A
          Alan Kilborn @Ekopalypse
          last edited by Feb 14, 2021, 4:11 PM

          @Ekopalypse said in Page side by side preview/ feature request:

          A quick one, just tested with py3.

          Nice – works fine!
          Thank you.

          Now I need to shutdown before I get into trouble with my family boss

          Way worse than the Monday thru Friday boss, when you get their ire up!
          Go man go!

          1 Reply Last reply Reply Quote 2
          • A
            Alan Kilborn @Ekopalypse
            last edited by Feb 15, 2021, 4:32 PM

            @Ekopalypse

            I turned your script into the following recursive function that finds a specified id:

            def menu_search_for_specified_id(menu_handle, id_to_find):  # returns ( direct-menu-handle, position-on-menu )
                menu_item_count = user32.GetMenuItemCount(menu_handle)
                for menu_pos in range(menu_item_count):
                    sub_menu_handle = user32.GetSubMenu(menu_handle, menu_pos)
                    if sub_menu_handle != 0:
                        (h, p) = menu_search_for_specified_id(sub_menu_handle, id_to_find)
                        if h != 0: return (h, p)
                    else:
                        mii = MENUITEMINFO()
                        mii.cbSize = ctypes.sizeof(mii)
                        mii.fMask = MIIM_ID
                        mii.dwTypeData = None
                        lpmii = ctypes.byref(mii)
                        user32.GetMenuItemInfoW(menu_handle, menu_pos, True, lpmii)
                        if mii.wID == id_to_find: return (menu_handle, menu_pos)
                return (0, 0)  # nothing found
            

            I’ll keep going with a final solution for the OP’s request, that uses this…interested parties please check back later. :-)

            1 Reply Last reply Reply Quote 2
            • A
              Amit
              last edited by Feb 15, 2021, 4:57 PM

              • You can Clone the text document to the other view. (Dual View).
              • Scroll down to about page length.
              • And then use Synchronized Vertical Scrolling feature to have Two-Page View in Notepad++.

              This is not a fully automated feature but one that you can do it very easily.

              This video shows how you can use Synchronized Vertical/horizontal scrolling feature in Notepad++. Hope it helps.

              (disclaimer: I am the owner of this Notepad++ YouTube Channel).

              E 1 Reply Last reply Feb 15, 2021, 5:24 PM Reply Quote 0
              • E
                Ekopalypse @Amit
                last edited by Feb 15, 2021, 5:24 PM

                @Amit - that is what @Alan-Kilborn suggested first, isn’t it?

                1 Reply Last reply Reply Quote 1
                • A
                  Alan Kilborn
                  last edited by Feb 15, 2021, 6:08 PM

                  I found time sooner than I thought to integrate the menu-search function into the main code for this thread’s topic.

                  Here’s a replacement script; obviously, quite a bit more complicated.
                  But, due to the virtues of encapsulation, the run() function looks very much like the original, simpler script (the first script provided in this thread).

                  I call the script CloneActiveDocAndCreateDualPageView.py and here’s its code:

                  # -*- coding: utf-8 -*-
                  
                  from Npp import editor, notepad, MENUCOMMAND
                  import ctypes
                  from ctypes import wintypes
                  
                  user32 = ctypes.WinDLL('user32')
                  
                  MIIM_STATE = 1
                  MIIM_ID = 2
                  MFS_DISABLED = 0x3
                  MFS_CHECKED = 0x8
                  
                  class MENUITEMINFO(ctypes.Structure):
                      _fields_ = [
                          ('cbSize', wintypes.UINT),
                          ('fMask', wintypes.UINT),
                          ('fType', wintypes.UINT),
                          ('fState', wintypes.UINT),
                          ('wID', wintypes.UINT),
                          ('hSubMenu', wintypes.HMENU),
                          ('hbmpChecked', wintypes.HBITMAP),
                          ('hbmpUnchecked', wintypes.HBITMAP),
                          ('dwItemData', wintypes.LPVOID),
                          ('dwTypeData', wintypes.LPWSTR),
                          ('cch', wintypes.UINT),
                          ('hbmpItem', wintypes.HBITMAP),
                      ]
                  
                  class CADACDPV(object):
                  
                      def __init__(self):
                          pass
                  
                      def menu_search_for_specified_id(self, menu_handle, id_to_find):  # returns ( direct-menu-handle, position-on-menu )
                          menu_item_count = user32.GetMenuItemCount(menu_handle)
                          for menu_pos in range(menu_item_count):
                              sub_menu_handle = user32.GetSubMenu(menu_handle, menu_pos)
                              if sub_menu_handle != 0:
                                  (h, p) = self.menu_search_for_specified_id(sub_menu_handle, id_to_find)
                                  if h != 0: return (h, p)
                              else:
                                  mii = MENUITEMINFO()
                                  mii.cbSize = ctypes.sizeof(mii)
                                  mii.fMask = MIIM_ID
                                  mii.dwTypeData = None
                                  lpmii = ctypes.byref(mii)
                                  user32.GetMenuItemInfoW(menu_handle, menu_pos, True, lpmii)
                                  if mii.wID == id_to_find: return (menu_handle, menu_pos)
                          return (0, 0)  # nothing found
                  
                      def view_menu_sync_vertical_scroll_not_on(self):
                          npp_main_menu_handle = notepad.getMenuHandle(1)
                          (owner_menu, pos_in_owner_menu) = self.menu_search_for_specified_id(
                                  npp_main_menu_handle, int(MENUCOMMAND.VIEW_SYNSCROLLV))
                          if owner_menu != 0:
                              mii = MENUITEMINFO()
                              mii.cbSize = ctypes.sizeof(mii)
                              mii.fMask = MIIM_STATE
                              mii.dwTypeData = None
                              lpmii = ctypes.byref(mii)
                              user32.GetMenuItemInfoW(owner_menu, pos_in_owner_menu, True, lpmii)
                              if not (mii.fState & MFS_DISABLED) and not (mii.fState & MFS_CHECKED):
                                  return True
                          return False
                  
                      def run(self):
                          notepad.menuCommand(MENUCOMMAND.VIEW_CLONE_TO_ANOTHER_VIEW)
                          editor2.setFirstVisibleLine(editor1.getFirstVisibleLine() + editor1.linesOnScreen())
                          if self.view_menu_sync_vertical_scroll_not_on():
                              notepad.menuCommand(MENUCOMMAND.VIEW_SYNSCROLLV)
                  
                  if __name__ == '__main__': CADACDPV().run()
                  
                  1 Reply Last reply Reply Quote 2
                  • A
                    Alan Kilborn
                    last edited by Alan Kilborn Feb 15, 2021, 6:14 PM Feb 15, 2021, 6:12 PM

                    @Ekopalypse

                    One thing I noticed… In the code you provided, you called:

                    notepad.getMenuHandle(1)

                    and it works to get the main-menu handle (I suppose! because the rest of the logic works!).

                    But the documentation for this says 0 should be the main menu:

                    507731ce-419d-4953-80dd-f062f40fa196-image.png

                    Is my PythonScript documentation simply out-of-date in this regard?
                    Or…?

                    E 1 Reply Last reply Feb 15, 2021, 6:24 PM Reply Quote 1
                    • E
                      Ekopalypse @Alan Kilborn
                      last edited by Feb 15, 2021, 6:24 PM

                      @Alan-Kilborn

                      Not sure if this is an issue with PS code or documentation?
                      But yes, 1 seems to return the main and 0 the plugin handle.

                      P 1 Reply Last reply Feb 15, 2021, 6:37 PM Reply Quote 2
                      • P
                        PeterJones @Ekopalypse
                        last edited by Feb 15, 2021, 6:37 PM

                        @Ekopalypse said in Page side by side preview/ feature request:

                        @Alan-Kilborn

                        Not sure if this is an issue with PS code or documentation?
                        But yes, 1 seems to return the main and 0 the plugin handle.

                        When I implemented in perl , I used 1 for main and 0 for plugin. The NPPM_GETMENUHANDLE docs agree that 1 is main.

                        The PS docs are wrong.

                        1 Reply Last reply Reply Quote 2
                        • O
                          overstop
                          last edited by Feb 15, 2021, 11:13 PM

                          When reading a book, you have lelf and right page open thus I was thinking in np++ this book view side by side would be a natural option to have.

                          1 Reply Last reply Reply Quote 0
                          18 out of 20
                          • First post
                            18/20
                            Last post
                          The Community of users of the Notepad++ text editor.
                          Powered by NodeBB | Contributors