Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

RTF Highlight command 1

Status
Not open for further replies.

Koen Piller

Programmer
Jun 30, 2005
841
NL
Hi,

With RTF you can search and highlight for words in your RTF-text. However the highlight function is not as the default highlight in Word or Excel: it changes the forecolor to a given color and not the backcolor. Anybody to give me the code to change the highlight to true highlight?

I am using these procedures now:
Code:
PROCEDURE SEARCHIT
* cmd Search

Local ;
	lcFindExpression As String, ;
	liExpressionFound As Integer


If Empty(Thisform.Text1.Value)
	Return
Endif

With Thisform
	m.lcFindExpression = Alltrim(.Text1.Value)

	m.liExpressionFound = .oleDetails.Find(m.lcFindExpression ,0, -1)
	If m.liExpressionFound >-1
		.nStart = m.liExpressionFound + 1
	Endif
Endwith
ENDPROC

PROCEDURE SEARCHALL
Local ;
	lcExpressionSought As String, ;
	liFound As Integer

If Empty(Thisform.Text1.Value)
	Return
Endif

m.lcExpressionSought = Alltrim(Thisform.Text1.Value)

With Thisform
	.nStart = 0
	m.liFound = 0
	Do While m.liFound >=0
		m.liFound = .oleDetails.Find(m.lcExpressionSought ,.nStart, -1)
		If m.liFound >-1
			.nStart = m.liFound + 1
* highlight it
			.oleDetails.SelColor = Rgb(255,0,0)  &&red
			.oleDetails.SelBold = .T.
		Else
			Exit
		Endif
	Enddo
Endwith
ENDPROC

Anyone who has the code to change the highlight to as it should be?

Stay healthy,
Koen
 

you could change the RTF itself....


(borrowed from Craig Boyd's spellchecker component )

m.lcFront = SUBSTR(Thisform.Text1.Value,1,m.liFound)
m.lcBack = SUBSTR(Thisform.Text1.Value,m.liFound+LEN(m.lcExpressionSought)+1)

TEXT TO m.lcRTFLeadIn noshow
{\rtf1\ansi\deff0\deflang1033{\fonttbl{\f0\fswiss Tahoma;}}
{\colortbl ;\red255\green0\blue0;\red0\green0\blue0;}\viewkind4\uc1\pard\f0\fs20
ENDTEXT
m.lcRTF = m.lcRTFLeadIn + m.lcFront+ "\b\cf1 "+m.lcExpressionSought+"\cf0\b0 "+m.lcBack+"\par}"
THIS.oleDetails.textRTF = m.lcRTF
THIS.oleDetails.SELSTART = m.liFound
THIS.oleDetails.SELLENGTH = 0
THIS.oleDetails.REFRESH


but that may just introduce the problem of removing it later..

n
 
Is this the color your were looking for (blue background highlight)?

Capture9_ca7tjm.png


The problem is that the RTF control that ships with VFP is severely limited. Like I said in a previous post, it's only version 1 (current version is 4.1):


Unfortunately, the Find method is limited. Later versions use the FINDTEXTEXW structure with the EM_FINDTEXTEXW message in the SendMessage API:


The bad news is that this stuff requires major work and most customers want it yesterday...
 
Nigel,

With following code
Code:
With Thisform
	m.lcFindExpression = Alltrim(.Text1.Value)

	m.lcFront = Substr(Thisform.Text1.Value,1,m.liFound)
	m.lcBack = Substr(Thisform.Text1.Value,m.liFound+Len(m.lcExpressionSought)+1)

	TEXT TO m.lcRTFLeadIn noshow
{\rtf1\ansi\deff0\deflang1033{\fonttbl{\f0\fswiss Tahoma;}}
{\colortbl ;\red255\green0\blue0;\red0\green0\blue0;}\viewkind4\uc1\pard\f0\fs20
	ENDTEXT
	m.lcRTF = m.lcRTFLeadIn + m.lcFront+ "\b\cf1 "+m.lcExpressionSought+"\cf0\b0 "+m.lcBack+"\par}"
	This.oleDetails.textRTF = m.lcRTF
	This.oleDetails.SelStart = m.liFound
	This.oleDetails.SelLength = 0
	This.oleDetails.Refresh

	m.liExpressionFound = .oleDetails.Find(m.lcFindExpression ,0, -1)
	If m.liExpressionFound >-1
		.nStart = m.liExpressionFound + 1
	Endif
Endwith
I donot get the desired result, any idea how I show change it?

Vernpace:
Yes that is exactly what I am after, is that also doable with Version 1.0 and if so, do you have the syntax?

Stay healthy,
Koen
 
Tom,

a simple CTR+F with the cursor in myRTF does not do anything
have added a button with in the clickevent:
Code:
Local loShell as Object
This.Parent.oleRTF.SetFocus()
loShell = Newobject("wscript.shell")
loShell.sendKeys("^{F}")
loShell = Null
Release loShell
DoDefault()

Nothing and I wonder if it would work, what kind of backcolor I would get.

Stay healthy,

Koen
 
loShell = Newobject("wscript.shell")
loShell.sendKeys("^{F}")

Koen,

Try putting a short pause (500 ms or so) between the NewObject() and the SendKeys(). You need to give the object time to get instantiated.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Koen,

ah... that code is assuming the text is not already RTF and putting another {\rtf1 leader at the every beginning. Instead you need to merge just that color table into the existing RTF leader. Which will be a bit fiddly.

The updated RTF control as shown by Vernpace is probably the way to go if at all possible.

n
 
First of all, there is no Search/Replace dialog thats integrated within the RTF control. Below is the code we use for the Find operation.

Code:
LOCAL lcStruct, loFindTextEXW, liOptions, liSelStart, liSelLength

IF EMPTY(This.Parent.cboRTFFind.Text)
   RETURN
ENDIF

This.Parent.cboRTFFind.SetFocus()
ThisForm.SetStatusBarText("")
liOptions = FR_DOWN + IIF(This.Parent.chkRTFMatchCase.Value, FR_MATCHCASE, 0) + IIF(This.Parent.chkRTFMatchWords.Value, FR_WHOLEWORD, 0)

loFindTextEXW = CREATEOBJECT("FINDTEXTEXW")
loFindTextEXW.chrg(1).cpMin = ThisForm.iStart
loFindTextEXW.chrg(1).cpMax = -1
loFindTextEXW.lpstrText = RTRIM(This.Parent.cboRTFFind.Text)
lcStruct = loFindTextEXW.GetString()

IF SendMessageCRef(ThisForm.RichText.hWnd, EM_FINDTEXTEXW, liOptions, @lcStruct) > -1
   loFindTextEXW.SetString(lcStruct)
   liSelStart = loFindTextEXW.chrgText(1).cpMin
   liSelLength = loFindTextEXW.chrgText(1).cpMax - liSelStart
   ThisForm.RichText.SelStart = liSelStart
   ThisForm.RichText.SelLength = liSelLength
   ThisForm.iStart = loFindTextEXW.chrgText(1).cpMax + 1
   This.Caption = "Find Next"
ELSE
   IF ThisForm.iStart > 0
      ThisForm.iStart = 0
      This.Caption = "Find Again"
      ThisForm.SetStatusBarText("Search complete.  Search item found.")
   ELSE
      This.Enabled = .F.
      This.Caption = "Find Next"
      ThisForm.SetStatusBarText("Search complete.  Search item not found.")
   ENDIF
ENDIF

There is a lot going on here which is too much for me to expand on in this post. We are using Christian Ehlscheid's Struc class. You will need to learn how to use it to create the required structures (good documentation). You can get it here: This should work with version 1 of RTF. However, you will need to learn how to code the FINDTEXTEXW and CHARRANGE structures in conjuction with EM_FINDTEXTEX and the SendMessage API. You will have to do that on your own - I will not provide all that code.
 
I don't know what RTF control you are using, but I use the standard ocx and IT HAS CTRL+F functionality.
I'm using it for years and its an ocx from 2003.

But....maybe this is the reason and newer versions don't have it anymore....


EDIT: I mixed up Internet Explorer and RichText OCX. RTF indeed has not CTRL+F!!!!

-Tom
 
Tom,
I am using the default, which ships with VFP : RICHTEXT.RichtextCtrl.1
F.w.i.w. I have set the property AutoVerbMenu = .T. to get a shortcut popup and tried with .F. (= default) still nothing when I activate Ctrl+F
Strange.
Stay healthy,
Koen
 
Oh my.... MEA CULPA!!!

I just noticed, that I was talking about the HTML implementation code of my editor and not the RTF one. SORRY!
RTF indeed doesn't have CTRL+F implementation. It is part of the Internet Explorer ocx.

So I dived into the code and looked for the way I implemented the search....
It turned out, that it is rather easy to do. So have a look at the form first:

RTFSearch_fperey.png


On the upper right of the form you see the button [Suchen] (=search). Clicking the button fires a strategy pattern that checks the current mode (text/rtf/html). On text and rtf it shows (if not already visible) an inputbox right above the button where you can enter the search string. In this case the word 'confidential'. Pressing ENTER in the inputbox or another click on the button then starts the search process. Currently the 4th occurrence of 'confidential' is marked.

A RTF object has two properties for working with its content. The formatted content is accessible via .TextRTF. For searching the property .Text is nicer as it is the unformatted pure ansi text version.

This is the code I use for the search:

Code:
LOCAL lcSearch as String, liSelStart as Integer

IF NOT EMPTY( ALLTRIM( Thisform.txtSearch.Value ) )

	lcSearch = ALLTRIM( Thisform.txtSearch.Value )
	Thisform._Searched = Thisform._Searched + 1 

	WITH Thisform.oFormat.rtf.editBox
		liFound = OCCURS( lcSearch , .Text )
		IF liFound >= Thisform._Searched
			liSelStart	= AT( lcSearch , .Text , Thisform._Searched ) - 1
			.SelStart	= liSelStart
			.SelLength	= LEN( lcSearch )
		ELSE 
			Thisform._Searched = 0
		ENDIF 
	ENDWITH
ENDIF

I hope that I have all the code, as I had to cut out the HTML and TEXT parts.
Sorry again for my wrong infos from my previous postings.

-Tom
 
Tom,
I am afraid you did not copy all the code.
Your code does find, if available, but does it does not show. And what is more important it does not color the background of the found.
Please review.
Thnks.
Koen
 
Tom,

1) Presuming your form has the oleRTF loaded and it is named oleDetails
2) create a property nStart (0) on your form
3) create a Textbox Text1 on your form
4) create a button and put following code in the click event:

Code:
Local lcExpressionSought As String, ;
	liExpressionFound As Integer

If Empty(Thisform.Text1.Value)
	Return
Endif

m.lcExpressionSought = Alltrim(Thisform.Text1.Value)

m.liExpressionFound = Thisform.oleDetails.Find(m.lcExpressionSought,0, -1)
If m.liExpressionFound >-1
	Thisform.nStart = m.liExpressionFound+1
*WAIT WINDOW "FOUND" TIMEOUT 1
Endif

voila it finds (if available) but it does not highlight (backcolor something e.g. bright yellow, forecolor as is )
It is this highlight I am after. Not the find() function. See my initial question here.

Stay healthy,

Koen
 
Nigel

Your code:

Code:
TEXT TO m.lcRTFLeadIn noshow
{\rtf1\ansi\deff0\deflang1033{\fonttbl{\f0\fswiss Tahoma;}}
{\colortbl ;\red255\green0\blue0;\red0\green0\blue0;}\viewkind4\uc1\pard\f0\fs20
ENDTEXT
m.lcRTF = m.lcRTFLeadIn + m.lcFront+ "\b\cf1 "+m.lcExpressionSought+"\cf0\b0 "+m.lcBack+"\par}"

colors the forecolor, I would like to have the backcolor colored. (black on yellow is my preference)
switching to
Code:
{\colortbl ;\red0\green0\blue0;\red255\green0\blue0;}\viewkind4\uc1\pard\f0\fs20
makes no difference still red on white
Do you have an other solution?

Stay healthy,

Koen
 
Hi Koen,

my form is based on a pageframe called 'oFormat' and has 3 pages named 'text', 'rtf', 'html' and each object on the corresponding page is called 'editbox', either if its the VFP editbox, the rtf control or the internet.explorer control.
The form has a counter called ._Searched that holds the search offset number.

So I just checked my copied code and it is complete.

However, do you have the rtf's property 'HideSelection' set to .T.? If so, switch it to .F. as the rtf no longer has the focus, it has to be configured to display selected text even without focus.

-Tom
 
Koen,

play with the rgb settings in the color table

at a guess

{\colortbl ;\red0\green0\blue0;\red255\green255\blue0;}

edit: but i would suggest this is only worthwhile if you are displaying a fragment of the document (as with a spellchecker). If you are working with the final document you won't want to add and remove the colortables and the highlight encoding; better to use the control's properties as others have suggested.
n
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top