Community
    • Login

    Open with search

    Scheduled Pinned Locked Moved Help wanted · · · – – – · · ·
    35 Posts 5 Posters 8.6k 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.
    • pdanesP
      pdanes @PeterJones
      last edited by

      @PeterJones I tried that, and it seems to be doing something. When I pass the parameters properly, the SendMessage function returns one, when I do something else, it returns zero. However, it still does not launch the Find dialog. What I’m using is this:

      hNppWnd = FindWindow(“Notepad++”, vbNullString)
      i = SendMessage(hNppWnd, 2072, 0, 0)

      which does not throw an error, but nothing happens, or at least, nothing visible. Notepad++ is open in and visible, the proper file is open, but no Find dialog ever appears.

      PeterJonesP 1 Reply Last reply Reply Quote 0
      • PeterJonesP
        PeterJones @pdanes
        last edited by PeterJones

        @pdanes ,

        Per Plugin Communications # NPPM_MENUCOMMAND,

        NPPM_MENUCOMMAND

        Calls all possible Notepad++ menu commands.

        Parameters:####

        wParam [in]
        int, must be zero.

        lParam [in]
        int commandID, see menuCmdID.h for all possible values.

        Return value:
        Returns True

        You sent message ID of 2072, which is NPPM_MENUCOMMAND. So good. But you send lParam of 0, which doesn’t match any of the command ID values, so it won’t run any menu command. You actually have to pick a menu command for it to run.

        To pick the right lParam value for the commandID, you have to look in menuCmdID.h

        Looking at the commands, there is IDM_SEARCH_FIND, which is IDM_SEARCH + 1 = IDM + 3000 + 1 = 40000 + 3000 + 1 = 43001.

        So you should send

        hNppWnd = FindWindow(“Notepad++”, vbNullString)
        i = SendMessage(hNppWnd, 2072, 0, 43001)
        

        In my so-called PerlScript, I can access that correctly using any of

        perl -MWin32::Mechanize::NotepadPlusPlus=:all -le "notepad->menuCommand($NPPIDM{IDM_SEARCH_FIND})"
        perl -MWin32::Mechanize::NotepadPlusPlus=:all -le "notepad->menuCommand(43001)"
        perl -MWin32::Mechanize::NotepadPlusPlus=:all -le "notepad->SendMessage(2072, 0, 43001)"
        perl -MWin32::Mechanize::NotepadPlusPlus=:all -le "Win32::GuiTest::SendMessage( notepad->{_hwnd}, 2072, 0, 43001)"
        

        (getting less abstract with each line, with the final one basically being the equivalent of my modified versin of your VBA code)

        pdanesP 2 Replies Last reply Reply Quote 0
        • pdanesP
          pdanes @PeterJones
          last edited by

          @PeterJones I don’t know what I’m doing wrong - I feel like a little kid that just can’t seem to hit the toilet, no matter how much the adults help me aim.

              hNppWnd = FindWindow("Notepad++", vbNullString)
              i = SendMessage(hNppWnd, 2072, 0, 43001)
          

          Tried this, along with all sort of other variations, like IDM_FILE_OPEN, IDM_FILE_CLOSE, IDM_FILE_SAVEAS and numerous others, from looking up in the menuCmdID.h file. Not one does anything - I’m still at the same place as when I started. NPP starts, opens the file and that’s it. SendMessage acts like it’s working, but nothing happens, no matter what I try.

          PeterJonesP 1 Reply Last reply Reply Quote 0
          • pdanesP
            pdanes @PeterJones
            last edited by

            @PeterJones JESUS!!! I got it. THIS is what finally worked:

                hNppWnd = FindWindow("Notepad++", vbNullString)
                i = SendMessage(hNppWnd, 2072, 0, ByVal 43001)
            

            The ByVal keyword made it work. I have no idea why, but I was flailing, try ing anything I could think of, and that clicked.

            1 Reply Last reply Reply Quote 1
            • PeterJonesP
              PeterJones @pdanes
              last edited by

              @pdanes ,

              I don’t have access to VBA while at home this week, and probably won’t have time to debug this for you when at work next week, so I cannot debug this problem for you.

              My best guess is that you don’t have what you think you have. Has your found a valid hNppWnd? Is SendMessage properly defined in VBA?

              And, with the update posted while I was replying:

              The ByVal keyword made it work

              Ah, yes, VBA defaults to ByRef. I don’t remember using SendMessage from VBA, so I had never been reminded that you would need to force ByVal when sending a value. (They have to allow ByRef in the SendMessage, because sometimes, it is a reference, like when you need a string in wParam or lParam.)

              pdanesP 2 Replies Last reply Reply Quote 1
              • pdanesP
                pdanes @PeterJones
                last edited by

                @PeterJones I thought literals were always passed ByVal anyway, and I’ve never used that keyword in the call - only in the definition. I had no idea it could even be used here, or what the significance is, but I saw it in some code example somewhere, so I tried it.

                Time to do some more reading, looks like.

                Thank you, thank you, thank you. I think I may be able to get it going from here. I’ll post back as I go.

                1 Reply Last reply Reply Quote 2
                • pdanesP
                  pdanes @PeterJones
                  last edited by pdanes

                  @PeterJones Spoke too soon - I’m stuck again. I can’t figure out how to get hold of the search dialog, or address the controls on it. The line:

                      i = SendMessage(hNppWnd, 2072, 0, ByVal 43001)
                  

                  spawns the dialog, but nothing I have tried has returned the handle to it. The lines:

                      i = FindWindow(hNppWnd, vbNullString)
                      hWndNppFind = FindWindowEx(hNppWnd, 0, vbNullString, vbNullString)
                  

                  return a success code of one only when I specify vbNullString in all the parameters. When I put any sort of text into the parameters, including the clearly visible correct title, the calls return zero. The FindWindowEx call does return some sort of number that looks like a window handle, but it’s the wrong one, and when I pause execution before the two lines and manually close the find dialog that I was so excited about finally being able to open with SendMessage, the results are the same, so it’s obviously not getting that dialog. I then used a routine named EnumWindowsProc that I found online, and located the handle to the dialog there, with the exact text of the title that it refuses to find and a different handle number. When I manually put that handle number into this call:

                      i = SendMessage(3804974, WM_SETTEXT, 0, ByVal "Some more text that is pointless, but assists tracking")
                  

                  The number does direct it to the dialog, but the text goes into the dialog’s title bar.

                  I’ve spent the last two days looking up and trying stuff from every API forum and tutorial site I can find, and results zero. The dialog is open, it has a window handle, and using that handle does direct activity to that dialog. But I can’t figure out how to locate it with code, and I can’t figure out how to put text into the search box and fire the search. Can you shed some light on where I’m being dumb this time?

                  Alan KilbornA 1 Reply Last reply Reply Quote 0
                  • Alan KilbornA
                    Alan Kilborn @pdanes
                    last edited by

                    @pdanes

                    spawns the dialog, but nothing I have tried has returned the handle to it

                    A key line for this in the original source is:

                    hFindWnd = FindWindow("#32770", "Find") 'Find dialog handle

                    Perhaps it is strange that you haven’t mentioned 32770 in your discussion?

                    I’ve lurked on this issue, tempted to say something, but then backing off because VB/VBA is not something I’m great at (just don’t do it enough).

                    Since I did speak up, I’m wondering if you are tied to VB in some way, because (sorry) you don’t seem to be a great VB programmer. :-)

                    I ask because I could have given you the same solution, but in Python and definitely working.

                    pdanesP 1 Reply Last reply Reply Quote 0
                    • pdanesP
                      pdanes
                      last edited by

                      @Alan-Kilborn I’m not a great VB programmer - I should think that would be obvious. I’m primarily a database designer and administrator, but I occasionally get asked to do odd things that are outside my specialty, and when I can’t figure out things on my own, I go to the appropriate forums. This is a stand-alone Access app, with VBA driving the details. VBA is not the same as VB, but I am tied to VBA, since that is the entire app. This is a portable, single-file DB, rather than a full-blown client-server system.

                      The line you cite did indeed latch onto the dialog properly - returned the correct handle of 3804974. Thank you. I have not mentioned 32770 because I have not the slightest idea of its significance, or that I needed it. If you have any further advice, on what I need to do to load the search string and fire the search, I would be ecstatic to hear it.

                      1 Reply Last reply Reply Quote 0
                      • pdanesP
                        pdanes @Alan Kilborn
                        last edited by

                        @Alan-Kilborn Where is this ‘original source’ that you mention for 32770?

                        Alan KilbornA 1 Reply Last reply Reply Quote 0
                        • Alan KilbornA
                          Alan Kilborn @pdanes
                          last edited by

                          @pdanes

                          Where is this ‘original source’ that you mention for 32770?

                          The “original source” is the code in the thread that @Terry-R originally pointed you to; and what I assume is your starting point for your current effort.

                          If you have any further advice, on what I need to do to load the search string and fire the search

                          I probably should stay out of it, given my non-expert status in VB. :-)

                          pdanesP 2 Replies Last reply Reply Quote 0
                          • pdanesP
                            pdanes @Alan Kilborn
                            last edited by pdanes

                            @Alan-Kilborn I went back and looked, but still don’t see it. In any case, you seem to know how to do this, or at least you said you could provide a properly working setup in Python. If you really do know how to get hold of the search text box, put something in it and launch the search, would you please be so kind as to post it here? I can slog my way through Python code, to some degree. I’ve built web-scraping gadgets in it, although I am also quite far from being a great Python programmer. But if you can show me the necessary calls, I’ll try to make them functional in VBA.

                            Alan KilbornA 1 Reply Last reply Reply Quote 0
                            • pdanesP
                              pdanes @Alan Kilborn
                              last edited by

                              @Alan-Kilborn Hooray - I got the text into the search box.

                                  hWndNppFind = FindWindowEx(hFindWnd, 0, "ComboBox", vbNullString)
                                  i = SendMessage(hWndNppFind, WM_SETTEXT, 0, ByVal "Some more text that is pointless, but assists tracking")
                              

                              Now trying to click the Searc button. Maybe I’ll get this done after all.

                              pdanesP 1 Reply Last reply Reply Quote 0
                              • pdanesP
                                pdanes @pdanes
                                last edited by pdanes

                                I’m ready to go jump off a bridge. When I use this:

                                    i = SendMessage(hWndNppFind, WM_SETTEXT, 0, ByVal "._HS 68")
                                

                                the search box gets populated correctly. but when I use this:

                                    HSHesla = "._HS 68"
                                    i = SendMessage(hWndNppFind, WM_SETTEXT, 0, ByVal HSHesla)
                                

                                the search box gets populated with heiroglyphics. When I use this:

                                    HSHesla = "._HS 68"
                                    i = SendMessage(hWndNppFind, WM_SETTEXT, 0, HSHesla)
                                

                                I still get heiroglyphics, but different ones. Why the hell does this have to be so damn complicated?

                                pdanesP 1 Reply Last reply Reply Quote 0
                                • pdanesP
                                  pdanes @pdanes
                                  last edited by

                                  Got it, sort of. I can get text into the search box and I figured out how to click to Find button. It works. All I’ve got left is how to get the contents of my variable into the search text box, instead of a constant.

                                  pdanesP 1 Reply Last reply Reply Quote 0
                                  • pdanesP
                                    pdanes @pdanes
                                    last edited by

                                    Got it all, finally. This is what made the text populate correctly from a variable:

                                        i = SendMessage(hWndNppFind, WM_SETTEXT, 0, ByVal CStr(HSHesla))
                                    

                                    Christ on a crutch - this is the most annoying, non-intuitive setup I’ve seen in a long time.

                                    Many thanks to everyone for the tips.

                                    PeterJonesP 1 Reply Last reply Reply Quote 1
                                    • PeterJonesP
                                      PeterJones @pdanes
                                      last edited by

                                      @pdanes said in Open with search:

                                      • this is the most annoying, non-intuitive setup I’ve seen in a long time

                                      This is because you are trying to use VBA to talk to the C-style world. It’s nothing specific to Notepad++, and you would have the same issues talking with any message-based app from VBA.

                                      I only try such gymnastics once every few years, and forget the details between; fortunately, I am able to dig up my old code to remind myself how it works.

                                      But you are making good progress. And soon you will have a working example from which you can base future VBA/C crossovers.

                                      pdanesP 1 Reply Last reply Reply Quote 0
                                      • Alan KilbornA
                                        Alan Kilborn @pdanes
                                        last edited by

                                        @pdanes said in Open with search:

                                        I went back and looked, but still don’t see it.

                                        I guess I’m confused as to what you don’t see.
                                        I’m referring to this exact posting: https://community.notepad-plus-plus.org/post/59785 which has a code-listing with this line of code in it:

                                        hFindWnd = FindWindow("#32770", "Find") 'Find dialog handle

                                        Are we talking about the same thing?
                                        I’m guessing not but I can’t see where we got off track. Hmm.

                                        you said you could provide a properly working setup in Python. If you really do know how to get hold of the search text box, put something in it and launch the search, would you please be so kind as to post it here?

                                        Sure.
                                        It was harder than I thought to extract something presentable. :-(
                                        Normally, I have everything all “complicated” so that I can do this type of thing:

                                        FDA = FindDlgAutomation()
                                        FDA.set_radio(FDA.normalmode_radio_id)
                                        FDA.check_checkbox(FDA.wholeword_check_id, False)
                                        FDA.check_checkbox(FDA.backwarddir_check_id, False)
                                        FDA.check_checkbox(FDA.matchcase_check_id, False)
                                        FDA.check_checkbox(FDA.wraparound_check_id, False)
                                        FDA.check_checkbox(FDA.dothitsnewline_check_id, False)
                                        FDA.check_checkbox(FDA.inselection_check_id, False)
                                        FDA.set_control_text(FDA.findwhat_edit_id, 'foobar')
                                        FDA.press_button(FDA.findallcurrdoc_button_id)
                                        

                                        Clearly that is so “involved” in an “under the hood” sense that it wouldn’t help you.
                                        So I dug in to pull out some of it in simplified form.
                                        Here’s what I came up with for “simple” Python, in the context of the VB example:

                                        # -*- coding: utf-8 -*-
                                        
                                        import ctypes
                                        import time
                                        
                                        BM_CLICK = 0x00F5
                                        WM_SETTEXT = 0x000C
                                        NPPM_MENUCOMMAND = 2072
                                        IDM_SEARCH_FIND = 43001
                                        
                                        find_what_ctrl_id = 1601
                                        find_all_curr_doc_ctrl_id = 1641
                                        
                                        npp_hwnd = ctypes.windll.user32.FindWindowW('Notepad++', 0)
                                        ctypes.windll.user32.SendMessageW(npp_hwnd, NPPM_MENUCOMMAND, 0, IDM_SEARCH_FIND)
                                        time.sleep(0.5)
                                        find_hwnd = ctypes.windll.user32.FindWindowW(0, 'Find')
                                        find_what_hwnd = ctypes.windll.user32.GetDlgItem(find_hwnd, find_what_ctrl_id)
                                        ctypes.windll.user32.SendMessageW(find_what_hwnd, WM_SETTEXT, 0, 'foobar')
                                        find_all_curr_doc_hwnd = ctypes.windll.user32.GetDlgItem(find_hwnd, find_all_curr_doc_ctrl_id)
                                        ctypes.windll.user32.SendMessageW(find_all_curr_doc_hwnd, BM_CLICK, 0, 0)
                                        

                                        The only thing there that is a bit different is that I used the control IDs (1601 and 1641) from the Find dialog. These I originally found HERE.

                                        Note that my code is rather barebones, that is, devoid of error checking that of course should be done in any real program. As it is for illustrative purposes only, adding that in just tends to obscure what is going on. Of course the most obvious thing I didn’t do was to check “hwnd” variables against 0 after obtaining them, to see if they are valid or not.

                                        So it appears in the interim that you got things working – good to hear it.

                                        pdanesP 1 Reply Last reply Reply Quote 1
                                        • pdanesP
                                          pdanes @PeterJones
                                          last edited by

                                          @PeterJones I suppose so. Nothing against Notepad++ - I love it, although I wish they had a “search on startup” option in the command line parsing. I wonder if a suggestion / request for such a feature would land on receptive soil. My main beef is with the clumsiness of the Windows API interface. However, this is not my daily bread – I’m used to working at a much higher level of abstraction than this. Declarative languages like SQL and XPath don’t bother me with these sorts of details – that’s the computer’s job, keeping track of pointers, memory allocation and the like. Such languages either don’t allow mismatched constructs, or deliver some sort of meaningful error message. Accepting an incorrect parameter and merrily trying to do something with it is not good manners in my book. And such tolerance for slop is the weak point in a great many vulnerabilities to malware.

                                          Got to wondering what was special about CStr(), though. Its normal use is to convert a numeric variable to its string representation, but I already have a string, so why should this make a difference? Turns out there is no need for CStr() specifically – other functions do just as well, like Trim$(), Left$() or probably anything. Apparently, calling a function does something like make a local copy, same as what happens when I pass a literal. But in that case, why do I need the ByVal keyword? Both are necessary – if I leave out either the ByVal keyword or wrapping the variable into a function call, it doesn’t work. Leaving out one or the other or both all inject garbage, instead of the proper text. Different garbage in all three cases, so there is some difference in what is happening, but only when I use both does it work properly.

                                          Still, I guess I should be glad it works at all. Appreciate the help.

                                          1 Reply Last reply Reply Quote 1
                                          • pdanesP
                                            pdanes @Alan Kilborn
                                            last edited by

                                            @Alan-Kilborn You’re right, I got lost in the myriad of web pages I had opened and looked for something to help me. It’s there, as you say, only way down near the end. Also, I’m doing this on a laptop. At work, I have three computers and seven monitors on my desk, all linked to a single keyboard/mouse, so I have much more space to spread things out and keep clear what is where. Flipping and scrolling around on a small single screen makes it much more difficult to keep things straight.

                                            Thank you for the code. Studying it will help me get a grip on this. I didn’t mention earlier, I’m also doing this on a non-English machine. So sometimes the find dialog has the title “Find”, and sometimes it’s “Najít”. Haven’t yet tracked down which circumstance makes it use which language, and I’m not sure if it’s worth the bother. So far, I just look for one and if the call is unsuccessful, I look for the other. That seems to work well enough.

                                            Alan KilbornA 2 Replies Last reply Reply Quote 1
                                            • First post
                                              Last post
                                            The Community of users of the Notepad++ text editor.
                                            Powered by NodeBB | Contributors