From: Larry Serflaten on

"Karl E. Peterson" <karl(a)exmvps.org> wrote

> It started with a post by Leo the other day, titled "How to use the
> FindText and ReplaceText API". He pointed to a *totally* bizarre KB
> article that almost certainly just wouldn't work. (Yeah, I didn't even
> try it.) It just makes no damn sense on the face of it. This was it:
>
> How To Use FindText to Enable Searching in a Text Box
> http://support.microsoft.com/kb/267939
<...>
> Long story, short, here's the result:
>
> http://vb.mvps.org/samples/_beta/FindReplace.zip
>
> Anyone see any problems with it? Leo, thanks man. I had fun! :-)

I've looked at both methods, and not tried either of them (yet), but from a
first glance perspective, how is your method any less 'bizarre'? It looks
to me like MSDN did the 'Find' part with much less code....

(ie; you both resort to subclassing to work with the dialog box)

LFS


From: Karl E. Peterson on
Larry Serflaten used his keyboard to write :
> "Karl E. Peterson" <karl(a)exmvps.org> wrote
>
>> It started with a post by Leo the other day, titled "How to use the
>> FindText and ReplaceText API". He pointed to a *totally* bizarre KB
>> article that almost certainly just wouldn't work. (Yeah, I didn't even
>> try it.) It just makes no damn sense on the face of it. This was it:
>>
>> How To Use FindText to Enable Searching in a Text Box
>> http://support.microsoft.com/kb/267939 <...>
>> Long story, short, here's the result:
>>
>> http://vb.mvps.org/samples/_beta/FindReplace.zip
>>
>> Anyone see any problems with it? Leo, thanks man. I had fun! :-)
>
> I've looked at both methods, and not tried either of them (yet), but from a
> first glance perspective, how is your method any less 'bizarre'? It looks
> to me like MSDN did the 'Find' part with much less code....
>
> (ie; you both resort to subclassing to work with the dialog box)

Well, for the most obvious thing, the KB sample won't do any
accelerator key handling (Tab, Enter, Escape, arrows, etc.). Obvious
to me, at any rate, because that was kind of a bear to work out.
Theirs won't even trigger when you press the spacebar and the command
button has focus.

And subclassing *is* how this dialog is designed to be used. Take a
look at the FindText docs, and they'll tell you to monitor the owner
window for FINDMSGSTRING messages.

Also, the KB article *is* subclassing, but not the proper (owner)
window. Rather, they're subclassing one specific button (the very
first, which just happens to be "Find Next") on the dialog itself.
That's just bizarre.

' Show the dialog box.
gHDlg = FindText(frText)
' Get the handle of the dialog box
hCmdBtn = GetDlgItem(gHDlg, 1)
' Get necessary value for calling default window procedure.
gOldDlgWndHandle = GetWindowLong(hCmdBtn, GWL_WNDPROC)

There's no particular reason to believe that the KB method will
continue to work, should the dialog be redesigned at some point down
the road, because they're using hard-coded dialog element IDs.

' Get the pattern string
ptnLen = GetDlgItemText(gHDlg, &H480, strPtn, MaxPatternLen)

' Get the MatchCase option
If IsDlgButtonChecked(gHDlg, &H411) = 0 Then

They never unhook the subclass, either. Hmmm... Sloppy.

Of course, because of this weird subclassing method they employ,
there'd be virtually no hope of adapting this method to using the
ReplaceText call. With mine, it's a simple If test choice of which to
call. Both are supported using the same framework.

They don't null terminate the buffers, so sometimes you get random
garbage showing up in the "Find what:" box. How's this for assigning a
string to a byte array?

ReDim strArr(0 To Len(szFindString) - 1)
For i = 1 To Len(szFindString)
strArr(i - 1) = Asc(Mid(szFindString, i, 1))
Next i

Their puny buffer prevents you from entering FindWhat text longer than
what came up as the default when the dialog was created. MSDN says the
buffer should be a minimum of 80 characters. I think I used 512.

Now, I don't even attempt to implement the actual find/replace routines
themselves. But that could pretty easily be added, and may at some
point. The KB article does attempt to do so, and fails miserably. It
just doesn't work, unless you happen to do something magic before
popping the dialog. If you do the magic, the search always starts at
the beginning, sort of ignoring the first word on the button they're
subclassing.

Hmmm, what else? Oh, they don't even use Option Explicit! Does that
count against me for part of the extra code I employed? <g>

Yes, they *do* manage to pop the dialog without a GPF. I guess that's
something. <g> But it's pretty darn far from functional.

I am intrigued, however, that they're not copying the structure out of
VB variables into heap memory before making the call. It was crashing
nasty until I made that stab at it. I'll need to revisit that. That'd
cut a good half dozen, or maybe even more, LOC right that! ;-)

--
..NET: It's About Trust!
http://vfred.mvps.org


From: Karl E. Peterson on
Karl E. Peterson presented the following explanation :
> I am intrigued, however, that they're not copying the structure out of VB
> variables into heap memory before making the call. It was crashing nasty
> until I made that stab at it. I'll need to revisit that. That'd cut a good
> half dozen, or maybe even more, LOC right that! ;-)

Huh. I think I was mistaken, there. I just yanked that part out, and
it's still working just fine. As it should. Not sure what else it was
causing the crashes at the time, but hey, they're gone now! :-)

New upload: http://vb.mvps.org/samples/_beta/FindReplace.zip

--
..NET: It's About Trust!
http://vfred.mvps.org


From: Leo on
Karl E. Peterson was thinking very hard :
> Larry Serflaten used his keyboard to write :
>> "Karl E. Peterson" <karl(a)exmvps.org> wrote
>>
>>> It started with a post by Leo the other day, titled "How to use the
>>> FindText and ReplaceText API". He pointed to a *totally* bizarre KB
>>> article that almost certainly just wouldn't work. (Yeah, I didn't even
>>> try it.) It just makes no damn sense on the face of it. This was it:
>>>
>>> How To Use FindText to Enable Searching in a Text Box
>>> http://support.microsoft.com/kb/267939 <...>
>>> Long story, short, here's the result:
>>>
>>> http://vb.mvps.org/samples/_beta/FindReplace.zip
>>>
>>> Anyone see any problems with it? Leo, thanks man. I had fun! :-)
>>
>> I've looked at both methods, and not tried either of them (yet), but from a
>> first glance perspective, how is your method any less 'bizarre'? It looks
>> to me like MSDN did the 'Find' part with much less code....
>>
>> (ie; you both resort to subclassing to work with the dialog box)
>
> Well, for the most obvious thing, the KB sample won't do any accelerator key
> handling (Tab, Enter, Escape, arrows, etc.). Obvious to me, at any rate,
> because that was kind of a bear to work out. Theirs won't even trigger when
> you press the spacebar and the command button has focus.
>
> And subclassing *is* how this dialog is designed to be used. Take a look at
> the FindText docs, and they'll tell you to monitor the owner window for
> FINDMSGSTRING messages.
>
> Also, the KB article *is* subclassing, but not the proper (owner) window.
> Rather, they're subclassing one specific button (the very first, which just
> happens to be "Find Next") on the dialog itself. That's just bizarre.
>
> ' Show the dialog box.
> gHDlg = FindText(frText)
> ' Get the handle of the dialog box
> hCmdBtn = GetDlgItem(gHDlg, 1)
> ' Get necessary value for calling default window procedure.
> gOldDlgWndHandle = GetWindowLong(hCmdBtn, GWL_WNDPROC)
>
> There's no particular reason to believe that the KB method will continue to
> work, should the dialog be redesigned at some point down the road, because
> they're using hard-coded dialog element IDs.

That was one of the things I didn't like. Thats what the UDT is for.
>
> ' Get the pattern string
> ptnLen = GetDlgItemText(gHDlg, &H480, strPtn, MaxPatternLen)
>
> ' Get the MatchCase option
> If IsDlgButtonChecked(gHDlg, &H411) = 0 Then
>
> They never unhook the subclass, either. Hmmm... Sloppy.
>
> Of course, because of this weird subclassing method they employ, there'd be
> virtually no hope of adapting this method to using the ReplaceText call.
> With mine, it's a simple If test choice of which to call. Both are supported
> using the same framework.
>
> They don't null terminate the buffers, so sometimes you get random garbage
> showing up in the "Find what:" box. How's this for assigning a string to a
> byte array?
>
> ReDim strArr(0 To Len(szFindString) - 1)
> For i = 1 To Len(szFindString)
> strArr(i - 1) = Asc(Mid(szFindString, i, 1))
> Next i
>
> Their puny buffer prevents you from entering FindWhat text longer than what
> came up as the default when the dialog was created. MSDN says the buffer
> should be a minimum of 80 characters. I think I used 512.
>
> Now, I don't even attempt to implement the actual find/replace routines
> themselves. But that could pretty easily be added, and may at some point.
> The KB article does attempt to do so, and fails miserably. It just doesn't
> work, unless you happen to do something magic before popping the dialog. If
> you do the magic, the search always starts at the beginning, sort of ignoring
> the first word on the button they're subclassing.
>
> Hmmm, what else? Oh, they don't even use Option Explicit! Does that count
> against me for part of the extra code I employed? <g>
>
> Yes, they *do* manage to pop the dialog without a GPF. I guess that's
> something. <g> But it's pretty darn far from functional.
>
> I am intrigued, however, that they're not copying the structure out of VB
> variables into heap memory before making the call. It was crashing nasty
> until I made that stab at it. I'll need to revisit that. That'd cut a good
> half dozen, or maybe even more, LOC right that! ;-)

--
ClassicVB Users Regroup! comp.lang.basic.visual.misc
Free usenet access at http://www.eternal-september.org


From: Karl E. Peterson on
It happens that Kevin Provance formulated :
> Well, besides the text im looking for to find and or replace not being
> highlighted or replaced, the "framework" seems to work just peachy (no
> crashes or the like).
>
> Are you going to add that functionality? If not, kick it over here. If so,
> I'll wait for the finished bits.

Yeah, right now, it's just raising events to alert the client what the
user asked for. I was thinking the class just begged for a nice little
routine you could pass the original text to, and it'd act on the dialog
results. Hadn't really gotten to what might be the best actual
implementation for that yet, though.

Seems the ideal thing to do would be to keep raising the events, but
have a method you could call to "handle it" for you. The reason I was
thinking passing the original text, was that a handle would limit the
types of controls you could use the dialog with.

I suppose there could be one specialized All-In-One routine that was
just for textboxes, and another that simply took the original text and
told you where the "next" instance was. (You already need both, so the
only "task" there is providing two entry points.) That'd require a
starting position, for sure, and probably an optional parameter to wrap
the search?

Replace next would almost be the same as Find next, eh? I suppose
replace all would be easiest (a one-liner? <g>). I'd be happy to
bounce ideas around here!

> Looks friggin great so far tho. :-)

Thanks! It was really fun when it all of a sudden *snapped* into
place. When Bruce tells me "it can't be done", there's only one
natural response. <bSEg>

--
..NET: It's About Trust!
http://vfred.mvps.org