Delphi,Rxlib,RxRichEdit,Richedit 高版本 ,Rich Text Edit Control, v4.1 控件,打印Bug

我们知道 RichEdit 是M$提供的标准控件,delphi的vcl里面是很老的版本,而rxlib的有最新的4.1的封装

 

但是bug很多 ,比如查找替换 ,中文支持,打印等等,下面代码就是解决的打印问题,来自国外某网站,

 

自己根据情况,有调整

 

Why? ---为什么使用这个高版本呢?这个版本的RTF控件,支持插入表格(当然是用接口罗),支持从word粘贴表格

不变形,插入图片很方便,那么还有什么理由拒绝呢?

 

代码
//打印rxrichedit
//可以设置左边,上边距,单位inch
//eg:
//  printrxrichedit(editor,0.5,0.5);

unit uPrintRxRichEdit;

interface

uses Windows,messages,RxRichEd ,RichEdit,printers,math;

type
  TPageOffset 
= record
    mStart,
      mEnd: Integer;
    rendRect: TRect;
  
end;

//打印rxrichedit
function printRxRichEdit(editor:TRxRichEdit;leftoffset,topoffset:double):integer;

  
implementation

//打印rxrichedit ,返回值是页数
function printRxRichEdit(editor:TRxRichEdit;leftoffset,topoffset:double):integer;
var
  wPage, hPage, xPPI, yPPI, wTwips, hTwips: integer;
  pageRect, rendRect: TRect;
  po: TPageOffset;
  fr: TFormatRange;
  lastOffset, currPage, pageCount: integer;
  xOffset, yOffset: integer;
  FPageOffsets: 
array of TPageOffset;
  TextLenEx: TGetTextLengthEx;
  firstPage: boolean;
begin
  
//First, 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);
  yPPI :
= GetDeviceCaps(Printer.Handle, LOGPIXELSY);
  
//Convert the page size from device units to twips
  wTwips :
= MulDiv(wPage, 1440, xPPI);
  hTwips :
= MulDiv(hPage, 1440, yPPI);
  
//Save the page size in twips
  
with pageRect do
  
begin
    Left :
= 0;
    Top :
= 0;
    Right :
= wTwips;
    Bottom :
= hTwips
  
end;
  
//Next, calculate the size of the rendering rectangle in twips
  
//Rememeber - two inch margins are hardcoded, so the below code
  
//reduces the width of the output by four inches
  
with rendRect do
  
begin
    Left :
= 0;
    Top :
= 0;
    
//Right := pageRect.Right - (1440 * 4);
    
//Bottom := pageRect.Bottom - (1440 * 4)
     Right :
= pageRect.Right - floor(1440 * leftoffset * 2); //左右 上下边距相同
     Bottom :
= pageRect.Bottom - floor(1440 * topoffset * 2);

  
end;
  
//Define a single page and set starting offset to zero
  po.mStart :
= 0;
  
//Define and initialize a TFormatRange structure. This structure is passed
  
//to the TRichEdit with a request to format as much text as will fit on a
  
//page starting with the chrg.cpMin offset and ending with the chrg.cpMax.
  
//Initially, we tell the RichEdit control to start at the beginning
  
//(cpMin = 0and print as much as possible (cpMax = -1). We also tell it
  
//to render to the printer
  
with fr do
  
begin
    hdc :
= Printer.Handle;
    hdcTarget :
= Printer.Handle;
    chrg.cpMin :
= po.mStart;
    chrg.cpMax :
= -1;
  
end;
  
//In order to recognize when the last page is rendered, we need to know how
  
//much text is in the control.
  
if RichEditVersion >= 2 then
  
begin
    
with TextLenEx do
    
begin
      flags :
= GTL_DEFAULT;
      codepage :
= CP_ACP;
    
end;
    lastOffset :
= SendMessage(Editor.Handle, EM_GETTEXTLENGTHEX, wParam(@TextLenEx), 0)
  
end
  
else
    lastOffset :
= SendMessage(Editor.Handle, WM_GETTEXTLENGTH, 00);
  
//As a precaution, clear the formatting buffer
  SendMessage(Editor.Handle, EM_FORMATRANGE, 
00);
  
//Printers frequently cannot print at the absolute top-left position on the
  
//page. In other words, there is usually a minimum margin on each edge of the
  
//page. When rendering to the printer, RichEdit controls adjust the top-left
  
//corner of the rendering rectangle for the amount of the page that is
  
//unprintable. Since we are printing with two-inch margins, we are presumably
  
//already within the printable portion of the physical page.
  SaveDC(fr.hdc);
  SetMapMode(fr.hdc, MM_TEXT);
  xOffset :
= GetDeviceCaps(Printer.Handle, PHYSICALOFFSETX);
  yOffset :
= GetDeviceCaps(Printer.Handle, PHYSICALOFFSETY);

  
//添加了2inch边,取消就ok
  
//改为 参数指定,参数是小数允许的
  
//xOffset := xOffset + MulDiv(1440 + 1440, xPPI, 1440);
  
//yOffset := yOffset + MulDiv(1440 + 1440, yPPI, 1440);
   xOffset :
= xOffset + MulDiv(floor(1440 * leftoffset), xPPI, 1440);
   yOffset :
= yOffset + MulDiv(floor(1440 * topoffset), yPPI, 1440);

  SetViewportOrgEx(fr.hdc, xOffset, yOffset, 
nil);

  
//Now we build a table of page entries, one entry for each page that would be
  
//printed.
  
while ((fr.chrg.cpMin <> -1and (fr.chrg.cpMin < lastOffset)) do
  
begin
    fr.rc :
= rendRect;
    fr.rcPage :
= pageRect;
    po.mStart :
= fr.chrg.cpMin;
    fr.chrg.cpMin :
= SendMessage(Editor.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);
  
//ShowMessage(Format('Es wurde %d Seiten ermittelt', [pageCount]));
  SendMessage(Editor.Handle, EM_FORMATRANGE, 
00);
  RestoreDC(fr.hdc, 
-1);
  
//Now, we are almost ready to actually print.
  Printer.BeginDoc;
  fr.hdc :
= Printer.Handle;
  fr.hdcTarget :
= Printer.Handle;
  SaveDC(fr.hdc);
  SetViewportOrgEx(fr.hdc, xOffset, yOffset, 
nil);
  
//Ok, here we go to print
  firstPage :
= True;
  
//At this point you can select from page and to page
  currPage :
= 0//Print from the first page
  
//不只一页
  
//pageCount := 1//Only One page for testing
  
while (currPage < pageCount) do
  
begin
    
if firstPage then
      firstPage :
= False
    
else
      Printer.NewPage;
    SetViewportOrgEx(fr.hdc, xOffset, yOffset, 
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(Editor.Handle, EM_FORMATRANGE, 1, Longint(@fr));
    Inc(currPage);
  
end;
  
//At this point, we have finished rendering the contents of the RichEdit
  
//control. Now we restore the printer's HDC settings and tell Windows that
  //we are through printing this document
  RestoreDC(fr.hdc, 
-1);
  Printer.EndDoc;
  
//Finally, we clear the RichEdit control's formatting buffer and delete
  //the saved page table information
  fr.chrg.cpMin :
= SendMessage(Editor.Handle, EM_FORMATRANGE, 00);
  Finalize(FPageOffsets);
  
//That's it

  result :
= pagecount;
end;

end.
 

 

 

posted @ 2010-07-01 18:11  苹果X1  阅读(1353)  评论(0编辑  收藏  举报