Page 1 of 1

Richtext printing

Posted: Tue Feb 07, 2006 8:36 pm
by reinaldocrespo
Hi.

To print richt text with tprinter class, I've decided to implement an algorithm where I parse the richtext detecting rtf tokens and printing every time a font change happens. To this end, when achange is detected I do a "selection" of the text and then with REGetCharFormat I get the font and color.

But ortf:SetSel() does not seem to work properly. ReGetCharFormat always return the last font and color of text in the rtf control.

Here is a piece of the code showing at least part of the logic:

Code: Select all

local cRtf		:= RESaveAsRTF( ::ortf:hWnd, SF_RTF )
...
	While nStart < len( cRtf )
		nLast := FindEndOfText( cRtf, nStart )
		::oRtf:SetSel( nStart, nLast )
		cLine := SubStr( cRtf, nStart, nLast - nStart )

		nStart := nLast + 1
		nStart := FindEndOfTokens( cRtf, nStart )

		aFont := REGetCharFormat( ::ortf:hWnd, @nColor )
		nPad := ::oRtf:GetAlign()
		oRtfFont := tFont():New( aFont[ LF_FACENAME ], ;
						aFont[ LF_WIDTH ], ;
						aFont[ LF_HEIGHT ], .f.,;
						aFont[ LF_WEIGHT ] == FW_BOLD,,,;
						aFont[ LF_WEIGHT ],;
						aFont[ LF_ITALIC ],;
						aFont[ LF_UNDERLINE ],,,,,, ::oPrn, aFont[ LF_PITCHANDFAMILY ] )

		nChrsPerLine:= Int( ( ::oPrn:nHorzRes() - ( ::oPrn:nHorzRes() / 8.5 ) ) / max( oRtfFont:nWidth, 10 )  )
		cLine := StrTran( cLine, "\par", "" )
		nTotLns	:= MlCount( cLine, nchrsPerLine, 5, .t. )

		For i:= 1 to nTotLns
			::oprn:InchSay( nLine, nLeftMargin, MemoLine( cLine, nChrsPerLine, i, 5, .t. ), ;
					oRtfFont,, nColor,, iif( nPad == 3, 2, 0 ) )

			nLine += 0.16
...
It prints the text just fine. But it prints all text using the last font and color on the rtf control. I'm quite sure I'm doing something wrong with SetSel() or it is just not the function I need.

I still need to implement justification (npad above) and how to continue printing at the exact position that the last char was printed, but I'll get to that later. Right now, I only need to solve the setsel() problem.

Please help.




Reinaldo.

Posted: Wed Feb 08, 2006 2:04 pm
by reinaldocrespo
This silence only tells me that, perhaps, my note is not clear enough. So let me update the situation.

I've found that with this small change it almost works.

Code: Select all

	While nStart < len( cRtf )
		nLast := FindEndOfText( cRtf, nStart )
		cLine := SubStr( cRtf, nStart, nLast - nStart )
		::oRtf:SetSel( nMax := at( cLine, cText ), Len( cLine ) )
Which means that ::setsel() takes a parameter the point where to start and end using as reference the actual text with out the rtf code. And this is why setsel() was not working for me.

Reinaldo.

Reinaldo.

Posted: Wed Feb 08, 2006 2:07 pm
by Enrico Maria Giordano
reinaldocrespo wrote:This silence only tells me that, perhaps, my note is not clear enough.
No, this silence loudly tells you that without a reduced and self-contained sample it is often practically impossible to help you. :-)

EMG

Posted: Wed Feb 08, 2006 2:52 pm
by reinaldocrespo
Enrico;

Good to see your answer.
Ok. I take your point.

Let's just rephrase the question. First let's laid a couple of assumptions:
With:

Code: Select all

local cRtf	:= RESaveAsRTF( ::ortf:hWnd, SF_RTF )
local cText  := ortf:GetText()
I have in cRtf all text together with all rtf tokens embedded. And cText contains only the text.

Now I want to select a piece of text that starts at nMin and ends at nMax in cRtf and the only way I know how is using ::setsel( nMin, nMax). But the parameters expected by setsel() are in reference to cText not in cRtf. Thus if use:

Code: Select all

::oRtf:SetSel( nMin, nMax )
I'd get the wrong text selected and that is because nMin and nMax are points in cRtf not in cText.

So my question is: given start and end points in cRtf how can I select that piece? (I intend to use ReGetCharFormat afterwards). I'm thinking that perhaps there is another way to select() using points that reference cRtf.

After reading this and what I wrote before, I have to say; I made a mess the first time. I appologize. If you'd still need a self contained sample, I'll gladly work it up and upload it.

Thank you,

Reinaldo.

Posted: Wed Feb 08, 2006 3:08 pm
by Enrico Maria Giordano
Try with EM_EXSETSEL message instead of EM_SETSEL. From the MSDN:
EM_EXSETSEL
The EM_EXSETSEL message selects a range of characters and/or COM objects in a rich edit control.

To send this message, call the SendMessage function with the following parameters.

SendMessage(
(HWND) hWnd, // handle to destination window
EM_EXSETSEL, // message to send
(WPARAM) wParam, // not used; must be zero
(LPARAM) lParam // selection range (CHARRANGE *)
);
Parameters
wParam
This parameter is not used; it must be zero.
lParam
Pointer to a CHARRANGE structure that specifies the selection range.
Return Values
The return value is the selection that is actually set.

Requirements
Windows NT/2000/XP: Included in Windows NT 4.0 and later.
Windows 95/98/Me: Included in Windows 95 and later.
Header: Declared in Richedit.h.

See Also
Rich Edit Controls Overview, Rich Edit Messages
EMG

Posted: Wed Feb 08, 2006 5:23 pm
by reinaldocrespo
Enrico;

My rtf file is 676 bytes long. The text obtain by ortf:gettext() is 202 bytes long.

when I issue a EM_EXSETSEL message with cpmin set at any nuber above 202 it set is to 202.

Example:

Code: Select all

		RESetSelection( ::ortf:hWnd, nmin, len( cLine ) )
Where nmin is 300,

Code: Select all

		REGetSelection( ::oRtf:hwnd, @nMin, @nMax )
will set nmin to 202.
Below my ReGet and ReSel funcs.

Code: Select all

//------------------------------------------------------------------------------------------------------------------------------
HB_FUNC( REGETSELECTION )
{
   CHARRANGE cr;

   SendMessage( ( HWND ) hb_parnl( 1 ), EM_EXGETSEL, 0, ( LPARAM ) &cr );

   if( hb_pcount() > 1 )
      hb_stornl( cr.cpMin, 2 );

   if( hb_pcount() == 3 )
      hb_stornl( cr.cpMax, 3 );
}

//------------------------------------------------------------------------------------------------------------------------------
HB_FUNC( RESETSELECTION )
{
   CHARRANGE cr;

   cr.cpMin = hb_parnl( 2 );
   cr.cpMax = hb_parnl( 3 );

   SendMessage( ( HWND ) hb_parnl( 1 ), EM_EXSETSEL, 0, ( LPARAM ) &cr );

   hb_retni( SendMessage( ( HWND ) hb_parnl( 1 ), EM_SCROLLCARET, 0, 0L ) );
}

so obviously EM_EXSETSEL is working on plain text not on the actual rtf command embedded text.

Reinaldo.

Posted: Wed Feb 08, 2006 5:32 pm
by Enrico Maria Giordano
Sorry, I ran out of ideas... :-(

EMG

Posted: Wed Feb 08, 2006 9:33 pm
by Antonio Linares
Reinaldo,

We plan to publish richedit printing in next March build.

Posted: Wed Feb 08, 2006 9:51 pm
by reinaldocrespo
Antonio;

Hi.

Glad to hear the news. I'll be waiting in line to place the order for March build. :-)


BTW -- with it, I'll be able to print rtf data to a region of an already opened tprinter object. Right?


Reinaldo.

Posted: Wed Feb 08, 2006 11:30 pm
by Antonio Linares
Reinaldo,

Yes

Posted: Thu Feb 09, 2006 7:34 am
by Antonio Linares
Reinaldo,

Yes,

Posted: Thu Feb 09, 2006 9:09 am
by Silvio
Dear Antonio,
I have richpad ( do you remember ?) But there are many func REXXXXXXXX , I not have this source file where i can found it ?
I used it for a program at school office
silvio