Open with search
-
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.
-
@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.
-
@Alan-Kilborn Where is this ‘original source’ that you mention for 32770?
-
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. :-)
-
@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-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.
-
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?
-
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.
-
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.
-
@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.
-
@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.
-
@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.
-
@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.
-
@pdanes said in Open with search:
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…
Perhaps this?:
-
Just a few more thoughts:
I’m not seeing the entirety of your code, but the code that has been discussed to this point is somewhat incomplete. By that I mean that it has been a rather “bare” search where only the “Find what” box in Notepad++ has been configured.
What about the other settings? For example, what is the setting of the Match case checkbox when the search is initiated? What about the Search mode? And the Whole word checkbox? These things can easily cause a search not to find what you are intending, unless they are for-sure set to the correct thing (and this probably means coding them to set states). (I hint at this when I showed my “FDA” code in a previous post.)
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
I would say it likely would not be well-received, meaning it is something that wouldn’t get implemented.
But you can try if you’d like by opening an “issue”.
See HERE for some info on exactly how to do that.There are ways to write (different) Python code (called “script code”) that runs inside Notepad++. (The Python I showed earlier runs from outside Notepad++). This could be exploited to pass a special custom command-line parameter to Notepad++ that could populate the Find’s Find what box and start a search, thus achieving what you desire without having to ask the Notepad++ developers to change anything about the program itself.
Thus instead of the VB you’ve been doing, you’d just have to invoke Notepad++ with a command line; here’s a possible example:
c:\wherever\notepad++.exe c:\myfile.txt -zzzFoo
which could be made to search
c:\myfile.txt
for the textFoo
when run externally. Here-zzz
is just an example command-line parameter; a real-world one would make more intuitive sense.seven monitors on my desk
Heaven! I only have four right now. Poor me. :-(
I’m used to working at a much higher level of abstraction than this. Declarative languages … 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.
Well, it greatly depends upon what level you want/need to work at, to accomplish what you desire. The “negatives” you point out are all “positives” when the programmer needs a high-degree of control or power over a task. But don’t “pooh-pooh” that kind of power just because you don’t like programming that way – a lot of things wouldn’t be possible without it, including things like Notepad++. :-)
-
@Alan-Kilborn said in Open with search:
@pdanes said in Open with search:
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…
Perhaps this?:
No, it changes in mid-stream. When I first call it, the dialog opens with “Find”, but after a while, it switches on its own to “Najít”. I haven’t (yet, anyway) taken the trouble to find out exactly when, or see if I can isolate the exact cause - I’ve been too busy just trying to get it working at all.
-
@Alan-Kilborn said in Open with search:
Just a few more thoughts:
I’m not seeing the entirety of your code, but the code that has been discussed to this point is somewhat incomplete. By that I mean that it has been a rather “bare” search where only the “Find what” box in Notepad++ has been configured.
What about the other settings? For example, what is the setting of the Match case checkbox when the search is initiated? What about the Search mode? And the Whole word checkbox? These things can easily cause a search not to find what you are intending, unless they are for-sure set to the correct thing (and this probably means coding them to set states). (I hint at this when I showed my “FDA” code in a previous post.)
Yes, these other things I’m also going take a look at. I don’t think it will be a problem, since the end user is not exactly a power user – he is unlikely to use any of these options. Nonetheless, you are correct in that having them set improperly could cause my searches to fail, and I intend to set them properly. I think your code will go a long ways towards helping me get that done. It’s just that so far, I have been concentrating on getting it working at all, so I have only the bare bones necessary to make it happen. Now that it works, it’s time to make it fit for public consumption.
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
I would say it likely would not be well-received, meaning it is something that wouldn’t get implemented.
But you can try if you’d like by opening an “issue”.
See HERE for some info on exactly how to do that.There are ways to write (different) Python code (called “script code”) that runs inside Notepad++. (The Python I showed earlier runs from outside Notepad++). This could be exploited to pass a special custom command-line parameter to Notepad++ that could populate the Find’s Find what box and start a search, thus achieving what you desire without having to ask the Notepad++ developers to change anything about the program itself.
Thus instead of the VB you’ve been doing, you’d just have to invoke Notepad++ with a command line; here’s a possible example:
c:\wherever\notepad++.exe c:\myfile.txt -zzzFoo
which could be made to search
c:\myfile.txt
for the textFoo
when run externally. Here-zzz
is just an example command-line parameter; a real-world one would make more intuitive sense.Okay, I didn’t know you could do that. Do they have a real Python interpreter built into Notepad? That’s some text editor. Of course, MSWord has VBA built in, so I guess I shouldn’t be all that surprised. And if such a capability is already available, probably pestering the developers is a waste of time.
seven monitors on my desk
Heaven! I only have four right now. Poor me. :-(
It helps that I am the single-handed IT department for this outfit. Almost all computer gear here crosses my desk, and people visit me a lot for help with different things. Having a big enough work surface to accommodate all my work, plus all the other odd stuff I do for others is rather important. I also have an extra mouse next to the guest chair, so people don’t have to reach over me if we’re jointly fiddling with something.
I’m used to working at a much higher level of abstraction than this. Declarative languages … 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.
Well, it greatly depends upon what level you want/need to work at, to accomplish what you desire. The “negatives” you point out are all “positives” when the programmer needs a high-degree of control or power over a task. But don’t “pooh-pooh” that kind of power just because you don’t like programming that way – a lot of things wouldn’t be possible without it, including things like Notepad++. :-)
Oh, not at all. I started off programming in UNIVAC 9300 and PDP/11 assembly language, many eons ago, and I still do a good bit of procedural work in VBA, programming odd jobs for one-off projects in Access, Word and Excel, as well as smatterings of things in VBScript, Python, Ruby and other tools, as various odd jobs crop up. I got involved with Scala a while back, because I found the language utterly fascinating, but I couldn’t come up with anything to use it for, so I eventually quit Scala for lack of a purpose.
What bugs me about Windows APIs is not the power – it’s the (seemingly, to me, anyway) haphazard way some of this stuff is implemented. Like my issue with having to wrap my variable into some, any, random function call in order for the data to get passed properly. Maybe there is a clean way to do it – AddressOf or some such keyword that I don’t know, without having to call a function that is actually completely pointless. That’s the kind of thing that drives programmers bonkers when they have to look at other people’s code, including maybe my future self, at this very thing.
I still wonder what’s going on there. Probably someone with more knowledge of VB’s guts and API peculiarities could shed some light on it.
-
@pdanes said in Open with search:
it changes in mid-stream. When I first call it, the dialog opens with “Find”, but after a while, it switches on its own to “Najít”. I haven’t (yet, anyway) taken the trouble to find out exactly when, or see if I can isolate the exact cause - I’ve been too busy just trying to get it working at all
Well THAT is certainly strange!
Do they have a real Python interpreter built into Notepad? That’s some text editor.
It isn’t exactly “built-in”. It’s a plugin. But a rather miraculous one. :-)
-
@Alan-Kilborn said in Open with search:
@pdanes said in Open with search:
it changes in mid-stream. When I first call it, the dialog opens with “Find”, but after a while, it switches on its own to “Najít”. I haven’t (yet, anyway) taken the trouble to find out exactly when, or see if I can isolate the exact cause - I’ve been too busy just trying to get it working at all
Well THAT is certainly strange!
Isn’t it, though? What is happening is that only the first SendMessage call opens the dialog with “Find”. As long as the dialog stays open, and I simply put in different texts to search for and press the find button, it stays “Find”. As soon as a second SendMessage call is issued, or I manually switch to a different tab in the dialog, or I manually press ctrl/F (whether or not the search dialog is closed first), it immediately switches to “Najít” and stays that way from then on, for as long as Notepad remains open. If I completely close it, and it is opened again by the database and the search dialog is opened by the database’s SendMessage call, it is “Find” again. It seems that the very first SendMessage must bypass some initialization code. Maybe there is some other call I should issue first, some “SetInitialParameters” sort of thing, but I don’t really feel like looking for something that may not even exist. Just checking for both versions of the title works well enough. If someone who understands what’s going sees this and chimes in with some direction, I’ll fix it. If not, this works well enough.
A little odd, but I’ve seen stranger behavior from software.
Do they have a real Python interpreter built into Notepad? That’s some text editor.
It isn’t exactly “built-in”. It’s a plugin. But a rather miraculous one. :-)
So it seems. Python is probably something I should devote more time to. More and more situations are cropping up where knowing it well would be useful. At this point I can usually muddle my way to some result, but I don’t really ‘know’ the language, and I should.