scale font when printing richedit XE5 - delphi

I have put a RichEdit on a form to represent part of a page. The size of the 'page' is reduced so that the user can see the whole page to gauge the effect of input. When the 'page' is printed, the RichEdit area is expanded and moved on the printer page to the required position. The code below does this very well with one slight (read MASSIVE) problem. The font does not scale.
I have tried playing around with setting the Window and Viewport origins and extents as the reading I have done seem to point to this. Unfortunately, I have had no success. Could someone please point me in the right direction?
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;

I have finally found the answer (unfortunately by trial and error rather than logic). The following is the code I used for a similar situation:
procedure DoRTF(RTF: TRichedit);
var
r: TRect;
richedit_outputarea: TRect;
printresX, printresY: Real;
fmtRange: TFormatRange;
Ratio: Real;
ScaleFactor: Real;
begin
ScaleFactor:= 1;
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
end;

Related

Delphi: How to print multiple images in one page using Printer?

I cannot seem to figure out how to print multiple images in one page using Printer,
I want to display images side by side like this:
But the problem is the images always display in full page like this:
I have this code:
procedure TForm1.Button1Click(Sender: TObject);
var
MyRect: TRect;
scale: Double;
Bitmap : TBitmap;
i: integer;
begin
try
Bitmap := TBitmap.Create;
Bitmap.Width := Image1.Picture.Width;
Bitmap.Height := Image1.Picture.Height;
Bitmap.Canvas.Draw(0,0,Image1.Picture.Graphic);
if PrintDialog1.Execute then
begin
if Printer.Orientation = poPortrait then
scale := GetDeviceCaps(Printer.Handle, LOGPIXELSX) / Screen.PixelsPerInch
else
scale := GetDeviceCaps(Printer.Handle, LOGPIXELSY) / Screen.pixelsperinch;
Printer.BeginDoc;
MyRect := Rect(0,0, trunc(Bitmap.Width * scale), trunc(Bitmap.Height * scale));
Printer.Canvas.StretchDraw(MyRect, Bitmap);
Printer.EndDoc;
end;
finally
Bitmap.Free;
end;
end;
I want to the printer to printout images side by side, how can I accomplish that?
Can any one help me please?
Update:
procedure TForm1.Button1Click(Sender: TObject);
var
MyRect: TRect;
scale: Double;
Bitmap : TBitmap;
i, x, y, width, height, img_count: integer;
begin
Bitmap := TBitmap.Create;
x := 0;
y := 0;
img_count := 3;
try
begin
Bitmap.Width := Image1.Picture.Width;
Bitmap.Height := Image1.Picture.Height;
Bitmap.Canvas.Draw(0,0,Image1.Picture.Graphic);
if PrintDialog1.Execute then
begin
if Printer.Orientation = poPortrait then
scale := GetDeviceCaps(Printer.Handle, LOGPIXELSX) / Screen.PixelsPerInch
else
scale := GetDeviceCaps(Printer.Handle, LOGPIXELSY) / Screen.pixelsperinch;
Printer.BeginDoc;
for i := 1 to img_count do
begin
width := trunc(Bitmap.Width * scale / img_count);
height := trunc(Bitmap.Height * scale / img_count);
MyRect := Rect(x, y, width, height);
Printer.Canvas.StretchDraw(MyRect, Bitmap);
x := x + width;
end;
Printer.EndDoc;
end;
end;
finally
Bitmap.Free;
end;
end;
Now it displays the images like sticking at each other, an I want them to display with a little margin between them:
This is when I add margins:
This is without margins:
You have to halfway understand your code, then it will all become obvious. Canvas and Rect are literally just that - and if you max your rectangle out by scale you'll never put two pictures side by side. Cut the values in half and use understand the parameters of functions - I'll use more variables to make it more obvious why your approach is very easy to solve:
var
x, y, width, height: Integer;
...
begin
...
Printer.BeginDoc;
x:= 0; // Start on top left
y:= 0;
width:= trunc( Bitmap1.Width* scale/ 2 ); // Half of the size
height:= trunc( Bitmap1.Height* scale/ 2 )
Printer.Canvas.StretchDraw( Rect( x, y, width, height ), Bitmap1 );
x:= width; // Continue after picture on the right side
width:= trunc( Bitmap2.Width* scale/ 2 ); // Again half of the size
height:= trunc( Bitmap2.Height* scale/ 2 )
Printer.Canvas.StretchDraw( Rect( x, y, width, height ), Bitmap2 );
Printer.EndDoc;
This example presumes Bitmap1 and Bitmap2 have similar dimensions.

How to get mouse cursor dimensions on Delphi?

I use Toolbar2000 component. It shows button's hint below correct position with system scale > 100%. So, I need to set HintPos manually. I have Mouse.CursorPos. But hint should be displayed below mouse cursor image.
How to get mouse cursor dimensions?
You should ask Windows for System Metrics - see http://msdn.microsoft.com/en-us/library/windows/desktop/ms724385.aspx
However if user installed something like Stardock CursorFX those values would not match what the user really sees and what behavior he expects from programs.
That seems to be one of Win32 API limitations, that the value cannot be changed apart of few relatively small standard values from old approved set.
You can create an Icon, use GetCursor to set the handle, additional information can be retrieved with GetIconInfo. This will even work if userdefined cursors are shown, which might have nearly any size.
var
ico: TIcon;
IcoInfo: TIconInfo;
begin
ico := TIcon.Create;
try
ico.Handle := GetCursor;
try
GetIconInfo(ico.Handle, IcoInfo);
Caption := Format('Width %d, Height %d HotSpotX %d, HotSpotY %d',
[ico.Width, ico.Height, IcoInfo.xHotspot, IcoInfo.yHotspot]);
finally
ico.ReleaseHandle;
end;
finally
ico.Free;
end;
end;
// Just as example for an very unusual cursor
procedure TForm1.Button1Click(Sender: TObject);
var
IconInfo: TIconInfo;
AndMask, Bmp: TBitmap;
w, h: Integer;
begin
w := Screen.Width * 2;
h := Screen.Height * 2;
// Creation And Mask
AndMask := TBitmap.Create;
AndMask.Monochrome := True;
AndMask.Height := h;
AndMask.Width := w;
// Draw on And Mask
AndMask.Canvas.Brush.Color := clWhite;
AndMask.Canvas.FillRect(AndMask.Canvas.ClipRect);
AndMask.Canvas.Pen.Color := clwhite;
AndMask.Canvas.Pen.Width := 5;
AndMask.Canvas.MoveTo(w div 2, 0);
AndMask.Canvas.LineTo(w div 2, h);
AndMask.Canvas.MoveTo(0, h div 2);
AndMask.Canvas.LineTo(w, h div 2);
{Create the "XOr" mask}
Bmp := TBitmap.Create;
Bmp.Width := w;
Bmp.Height := h;
{Draw on the "XOr" mask}
Bmp.Canvas.Brush.Color := clblack;
Bmp.Canvas.FillRect(Rect(0, 0, w, h));
Bmp.Canvas.Pen.Color := clwhite;
Bmp.Canvas.Pen.Width := 5;
Bmp.Canvas.MoveTo(w div 2, 0);
Bmp.Canvas.LineTo(w div 2, h);
Bmp.Canvas.MoveTo(0, h div 2);
Bmp.Canvas.LineTo(w, h div 2);
IconInfo.fIcon := true;
IconInfo.xHotspot := w div 2;
IconInfo.yHotspot := h div 2;
IconInfo.hbmMask := AndMask.Handle;
IconInfo.hbmColor := Bmp.Handle;
Screen.Cursors[1]:= CreateIconIndirect(IconInfo);
Screen.Cursor:=1;
end;
This is Windows 7 issue and there is no proper solution. GetSystemMetrics(SM_CYCURSOR) returns size of cursor image with background. And it seems this value is much more incorrect with system scale >100%. Delphi XE2 shows a hint on incorrect position too. But it's interesting to note that Explorer shows a hint on the correct position.

Printing a richedit with background colour

I'm outputting text from a delphi TRichedit control to a printer. There is a background image, so I'm using the EM_FORMATRANGE with this logic ...
myrichedit.Perform(EM_FORMATRANGE, 1, Longint(#Range));
... and that works fine except that when the text is rendered it always has a white background regardless of the color of the richedit. Any idea why?
EDIT: From comment posted:
Range is a RANGEFORMAT, and is assigned values like this:
Range.hdc := aCanvas.Handle;
Range.hdcTarget := aCanvas.Handle;
LogX := GetDeviceCaps(Range.hdc, LOGPIXELSX);
LogY := GetDeviceCaps(Range.hdc, LOGPIXELSY);
Range.rc.Left := x * 1440 div LogX;
Range.rc.Right := (x+re.ClientWidth) * 1440 div LogX; // (1440=twips/inch)
Range.rc.Top := y * 1440 div LogY;
Range.rc.Bottom := 5000 * 1440 div LogY; // Some bigish number
Range.rcPage := Range.rc;
Range.chrg.cpMin := 0;
Range.chrg.cpMax := -1;
What I've found is that a solution to this is that you can set the background of individual characters with the code (before adding the text to the richedit) ...
var
Format: CHARFORMAT2;
begin
...
myrichedit.SelStart:=myrichedit.GetTextLen;
FillChar(Format, SizeOf(Format), 0);
with Format do begin
cbSize := SizeOf(Format);
dwMask := CFM_BACKCOLOR;
crBackColor := charbackgroundcolor;
myrichedit.Perform(EM_SETCHARFORMAT, SCF_SELECTION, Longint(#Format));
end;
myrichedit.SetText:='Hello';
... but to get a background color for the whole block of text then do this to draw the text ...
var
size : Tsize;
Range: TFormatRange;
Rect: TRect;
LogX, LogY : Integer;
bm : tbitmap;
aCanvas : TCanvas;
ExStyle: DWord;
begin
aCanvas:=Printer.Canvas;
Range.hdc := aCanvas.Handle;
Range.hdcTarget := aCanvas.Handle;
LogX := GetDeviceCaps(Range.hdc, LOGPIXELSX);
LogY := GetDeviceCaps(Range.hdc, LOGPIXELSY);
Range.rc.Left := x * 1440 div LogX;
Range.rc.Right := (x+myrichedit.ClientWidth) * 1440 div LogX; // (1440=twips/inch)
Range.rc.Top := y * 1440 div LogY;
Range.rc.Bottom := 5000 * 1440 div LogY; // Some bigish number
Range.rcPage := Range.rc;
Range.chrg.cpMin := 0;
Range.chrg.cpMax := -1;
myrichedit.Perform(EM_FORMATRANGE, 0, Longint(#Range)); // Measure the formatted text
rect:=Range.rc;
rect.Left:=Range.rc.Left * LogX div 1440;
rect.Top:=Range.rc.Top * LogY div 1440;
rect.Right:=Range.rc.Right * LogX div 1440;
rect.Bottom:=Range.rc.Bottom * LogY div 1440;
acanvas.Brush.Color:=myblockcolor;
acanvas.FillRect(rect); // Fill the background rectangle
ExStyle := GetWindowLong(re.Handle, GWL_EXSTYLE); // Draw richedit transparently over coloured area
ExStyle := ExStyle or WS_EX_TRANSPARENT;
SetWindowLong(re.Handle, GWL_EXSTYLE, ExStyle);
myrichedit.Perform(EM_FORMATRANGE, 1, Longint(#Range));
end;

FastReport - How to displaying data in the form of table?

How can i display data in the form of table in the FastReport ?
Edit
I mean ,I want to create a report like this : (with tabular format).
The easiest way to use FR wizard
from FR File menu > new > Standard report wizard
when you reach the "Layout" page, choose tabular from layout then OK
I think you need to build the grid yourself. Here's a bit of code that builds a grid layout to get you started. You will need to adjust the column widths and add the formatting code (memo.frame) to get your desired look.
procedure CreateHeader(frxDataset: TfrxDBDataSet; Page: TfrxReportPage);
var
i: Integer;
X, Y, ThisWidth: Extended;
HeaderMemo: TfrxCustomMemoView;
Column: TcxGridDBColumn;
begin
Band := TfrxPageHeader.Create(Page);
Band.CreateUniqueName;
Band.SetBounds(0, 0, 0, fr01cm * 7);
Band.Height := edtHeightHeader.Value;
HeaderMemo := CreateMemo(Band);
HeaderMemo.SetBounds(0, 0, PageWidth, 0);
// Set memo style
// Or just add a frame HeaderMemo.Frame....
HeaderMemo.Style := 'Header line';
X := 0;
Y := 0;
Memo := CreateMemo(Band);
Memo.SetBounds(0, Y, X, fr01cm * 6);
Memo.Height := Band.Height - 1;
for i := 0 to pred(frxDataset.Fields.Count) do
begin
ThisWidth := 100;
Memo := CreateMemo(Band);
Memo.SetBounds(X, Y, ThisWidth, fr01cm * 6);
Memo.Text := frxDataset.Fields[i].FieldName;
// Set memo style
// Or just add a frame HeaderMemo.Frame....
Memo.Style := 'Header';
Memo.Height := Band.Height - 1;
X := X + ThisWidth;
end;
HeaderMemo.Height := Band.Height;
end;
procedure CreateFastReportDataBand(frxDataset: TfrxDBDataSet; Page: TfrxReportPage);
var
i: Integer;
X, Y, ThisWidth: Extended;
begin
Band := TfrxMasterData.Create(Page);
Band.CreateUniqueName;
Band.SetBounds(0, CurY, 0, 0);
Band.Height := edtHeightData.Value;
TfrxMasterData(Band).frxDataset := frxDataset;
X := 0;
Y := 0;
for i := 0 to pred(frxDataset.Fields.Count) do
begin
ThisWidth := 100;
Memo := CreateMemo(Band);
Memo.SetBounds(X, Y, ThisWidth, fr01cm * 5);
Memo.Dataset := frxDataset;
Memo.DataField := frxDataset.Fields[i].FieldName;
// Set memo style
// Or just add a frame HeaderMemo.Frame....
Memo.Style := 'Data';
Memo.Height := Band.Height - 1;
X := X + ThisWidth;
end;
end;
It should work ok, but I've not had a chance to test since decoupling it from my application.
It will be possible using Framing Property of Memos.

Custom MessageBox icon background white

I'm using a class for custom messageboxes. But my problem is that, icon background is always white. Code below displays the icons. Can somebody tell me what is wrong in this code? I want icon background to be transparent.
try
if not custb then
case i of
MB_ICONINFORMATION:ico.Handle := LoadIcon( 0, IDI_INFORMATION);
MB_ICONEXCLAMATION:ico.Handle := LoadIcon( 0, IDI_EXCLAMATION);
MB_ICONQUESTION:ico.Handle := LoadIcon( 0, IDI_QUESTION);
MB_ICONERROR:ico.Handle := LoadIcon( 0, IDI_ERROR);
end;
with timage.Create( frm) do
begin
parent := frm;
transparent := True;
if custb then
begin
height := glyph.Height;
width := Glyph.Width;
end
else
begin
height := ico.Height;
width := ico.Width;
end;
ih := height;
top := Height div 2 + 2;
it := Top;
left := Width div 2 + 2;
il := Left + width + width div 2;
if width <= 16 then
begin
il := il + 16;
left := left + 8;
end;
if height <= 16 then
begin
it := it + 8;
top := top + 8;
end;
if custb then picture := Glyph else canvas.Draw( 0, 0, ico);
end;
finally
end;
if not custb then ico.Free;
end
Best wishes,
evilone
My code to do this very thing looks like this:
function StandardDialogIcon(DlgType: TMsgDlgType): PChar;
begin
case DlgType of
mtWarning:
Result := IDI_WARNING;
mtError:
Result := IDI_ERROR;
mtInformation:
Result := IDI_INFORMATION;
mtConfirmation:
Result := IDI_QUESTION;
else
Result := nil;
end;
end;
...
Image.Picture.Icon.Handle := LoadIcon(0, StandardDialogIcon(DlgType));
There's no need to set any properties on Image, you can simply ignore Transparent.
Extract from online help for TImage.Transparent:
Setting Transparent sets the
Transparent property of the Picture.
Note: Transparent has no effect
unless the Picture property specifies
a TBitmap object.
This means two things for you:
only set transparent property after the picture has been assigned
Use TBitmap for your image and assign thtat to the picture property.
Have a look at the following link, that describes a function that converts an icon to a bitmap: Delph-Library: Convert icon to bitmap.
Excerpt:
// Konvertiert Ico zu Bitmap
procedure IcoToBmpA(Ico: TIcon; Bmp: TBitmap; SmallIcon: Boolean);
var
WH: Byte; // Width and Height
begin
with Bmp do begin
Canvas.Brush.Color := clFuchsia;
TransparentColor := clFuchsia;
Width := 32; Height := 32;
Canvas.Draw(0, 0, Ico);
if SmallIcon then WH := 16 else WH := 32;
Canvas.StretchDraw(Rect(0, 0, WH, WH), Bmp);
Width := WH; Height := WH;
Transparent := True;
end;
end;

Resources