DrawPageAt to bitmap, metafile
DrawPageAt to bitmap, metafile
Hi Sergey,
I am trying to print preview. Our reporting engine works like this. It uses and informational device context (CreateIC) compatible with the default printer. Than all output methods are overridden in such way, that the actual "output" happens in a memory stream. So the DC is only used for measuring draw items.
To connect the engine with TRichView control, I decided to output the content into a bitmap (I also tried with a metafile) than, I would "Draw" the bitmap with our reporting engine. Thus, I should get an image of the richview at the coordinates computed in the printing engine. However the image is not coming out at all. To debug, intermediary I printed the image to some external file (bmp, emf) and I found out that the text is very very small
I do not know what I am doing wrong. This is how I implemented it:
I create a TRVReportHelper object, load its RichView from a database blob (LoadRVFFromStream):
- call Helper.Init(SomeCanvas, DocWidth), somecanvas is either a tbitmap.canvas or a TMetafileCanvas;
- call Helper.FormatNextPage(DocHeight)
- call Helper.DrawPageAt(0, 0, PageNo, somecanvas, True, DocHeight);
Any idea what I may be doing wrong. For example I understand that in DrawPageAt I should use true for Preview parameter and also that the Canvas should be a "true" output Canvas (like RV_GetPrinterDC or for a bitmap, TBitmap.Canvas)...?
Thx
I am trying to print preview. Our reporting engine works like this. It uses and informational device context (CreateIC) compatible with the default printer. Than all output methods are overridden in such way, that the actual "output" happens in a memory stream. So the DC is only used for measuring draw items.
To connect the engine with TRichView control, I decided to output the content into a bitmap (I also tried with a metafile) than, I would "Draw" the bitmap with our reporting engine. Thus, I should get an image of the richview at the coordinates computed in the printing engine. However the image is not coming out at all. To debug, intermediary I printed the image to some external file (bmp, emf) and I found out that the text is very very small
I do not know what I am doing wrong. This is how I implemented it:
I create a TRVReportHelper object, load its RichView from a database blob (LoadRVFFromStream):
- call Helper.Init(SomeCanvas, DocWidth), somecanvas is either a tbitmap.canvas or a TMetafileCanvas;
- call Helper.FormatNextPage(DocHeight)
- call Helper.DrawPageAt(0, 0, PageNo, somecanvas, True, DocHeight);
Any idea what I may be doing wrong. For example I understand that in DrawPageAt I should use true for Preview parameter and also that the Canvas should be a "true" output Canvas (like RV_GetPrinterDC or for a bitmap, TBitmap.Canvas)...?
Thx
-
- Site Admin
- Posts: 17557
- Joined: Sat Aug 27, 2005 10:28 am
- Contact:
All right, it started to work. Now I have another problem. For me, FormatNextPage always returns true, even though the full content for the richview fits on the first page. Here is a piece from how I coded it (you'll the WHILE loop should break when FormatNextPage would return false, however it never happens for me):
while TRUE do
begin
if fPrinter.LinesLeft < 6 then
fPrinter.NewPage;
Inc(PageNo);
DocTop := fPrinter.CursorYPos;
DocHeight := DocBottom - DocTop;
G := PrintWithMeta(fPrinter.Canvas.Handle);
if Assigned(G) then
try
ImageBounds := Rect(DocLeft, DocTop, DocLeft+DocWidth, DocTop+lRVHelper.EndAt);
fPrinter.StretchDraw(ImageBounds, G);
NewPos := fPrinter.XD2U(lRVHelper.EndAt);
fPrinter.YPos := fPrinter.YPos + NewPos;
finally
FreeAndNil(G);
end
else
BREAK;
end;
function PrintWithMeta(DC: HDC): TBitmap;
var
M: TMetafile;
MC: TMetafileCanvas;
begin
Result := nil;
M := TMetafile.Create;
try
M.Height := DocHeight;
M.Width := DocWidth;
MC := TMetafileCanvas.Create(M, DC);
try
MC.Font.PixelsPerInch := GetDeviceCaps(DC, LOGPIXELSY);
lRVHelper.Init(MC, DocWidth);
if not lRVHelper.FormatNextPage(DocHeight) then
EXIT
else
lRVHelper.DrawPageAt(0, 0, PageNo, MC, True, DocHeight);
finally
MC.Free;
end;
Result := GetImage(M);
finally
M.Free;
end;
end;
function GetImage(Drawing: TGraphic): TBitmap;
begin
Result := TBitmap.Create;
Result.Width := DocWidth;
Result.Height := lRVHelper.EndAt;
Result.Canvas.Draw(0, 0, Drawing);
//Result.SaveToFile('p:\test.bmp');
end;
while TRUE do
begin
if fPrinter.LinesLeft < 6 then
fPrinter.NewPage;
Inc(PageNo);
DocTop := fPrinter.CursorYPos;
DocHeight := DocBottom - DocTop;
G := PrintWithMeta(fPrinter.Canvas.Handle);
if Assigned(G) then
try
ImageBounds := Rect(DocLeft, DocTop, DocLeft+DocWidth, DocTop+lRVHelper.EndAt);
fPrinter.StretchDraw(ImageBounds, G);
NewPos := fPrinter.XD2U(lRVHelper.EndAt);
fPrinter.YPos := fPrinter.YPos + NewPos;
finally
FreeAndNil(G);
end
else
BREAK;
end;
function PrintWithMeta(DC: HDC): TBitmap;
var
M: TMetafile;
MC: TMetafileCanvas;
begin
Result := nil;
M := TMetafile.Create;
try
M.Height := DocHeight;
M.Width := DocWidth;
MC := TMetafileCanvas.Create(M, DC);
try
MC.Font.PixelsPerInch := GetDeviceCaps(DC, LOGPIXELSY);
lRVHelper.Init(MC, DocWidth);
if not lRVHelper.FormatNextPage(DocHeight) then
EXIT
else
lRVHelper.DrawPageAt(0, 0, PageNo, MC, True, DocHeight);
finally
MC.Free;
end;
Result := GetImage(M);
finally
M.Free;
end;
end;
function GetImage(Drawing: TGraphic): TBitmap;
begin
Result := TBitmap.Create;
Result.Width := DocWidth;
Result.Height := lRVHelper.EndAt;
Result.Canvas.Draw(0, 0, Drawing);
//Result.SaveToFile('p:\test.bmp');
end;
forget about last question
I think I got it. The Init call must happen only once, I call it for page one, but than since I "print" to TMetafileCanvas I must update PrinterCanvas property, new code something like:
TReportRVData(TReportRichView(lRVHelper.RichView).RVData).PrinterCanvas := MC;
Pretty ugly looks this , do you have a nicer suggestion Sergey?
Thx,
Lucian
TReportRVData(TReportRichView(lRVHelper.RichView).RVData).PrinterCanvas := MC;
Pretty ugly looks this , do you have a nicer suggestion Sergey?
Thx,
Lucian
-
- Site Admin
- Posts: 17557
- Joined: Sat Aug 27, 2005 10:28 am
- Contact:
-
- Site Admin
- Posts: 17557
- Joined: Sat Aug 27, 2005 10:28 am
- Contact:
It started to work
His Sergey,
It works for small data. However I have a 2-3 pages piece which doesn't work correctly. It only shows last page with my code. On the first page, the data should start at about 8 cm from the top of the page, than, the eventual other pages should start at about 3.5 cm. For whatever reason, the TRVReportHelper doesn't want to start with the beginning of the data (not sure how to explain). My code is something like this.
function PrintWithMeta(DC: HDC): TGraphic;
var
M: TMetafile;
MC: TMetafileCanvas;
begin
Result := nil;
M := TMetafile.Create;
try
M.Height := DocHeight; // 4786
M.Width := DocWidth; // 3922
MC := TMetafileCanvas.Create(M, DC);
try
MC.Font.PixelsPerInch := GetDeviceCaps(DC, LOGPIXELSY); // 600
if PageNo = 1 then
lRVHelper.Init(MC, DocWidth);
if not lRVHelper.FormatNextPage(DocHeight) then
EXIT
else
lRVHelper.DrawPageAt(0, 0, PageNo, MC, True, DocHeight);
(*
the problem seems to be that after first run of this method,
lRVHelper.EndAt is still 0, as if nothing fits
*)
finally
MC.Free;
end;
// use another metafile with correct height
Result := TMetafile.Create;
Result.Height := lRVHelper.EndAt;
Result.Width := DocWidth;
MC := TMetafileCanvas.Create(TMetafile(Result), DC);
try
MC.Draw(0, 0, M);
finally
MC.Free;
end;
finally
M.Free;
end;
end;
Any ideas?
Thx
Lucian
It works for small data. However I have a 2-3 pages piece which doesn't work correctly. It only shows last page with my code. On the first page, the data should start at about 8 cm from the top of the page, than, the eventual other pages should start at about 3.5 cm. For whatever reason, the TRVReportHelper doesn't want to start with the beginning of the data (not sure how to explain). My code is something like this.
function PrintWithMeta(DC: HDC): TGraphic;
var
M: TMetafile;
MC: TMetafileCanvas;
begin
Result := nil;
M := TMetafile.Create;
try
M.Height := DocHeight; // 4786
M.Width := DocWidth; // 3922
MC := TMetafileCanvas.Create(M, DC);
try
MC.Font.PixelsPerInch := GetDeviceCaps(DC, LOGPIXELSY); // 600
if PageNo = 1 then
lRVHelper.Init(MC, DocWidth);
if not lRVHelper.FormatNextPage(DocHeight) then
EXIT
else
lRVHelper.DrawPageAt(0, 0, PageNo, MC, True, DocHeight);
(*
the problem seems to be that after first run of this method,
lRVHelper.EndAt is still 0, as if nothing fits
*)
finally
MC.Free;
end;
// use another metafile with correct height
Result := TMetafile.Create;
Result.Height := lRVHelper.EndAt;
Result.Width := DocWidth;
MC := TMetafileCanvas.Create(TMetafile(Result), DC);
try
MC.Draw(0, 0, M);
finally
MC.Free;
end;
finally
M.Free;
end;
end;
Any ideas?
Thx
Lucian
-
- Site Admin
- Posts: 17557
- Joined: Sat Aug 27, 2005 10:28 am
- Contact: