2016-09-23 109 views
1

我已将RichEdit放在表单上以表示页面的一部分。 “页面”的大小会减小,以便用户可以看到整个页面以评估输入的效果。当打印“页面”时,RichEdit区域被展开并在打印机页面上移动到所需的位置。下面的代码很好地解决了一个小问题(读取MASSIVE)问题。字体不会缩放。打印RichEdit时缩放字体XE5

我试着玩弄设置窗口和视口的起源和范围,因为我所做的阅读似乎指向了这一点。不幸的是,我没有成功。有人能指点我正确的方向吗?

procedure TForm10.PrintNewClick(Sender: TObject); 
const 

PgHeight=1170; 
PgWidth=1170*210 div 294; 
var 
    EdTop,EdLeft,EdWidth,EdHeight :integer; 
    wPage, hPage, xPPI, yPPI, wTwips, hTwips: integer; 
    pageRect, rendRect, outline: TRect; 
    po: TPageOffset; 
    fr: TFormatRange; 
    lastOffset, currPage, pageCount: integer; 
    xOffset, yOffset: integer; 
    FPageOffsets: array of TPageOffset; 
    TextLenEx: TGetTextLengthEx; 
    firstPage: boolean; 
    PrinterRatioH,PrinterRatioV, ratio:Real; 
begin 
    Printer.Orientation:=poPortrait; 
    //get printer to 'page' ratios 
    PrinterRatioH :=Printer.PageWidth/PgWidth; 
    PrinterRatioV :=Printer.PageHeight/PgHeight; 

    //get positions and size of richedit on screen 'page' 
    //top of richedit on screen page 
    EdTop:=StrToInt(EditTop.Text); 
    //left of richedit on screen page 
    if EditCentre.Checked then 
    EdLeft:=(PgWidth-StrToInt(EditWidth.Text)) div 2 
    else 
    EdLeft:=StrToInt(EditLeft.Text); 
    //Width of richedit on screen page 
    EdWidth:=StrToInt(EditWidth.Text); 
    // Height of richedit on screen page 
    EdHeight:=StrToInt(EditHeight.Text); 

    //get bounding richedit rectangle on printer 
    with outline do 
    begin 
    left:=Round(EdLeft*PrinterRatioH); 
    top:=Round(EdTop*PrinterRatioV); 
    Right:=Left+Round(EdWidth*PrinterRatioH); 
    Bottom:=Top+Round(EdHeight*PrinterRatioV); 
    end; 

    //Get the size of a printed page in printer device units 
    wPage := GetDeviceCaps(Printer.Handle, PHYSICALWIDTH); 
    hPage := GetDeviceCaps(Printer.Handle, PHYSICALHEIGHT); 
    //Next, get the device units per inch for the printer 
    xPPI := GetDeviceCaps(Printer.Handle, LOGPIXELSX); 
    if TwipFactor=567 then 
    xPPI :=round(xPPI/2.54); //change to metric base 
    yPPI := GetDeviceCaps(Printer.Handle, LOGPIXELSY); 
    if TwipFactor=567 then 
    yPPI :=round(yPPI/2.54); 
    //Convert the page size from device units to twips 
    wTwips := MulDiv(wPage, TwipFactor, xPPI); 
    hTwips := MulDiv(hPage, TwipFactor, yPPI); 
    //Save the page size in twips 
    with pageRect do 
    begin 
    Left := 0; 
    Top := 0; 
    Right := wTwips; 
    Bottom := hTwips 
    end; 

    //calculate the size and position of the rendering rectangle in twips 
    with rendRect do 
    begin 
    Left :=MulDiv(Outline.Left, TwipFactor, xPPI); 
    Top := MulDiv(Outline.Top, TwipFactor, yPPI); 
    Right := MulDiv(Outline.Right, TwipFactor, xPPI); 
    Bottom := MulDiv(Outline.Bottom, TwipFactor, yPPI); 
    end; 

    //set starting offset to zero 
    po.mStart := 0; 
    //Define and initialize a TFormatRange structure. 
    with fr do 
    begin 
    hdc := Printer.Handle; 
    hdcTarget := Printer.Handle; 
    chrg.cpMin := po.mStart; 
    chrg.cpMax := -1; 
    end; 
    // how much text is in the control. 
    with TextLenEx do 
    begin 
    flags := GTL_DEFAULT; 
    codepage := CP_ACP; 
    end; 
    lastOffset := SendMessage(TestEdit.Handle, EM_GETTEXTLENGTHEX, wParam(@TextLenEx), 0); 

    //clear the formatting buffer 
    SendMessage(TestEdit.Handle, EM_FORMATRANGE, 0, 0); 

    SaveDC(fr.hdc); 
    SetMapMode(fr.hdc, MM_ANISOTROPIC{MM_TEXT}); 

    SetViewportOrgEx(fr.hdc, 0, 0, nil); 
    SetViewportExtEx(fr.hdc, TestEdit.Width ,testedit.Height , nil); 
    //build a table of page entries, 
    while ((fr.chrg.cpMin <> -1) and (fr.chrg.cpMin < lastOffset)) do 
    begin 
    fr.rc := rendRect; 
    fr.rcPage := pageRect; 
    po.mStart := fr.chrg.cpMin; 
    fr.chrg.cpMin := SendMessage(TestEdit.Handle, EM_FORMATRANGE, 0, Longint(@fr)); 
    po.mEnd := fr.chrg.cpMin - 1; 
    po.rendRect := fr.rc; 
    if High(FPageOffsets) = -1 then SetLength(FPageOffsets, 1) 
    else 
     SetLength(FPageOffsets, Length(FPageOffsets) + 1); 
    FPageOffsets[High(FPageOffsets)] := po 
    end; 
    pageCount := Length(FPageOffsets); 

    SendMessage(TestEdit.Handle, EM_FORMATRANGE, 0, 0); 
    RestoreDC(fr.hdc, - 1); 
    // print. 
    Printer.BeginDoc; 
    fr.hdc := Printer.Handle; 
    fr.hdcTarget := Printer.Handle; 
    SaveDC(fr.hdc); 
    SetViewportOrgEx(fr.hdc, 0, 0, nil); 
    SetViewportExtEx(fr.hdc, TestEdit.Width ,testedit.Height , nil); 

    firstPage := True; 
    //select from page and to page 
    currPage := 0; //Print from the first page 
    pageCount := 1; //Only One page for testing REMOVE LATER!!! 
    while (currPage < pageCount) do 
    begin 
     if firstPage then 
     firstPage := False 
     else 
     Printer.NewPage; 
     SetViewportExtEx(fr.hdc, TestEdit.Width ,testedit.Height 
     , nil); 
     fr.rc := FPageOffsets[currPage].rendRect; 
     fr.rcPage := pageRect; 
     fr.chrg.cpMin := FPageOffsets[currPage].mStart; 
     fr.chrg.cpMax := FPageOffsets[currPage].mEnd; 
     fr.chrg.cpMin := SendMessage(TestEdit.Handle, EM_FORMATRANGE, 1, Longint(@fr)); 
     Inc(currPage); 
    end; 
    SetViewportOrgEx(fr.hdc, 0, 0, nil); 
    //draw bounding rect 
    Printer.Canvas.MoveTo(outline.Left-2,outline.Top-2); 
    Printer.Canvas.LineTo(outline.Right+4,outline.Top-2); 
    Printer.Canvas.LineTo(outline.Right+4,outline.Bottom+4); 
    Printer.Canvas.LineTo(outline.Left-2,outline.Bottom+4); 
    Printer.Canvas.LineTo(outline.Left-2,outline.Top-2); 

    //restore the printer's HDC settings 
    RestoreDC(fr.hdc, - 1); 
    Printer.EndDoc; 
    // clear RichEdit control's formatting buffer 
    fr.chrg.cpMin := SendMessage(TestEdit.Handle, EM_FORMATRANGE, 0, 0); 
    //delete saved page table info 
    Finalize(FPageOffsets); 

end; 
+0

为什么要标记XE如果您使用XE5? –

+0

因为我没看到XE5 :-( – Badger

+0

)让我告诉你如何标记这个问题,看看我的编辑。如果版本是相关的,请始终包含简单的'delphi'标签以及与版本匹配的特定标签。 –

回答

0

我终于找到了答案(不幸的是通过反复试验而不是逻辑)。以下是我用于类似情况的代码: -

Procedure DoRTF(RTF:TRichedit); 
        var 
         r: TRect; 
         richedit_outputarea: TRect; 
         printresX, printresY: Real; 
         fmtRange: TFormatRange; 
         Ratio:Real; 
         ScaleFactor:Real; 
        Begin 
         ScaleFactor:= 1; 
         try 
         Ratio:=GetDeviceCaps(printer.canvas.handle, LOGPIXELSX)/GetDeviceCaps(MainForm.canvas.handle, LOGPIXELSX); 
         //"r" is the position of the richedit on the printer page  
         r:= Rect(badgerect.left+round((RTF.Left-WordsBottom.Left)*Ratio), 
            badgerect.Top+round((RTF.Top-WordsTop.Top)*Ratio), 
            badgerect.left+round((RTF.Left-WordsBottom.Left)*Ratio +RTF.width*Ratio), 
            badgerect.Top+round((RTF.Top-WordsTop.Top)*Ratio+RTF.Height*Ratio) ); 

         SetMapMode(printer.canvas.handle, MM_ANISOTROPIC); 
         SetWindowExtEx(printer.canvas.handle, 
             GetDeviceCaps(printer.canvas.handle, LOGPIXELSX), 
             GetDeviceCaps(printer.canvas.handle, LOGPIXELSY), 
             Nil); 
         SetViewportExtEx(printer.canvas.handle, 
             Round(GetDeviceCaps(printer.canvas.handle, LOGPIXELSX)*ScaleFactor), 
             Round(GetDeviceCaps(printer.canvas.handle, LOGPIXELSY)*ScaleFactor), 
             Nil); 

         With Printer.Canvas Do 
         Begin 
          printresX := GetDeviceCaps(handle, LOGPIXELSX) ; 
          printresY := GetDeviceCaps(handle, LOGPIXELSY) ; 

          richedit_outputarea := 
          Rect( round(r.left * 1440/printresX), 
            round(r.top * 1440/printresY), 
            round(r.right * 1440/printresX), 
            round(r.bottom* 1440/printresY)); 

          fmtRange.hDC := Handle; 
          fmtRange.hdcTarget := Handle; 
          fmtRange.rc := richedit_outputarea; 
          fmtRange.rcPage:= 
          Rect(0, 0, 
            round(Printer.PageWidth * 1440/printresX) , 
            round(Printer.PageHeight * 1440/printresY)); 
          fmtRange.chrg.cpMin := 0; 
          fmtRange.chrg.cpMax := RTF.GetTextLen-1; 

          // format text 
          RTF.Perform(EM_FORMATRANGE, 1, Longint(@fmtRange)); 

          // Free cached information 
          RTF.Perform(EM_FORMATRANGE, 0, 0); 
         End 
         finally 

         end; 
        End;