Page 1 of 1

Description of REPrintBox ()

Posted: Mon Jul 23, 2007 11:13 am
by StefanHaupt
Dear friends,

did anyone has a description of the function REPrintBox () used in the class TRichEdit ?

REPrintBox return an array with two elements, with the first one i get the position of the last printed char, is that right ?

How can I get the exact position in cm of this position, so I´m able to print some other text afterwards ?

Posted: Mon Jul 23, 2007 3:24 pm
by Antonio Linares
Stefan,

Please search for REPrintBox at FWH\whatsnew.txt

Posted: Mon Jul 23, 2007 8:27 pm
by StefanHaupt
Antonio,

thanks, I found it, but i have still some questions.

How can i control, if the rtf-text fits in the defined box ?

What happens, if there is pagebreak in the printbox ? Is the printbox automatically continued on the next page ?

Posted: Mon Jul 23, 2007 10:42 pm
by Antonio Linares
Stefan,

We can't tell you for sure, we need to do some tests. We appreciate if you also test it there, thanks

Posted: Tue Jul 24, 2007 7:20 am
by StefanHaupt
Antonio,

ok, i will try to build a small sample next days.

Posted: Tue Jul 24, 2007 11:30 am
by StefanHaupt
First tests show, that REPrintBox() does nor continue the print on the next page neither respects the margin on the bottom of the page.

I also did not find a way, to adjust the printbox to the selected text, so the text is always clipped, if the box is to small.

Posted: Fri Aug 03, 2007 9:36 am
by StefanHaupt
Antonio,

I made some investigations in the MSDN documentation about richtext and I tried to create my own print function.That was not as easy as on the first look, but here is the result.

It´s working fine so far, it does respect the margins and continues printing on the next page.

But there are still two issues I can´t solve.

As you can see in the picture at the end of this post, the richtext should fit into the rectangle, but it starts above over the last textlines.

Second, how can I get the position on the last page where the richtext ends, so I can print other text after it ?

I would be happy, if you can review my code, please.

Here is the code:

Code: Select all

#define PHYSICALWIDTH    110
#define PHYSICALHEIGHT   111
#define PHYSICALOFFSETX  112
#define PHYSICALOFFSETY  113
#define HORZSIZE 4
#define VERTSIZE 6
#define HORZRES  8
#define VERTRES 10
#define LOGPIXELSX       88
#define LOGPIXELSY       90

STATIC FUNCTION PrintMixed (lPreview)

  LOCAL oPrn, cName := "Mixed Printtest", aLine, nLine
  LOCAL aMargins
  LOCAL aPhysMarg := Array(4)
  LOCAL nPhysWidth, nPhysHeight
  LOCAL nHorzRes, nVertRes, nHorzSize, nVertSize
  LOCAL nTMarg, nLMarg, nRMarg, nBMarg
  LOCAL dpiX, dpiY
  LOCAL nL := 0, nT := 0, aPos, aFrom, aTo, i,y:= 0.5
  LOCAL aRect := Array (4)

  DEFAULT lPreview := .f.

  //? oDoc:RtfSize() // 1.048.576

  PRINT oPrn NAME cName FROM USER //PREVIEW

  nHorzRes := GETDEVICECAPS( oPrn:hDC, HORZRES ) // 9314,Druckbereich in Pixel, 47,2 Pixel/mm = 197mm
  nVertRes := GETDEVICECAPS( oPrn:hDC, VERTRES ) //

  nHorzSize := GETDEVICECAPS( oPrn:hDC, HORZSIZE )/10 // 197, Druckbereich in mm (cm)
  nVertSize := GETDEVICECAPS( oPrn:hDC, VERTSIZE )/10 // height in mm

  dpiX :=  GETDEVICECAPS( oPrn:hDC, LOGPIXELSX)   // 1200, Druckauflösung in dpi (pixel pro inch)
  dpiY :=  GETDEVICECAPS( oPrn:hDC, LOGPIXELSY)

  nPhysWidth  := GETDEVICECAPS( oPrn:hDC, PHYSICALWIDTH ) // 9921, gesamte Druckbreite incl. nicht bedruckbarer Bereich
  nPhysHeight := GETDEVICECAPS( oPrn:hDC, PHYSICALHEIGHT )
  aPhysMarg[1] := GETDEVICECAPS( oPrn:hDC, PHYSICALOFFSETY ) // 280, linker nicht bedruckbarer Bereich
  aPhysMarg[2] := GETDEVICECAPS( oPrn:hDC, PHYSICALOFFSETX ) // 280, oberer nicht bedruckbarer Rand
  aPhysMarg[3] := nPhysHeight - nVertRes - aPhysMarg[1]      // unterer rand
  aPhysMarg[4] := nPhysWidth - nHorzRes - aPhysMarg[2]       // rechter Rand = PHYSICALWIDTH-HORZRES-PHYSICALOFFSETX

  aMargins := PageGetMargins ()                                          // in 1/100 mm
  nTMarg := aMargins[ 1 ] / 2540 * GETDEVICECAPS( oPrn:hDC, LOGPIXELSY ) // pixel
  nLMarg := aMargins[ 2 ] / 2540 * GETDEVICECAPS( oPrn:hDC, LOGPIXELSX )
  nRMarg := aMargins[ 3 ] / 2540 * GETDEVICECAPS( oPrn:hDC, LOGPIXELSX )
  nBMarg := aMargins[ 4 ] / 2540 * GETDEVICECAPS( oPrn:hDC, LOGPIXELSY )

  AEval( aMargins, { |x,y|  aMargins[y] := x/1000 } )        // Margin in cm

  aPos := oPrn:Pix2Mmtr (nTMarg,nLMarg)

  aPos[1] := aPos[1]/10
  aPos[2] := aPos[2]/10


  PAGE

   for i := 1 TO 35
     oPrn:CmSay (aPos[1]+y,aPos[2], "Line "+Str(i,2)+" ,Testline")
     aPos[1] := aPos[1] + y
   next

   aFrom := oPrn:Cmtr2Pix (aPos[1]+1,aPos[2])
   aTo   := oPrn:Cmtr2Pix (nVertSize-aMargins[4],nHorzSize-aMargins[3]) // (nRow,nCol)
   aRect := {aFrom[1],aFrom[2],aTo[1],aTo[2]}

   oPrn:Box (aRect[1],aRect[2],aRect[3],aRect[4]) // (top,left,bottom,right)
  //aLine := oDoc:PrintBox (If( lPreview, oPrn:hDCOut, oPrn:hDC ), aFrom[1]+50,aFrom[2]+50,aTo[2]-5,aTo[1]-5, 0)
  // oPrn:Say (aLine[2]+100,nLMarg, "Zeile 2 des Testausdruckes")

    PrintRect (oPrn:hDC, aRect[1]+250, aRect[2]+250, aRect[3]-100, aRect[4]-100)
 // oPrn:Say (aLine[2]+100,nLMarg, "Zeile 2 des Testausdruckes")

   ENDPAGE

  ENDPRINT

RETURN (nil)




#define PIXELPERCM 472.44
//----------------------------------------------------------------------------//
STATIC FUNCTION PrintRect (hDC, nTop, nLeft, nBottom, nRight)

  LOCAL lResult //:= .f.
  DEFAULT nTop := 2.5,;    // cm
          nLeft := 2.5,;
          nBottom := nTop + 15,;
          nRight := nLeft + 10
/*
  nTop := nTop * PIXELPERCM    // umrechnen in pixel
  nLeft := nLeft * PIXELPERCM
  nBottom := nBottom * PIXELPERCM
  nRight := nRight * PIXELPERCM
*/

  lResult := REPrintRect (oRTF:hWnd, hDC, nTop, nLeft, nBottom, nRight)
  ? lResult[1],lResult[2],lResult[3]

RETURN (nil)


#pragma BEGINDUMP

#include <Windows.h>
#include <HbApi.h>
#include <Richedit.h>

//------------------------------------------------------------------------------------------------------------------------------
HB_FUNC( REPRINTRECT )
{
    HWND hwnd = (HWND) hb_parnl (1);
    HDC  hdc  = (HDC) hb_parnl (2);
    BOOL bSuccess = TRUE;
    //INT  nSuccess = 0;

    int TwipsPerPixelX = 1440/GetDeviceCaps (hdc,LOGPIXELSX);  //Twips per Pixel
    int TwipsPerPixelY = 1440/GetDeviceCaps (hdc,LOGPIXELSY);

    int cxPhysOffset = GetDeviceCaps(hdc, PHYSICALOFFSETX);
    int cyPhysOffset = GetDeviceCaps(hdc, PHYSICALOFFSETY);
    //int cxPhys = GetDeviceCaps(hdc, PHYSICALWIDTH);
    //int cyPhys = GetDeviceCaps(hdc, PHYSICALHEIGHT);

    int nHorzRes = GetDeviceCaps( hdc, HORZRES ); // Printarea in pixel  
    int nVertRes = GetDeviceCaps( hdc, VERTRES ); //

    int nTop    = (hb_parnl(3)==NULL) ? cyPhysOffset : hb_parnl(3) ;
    int nLeft   = (hb_parnl(4)==NULL) ? cxPhysOffset : hb_parnl(4) ;
    int nBottom = (hb_parnl(5)==NULL) ? cyPhysOffset+nVertRes : hb_parnl(5) ;
    int nRight  = (hb_parnl(6)==NULL) ? cxPhysOffset+nHorzRes : hb_parnl(6) ;

    long lPrinted = 0;
    //long lToPrint = 0;

    FORMATRANGE fr;
    //CHARRANGE cr;

    //SetMapMode (hdc, MM_TEXT);

    fr.hdc = hdc;
    fr.hdcTarget = hdc;

    fr.rcPage.top = 0;
    fr.rcPage.left = 0;
    fr.rcPage.bottom = nVertRes*TwipsPerPixelY;
    fr.rcPage.right  = nHorzRes*TwipsPerPixelX;
    //fr.rc.top   =  fr.rcPage.top+1440;
    //fr.rc.left  =  fr.rcPage.left+1440;
    //fr.rc.bottom = fr.rcPage.bottom;
    //fr.rc.right =  fr.rcPage.right;
    fr.rc.top   =  nTop*TwipsPerPixelY;
    fr.rc.left  =  nLeft*TwipsPerPixelX;
    fr.rc.bottom = nBottom*TwipsPerPixelY;
    fr.rc.right =  nRight*TwipsPerPixelX;

    //fr.chrg.cpMin = 0;
    //fr.chrg.cpMax = -1;

    SendMessage(hwnd, EM_SETSEL, 0, -1);                  // Select the entire contents.
    SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&fr.chrg);  // Put the selection into a CHARRANGE.

    //lToPrint = SendMessage (hwnd, WM_GETTEXTLENGTH,0,0);
    //lToPrint = SendMessage (hwnd, WM_GETTEXTLENEX,0,0);

    //SendMessage(hwnd, EM_FORMATRANGE, (WPARAM) 0, (LPARAM) 0);

    while (fr.chrg.cpMin < fr.chrg.cpMax ) //&& bSuccess)
    {
       // nSuccess = StartPage(hdc);
       // bSuccess = nSuccess >= 0;
       // if (!fSuccess) break;
        lPrinted = SendMessage(hwnd, EM_FORMATRANGE, (WPARAM) 1, (LPARAM) &fr);
        //lPrinted = SendMessage(hwnd, EM_FORMATRANGE, (WPARAM) 0, (LPARAM) &fr);
        //           SendMessage(hwnd, EM_DISPLAYBAND, (WPARAM) 0, (LPARAM) &fr.rc);

        if (lPrinted <= fr.chrg.cpMin)
          {
            bSuccess = FALSE;
            break;
          }
        fr.chrg.cpMin = lPrinted;
        fr.rc.top   =  fr.rcPage.top+1440;     // define new area for the next pages
        //fr.rc.left  =  fr.rcPage.left+1440;
        fr.rc.bottom = fr.rcPage.bottom;
        //fr.rc.right =  fr.rcPage.right;
        EndPage (hdc);
    }

    SendMessage(hwnd, EM_FORMATRANGE, (WPARAM) 0, (LPARAM) 0);

    hb_reta (3);

    hb_stornl (lPrinted, -1, 1);
    hb_stornl (fr.rc.top, -1, 2);
    hb_stornl (fr.rc.bottom, -1, 3);

    //hb_retni (lPrinted);

}

#pragma ENDDUMP
This is the result:

Image

Posted: Fri Aug 03, 2007 5:59 pm
by Antonio Linares
Stefan,

It looks as you are doing good progress. I can't debug/trace your code these days as I am busy with other tasks. I can help you on some specific questions only.

Posted: Fri Aug 03, 2007 9:50 pm
by reinaldocrespo
Maybe this will help. Below is a method from a class where I do printing of 4 different rtf objects. It shows how to continue printing page after page until the 4 rtf objects have been processed.

Code: Select all

*-------------------------------------------------------------------------------------------------------------------------------
METHOD PrintBodyWithAttributes() CLASS Transcription

local cTitle := "Title goes here"
local nFrom		:= 0
local a 		:= ::oprn:Inch2Pix( ::nTop, ::nLeft )
local b		:= ::oprn:Inch2Pix( ::nRight, ::nBottom )
local isdone	:= .f.
local aoRtf		:= { ::oTranscript:ortf1, ::oTranscript:ortf2, ::oTranscript:ortf3, ::oTranscript:ortf4 } 
local i		:= 1
local aRet
local nLen
local aFont, nColor
local nTotPage	:= 0

	::nLastLine := ::oPrn:Pix2Inch( a[ 1 ], 0 )[1]

	While !isdone

		RESetSelection( aoRtf[i]:hWnd, nFrom, -1)
		nLen	:= Len( aoRtf[ i ]:GetSel() ) -1
		aRet := REPrintBox( aoRtf[i]:hWnd, iif( ::isPreview, ::oPrn:hDCOut, ::oPrn:hDC ),.t., a[1 ], a[2], b[1], b[2], nFrom )
		nFrom := aRet[ 1 ]

		DO CASE
			CASE nFrom < nlen			//did not finish current rtf, must run over to next page

				ntotPage++	
				aoRtf[i]:nPrintedPages++	//number of pages ocupied by current rtf
				::oprn:InchSay( 10.53, 7.5, "Page " + Str( nTotPage, 2 ), ::aFonts[ 1 ],,,, PAD_RIGHT )
				::oprn:InchSay( 10.0, 4.25, "Continues on page " + str( nTotPage + 1, 2 ) + "...", ::ofont,,,, 2 )

				::oprn:endPage()
				::oprn:Startpage()

				a := ::oprn:Inch2Pix( ::ntop, ::nLeft )				//new print region
				b := ::oprn:Inch2Pix( ::nRight, ::nBottom )				//area for text

			CASE i == 4
				isdone := .t.

			CASE i < 4
				if !empty( aoRtf[ i ]:GetText() )
					::nLastLine := ::oPrn:Pix2Inch( aRet[ 2 ], 0 )[1]	//findout where was last line printed
					::nlastline += 0.32						//add couple of blank lines
				Endif

				i++	;nFrom := 0							//restart position zero for new rtf
				a := ::oprn:Inch2Pix( ::nLastLine, ::nLeft )		//new print region

			OTHERWISE				//unknown problems --get the hell out of here
				isdone := .t.
		END
	End

	::oprn:InchSay( 10.53, 7.5, "Page " + Str( nTotPage+1, 2 ), ::aFonts[ 1 ],,,, PAD_RIGHT )
	::nLastLine := ::oPrn:Pix2Inch( aRet[ 2 ], 0 )[ 1 ]	//Save pos where last line printed before printing footer

return nil
If you are only printing 1 rtf, then the code would be much simpler. Most of the work you need is inside the 1st case in the code above.


Reinaldo.

Posted: Mon Aug 06, 2007 8:00 am
by StefanHaupt
Antionio,
Antonio Linares wrote:I can help you on some specific questions only.

ok, thanks. I think the main problem is, to get the row of the last line of the rtf-text in printer-units. The struct FORMATRANGE holds only the whole page.

Do you have an idea ?

Posted: Mon Aug 06, 2007 8:05 am
by StefanHaupt
Reinaldo,

thanks for your function, but I had problems with the function REPrintRect().
In my tests it does not respect the margins and does not eject the page properly if you start in the middle of a page.

If it works for you, maybe my test was faulty. I will check this.