From: Mayayana on
Function Find(ByVal sText As String, ByVal LStart As Long, ByVal LEnd As
Long, ByVal LOpts As Long) As Lon
Dim Ft As FINDTEXT
Dim LRet As Long
Dim s As String
With Ft
.chrg.cpMin = LStart
.chrg.cpMax = LEnd
End With
s = StrConv((sText & vbNullChar), vbFromUnicode)
Ft.lpstrText = StrPtr(s)
LRet = SendMessageAny(hRTB, EM_FINDTEXT, ByVal LOpts, Ft)
Find = LRet
End Function

You have to also watch for direction. Starting with
RichEdit v. 2, backward search is possible, and it's
the default! Add 1 to wParam for forward search.

So, if I've got it right, it's now possible to call up
a bland-looking system Find/Replace window and
find given text in an RTB....in less than 5 pages of code.
I anxiously await the API code to create those system
command buttons from scratch. They look so much
more official than VB buttons. :)


| :
| : Congratulations on solving this problem thirteen years after I posed
| : it. I tried to read through some of your code, but it just makes my
| : eyes cross. I don't have VB on my machine, so that makes it even
| : harder to follow, but the EXE ran and demonstrated that you had indeed
| : brought up the dialog and that Tab and Enter worked.I'm not sure that
| : your reason for doing it was justified, but if you had fun, that's all
| : that counts. As far as Find and Replace go, I still think the solution
| : I presented in the book (a custom form) is better than the standard
| : dialog for most situations for the reasons I presented. But I'm glad
| : you solved the problem and I hope you didn't waste as much time on
| : your success as I did on my failure.
| :
| : Bruce
|
| <MILDHEROWORSHIP>
|
| Wow, Bruce McKinney stopped by. Wicked cool! I loved your book and the
CD
| that came with, learned a *lot*. Thank you for your efforts.
|
| </MILDHEROWORSHIP>
|
| I was researching some of this for Karl, and dicovered the problem of
| searching for case and whole word is solved with the EM_FINDTEXT in which
| FR_MATCHCASE and FR_WHOLEWORD are entered in the wParam. If the string
| target is found, the ret val is the zero-based position of the first
| character of the first instance found. The caveat, it's gotta be a RTB,
| apparently. If it also works for the standard text box, the docs did not
| say.
|
| Am going to play with this within Karl's example and see what happens!
|
| Peace!
|
| - Kev
|


From: Karl E. Peterson on
Larry Serflaten was thinking very hard :
> "Karl E. Peterson" <karl(a)exmvps.org> wrote
>
>>> 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'?
>>
>> 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.
>
> <... snipped for brievity ...>
>
>> They never unhook the subclass, either. Hmmm... Sloppy.
>
> <...>
>
>> 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.
>
>
> Thanks for the point by point analysis. You've covered several things
> I very probably would have overlooked.

I might've as well, but the pesky things just had a way of jumping up
and slapping me silly as I tried to get this one to go. I really have
to wonder whether those guys ever actually *tried* that sample they put
in the KB. <g>

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


From: Karl E. Peterson on
Leo explained on 6/30/2010 :
> Leo formulated on Thursday :
>> Karl E. Peterson has brought this to us :
>>> Yeah, I'd call those numeric, not alpha. But that's interesting, I'd have
>>> to try it to really see what you're saying. OTOH, I'd say you have a hit
>>> if it were "hello!", eh?
>>
>> Nope it doesn't find hello in that string so wordpad in an English locale
>> counts numbers as part of a word. But If I add an _ to the begining and a +
>> at the end and search for the original string it ignores the two new
>> characters.
>
> You could take a look at IsCharacterAlphaNumeric which is language
> independant.

Not a bad thought! That might be exactly what they're using for this.

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


From: Karl E. Peterson on
Mayayana wrote on 6/30/2010 :
> Wordpad uses a RichEdit window.
> You can check the status of characters in
> a RichEdit with the following code.
> Put an RTB and a label on a form, paste
> text into the RTB, then click characters:
>
> Private Const WM_USER = &H400
> Private Const EM_FINDWORDBREAK = (WM_USER + 76)
> Private Const WB_CLASSIFY As Long = 3
> Private Const WBF_BREAKAFTER As Long = &H40
> Private Const WBF_BREAKLINE As Long = &H20 'AKA WBF_WORDBREAK
> Private Const WBF_ISWHITE As Long = &H10 'AKA WBF_WORDWRAP
>
> Private Declare Function SendMessageLong Lib "user32" Alias "SendMessageA"
> (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam
> As Long) As Long
>
>
> Private Sub RTB_Click()
> Dim StPt As Long, LRet As Long
> StPt = RTB.SelStart
> LRet = SendMessageLong(RTB.hwnd, EM_FINDWORDBREAK, WB_CLASSIFY, StPt)
> Label1.Caption = CStr(LRet)
> End Sub
>
> Explanation of the different values that show
> in the label (which are a combination of the WBF
> flags and the character classification):
>
> "A delimiter is a character that marks the end of a word, such as a space.
> In an edit control, word breaks occur only after delimiters.
>
> Word break procedures for rich edit controls also group characters into
> character classes, each identified by a value in the range 0x00 through
> 0x0F. Word breaks occur either after delimiters or between characters of
> different classes. Thus, a word break procedure with different classes for
> alphanumeric and punctuation characters would find two word breaks in the
> string "WIN.COM"."
>
> If you use the WB_ISDELIMITER flag with
> EM_FINDWORDBREAK it returns True for a space
> and False for everything else. But if you use
> WB_CLASSIFY you can see that alphanumeric
> characters return 0, while punctuation marks
> return various values.
>
> There's also EM_SETWORDBREAKPROC which allows
> setting a callback function to take over word break
> functionality. I've never tried it. The docs seem to
> imply that your callback would only be called when a
> line needs to be broken.

Starting to sound like there could be an optimized engine for this kind
of search for each type of control it may be used with?

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


From: Karl E. Peterson on
Hi Bruce!

> Congratulations on solving this problem thirteen years after I posed
> it. I tried to read through some of your code, but it just makes my
> eyes cross. I don't have VB on my machine, so that makes it even
> harder to follow, but the EXE ran and demonstrated that you had indeed
> brought up the dialog and that Tab and Enter worked.

I think the trick was "just" taking over the message loop processing
that VB was doing, and injecting an IsDialogMessage call in there...

Private Sub MessageLoop()
Dim msg As Message
' If you create a Find dialog box, you must also use the
IsDialogMessage
' function in the main message loop of your application to ensure
that the
' dialog box correctly processes keyboard input, such as the TAB
and ESC
' keys. IsDialogMessage returns a value that indicates whether
the Find
' dialog box processed the message.
' http://msdn.microsoft.com/en-us/library/ms646918(VS.85).aspx
Do While (GetMessage(msg, 0, 0, 0) <> 0) And (IsWindow(m_hDlg) <>
0)
If IsDialogMessage(m_hDlg, msg) = 0 Then
' Message was not processed by dialog, so we need to
process here.
Call TranslateMessage(msg)
Call DispatchMessage(msg)
End If
Loop
DebugOutput "Exiting MessageLoop"
End Sub

But that meant the call to show the dialog wouldn't return until the
dialog was dismissed, which raised new problems. Had to make the call
async to cover that issue.

> I'm not sure that your reason for doing it was justified, but if you
> had fun, that's all that counts.

That was most of it, yeah. <bg> Leo, the guy who first asked about it,
threw out the clincher, though. When he was asked why he wanted to do
it, he said (paraphrasing), "so the app would maintain the look and
feel of whatever OS it found itself running on." That made good sense
to me. Outdated appearing dialogs are just ugly.

Then there were the peripheral purposes too, like driving home the
point of just how lame that KB (Q267939) was. Not to mention my
reaction after googling and seeing everyone basically throwing their
hands up in frustration saying "you can't do that in VB."

> As far as Find and Replace go, I still think the solution
> I presented in the book (a custom form) is better than the standard
> dialog for most situations for the reasons I presented.

I agree, in a lot of circumstances, that's probably true. Especially
for the customization opportunities it allows. But for the most basic
functionality, this class now presents what amounts to a drop-in ready
solution that'll always replicate the native environment.

> But I'm glad
> you solved the problem and I hope you didn't waste as much time on
> your success as I did on my failure.

You said "days" right? I think I got this one going in some fractional
part of a day. Heh, though it certainly was more time than I
originally thought it might be. :-)

Regards... Karl

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