I am having trouble with printing string grid. I use this code which works good except brush style. In application it works - where in cell is 'XXXX', it is overwritten with brush.style:= bsDiagCross; But when I try to print it, brush style is gone and on printed page is table with 'XXXX'. What´s wrong?
procedure frmPrint.Gridd(grd:TStringGrid; links, oben: Integer; scal:double; farbig:boolean);
var
x, y, li, ob, re, un, waag, senk, a, vSpalte, bSpalte, vZeile, bZeile: integer;
fix, grund, schrift, Barva: TColor;
r: TRect;
RR: TRect;
Sirka,Vyska, Velikost : integer;
function rech(i,j:integer):integer;
begin
result:=round(((i*j) / 72) * scal);
end;
begin
if printdialog.execute then // offnet den print dialog
begin
vZeile := 0;
vSpalte := 0;
Sirka := Printer.PageWidth;
Vyska := Printer.PageHeight;
bZeile := grd.rowcount - 1;
bSpalte := grd.colcount - 1;
if (scal > 0) and
(vZeile < grd.rowcount) and
(vSpalte < grd.colcount) then
begin
if farbig then
begin
fix := grd.fixedcolor;
grund := grd.color;
schrift := grd.font.color;
end
else
begin
fix := clsilver;
grund := clwhite;
schrift := clblack;
end;
waag := GetDeviceCaps(Printer.Handle, LogPixelSX);
senk := GetDeviceCaps(Printer.Handle, LogPixelSY);
links := rech(links, waag);
oben := rech(oben, senk);
li := GetDeviceCaps(Printer.Handle, PhysicalOffsetX) + 1 + links;
a := rech(3, waag);
with Printer do
begin
Title := 'report';
Orientation := poLandscape; //poLandscape;
BeginDoc;
if grd.gridlinewidth > 0 then
begin
Canvas.Pen.color := $333333;
Canvas.Pen.width := 1;
Canvas.Pen.Style := psSolid
end
else
Canvas.Pen.Style := psClear;
Canvas.Font := Grd.Font;
Canvas.Font.Color := Schrift;
Canvas.Font.Size := round((Grd.Font.Size / 0.72) * scal);
ob := GetDeviceCaps(Printer.Handle, PhysicalOffsetY) + 1 + oben;
for y := vZeile to bZeile do
begin
un := ob + rech(Grd.RowHeights[y]+1, senk);
//neue Seite + Kopf
if (un > Printer.PageHeight) and
(Printing) then
begin
EndDoc;
BeginDoc;
ob := GetDeviceCaps(Printer.Handle, PhysicalOffsetY) + 1 + oben;
un := ob + rech(Grd.RowHeights[y]+1, senk);
for x := vSpalte to bSpalte do
begin
Canvas.Brush.Color := fix;
re := li + rech(Grd.ColWidths[x] + 1, waag);
Canvas.Rectangle(li, ob, re + 2, un + 2);
r := rect(li + a, ob + 1, re - a, un - 2);
DrawText(Canvas.Handle, PChar(Grd.Cells[x,0]), length(Grd.Cells[x,0]), r, DT_SINGLELINE or DT_VCENTER);
li := re;
end;
li := GetDeviceCaps(Printer.Handle, PhysicalOffsetX) + 1 + links;
ob := un;
end;
un := ob + rech(Grd.RowHeights[y]+1, senk);
for x := vSpalte to bSpalte do
begin
if (x < Grd.FixedCols) or
(y < Grd.FixedRows) then
Canvas.Brush.Color := fix
else
Canvas.Brush.Color := Grund;
re := li + rech(Grd.ColWidths[x]+ 1, waag);
Canvas.Rectangle(li, ob, re + 2, un + 2);
r := rect(li + a, ob + 1, re - a, un - 2);
DrawText(Canvas.Handle, PChar(Grd.Cells[x,y]), length(Grd.Cells[x,y]), r, DT_SINGLELINE or DT_VCENTER);
li := re;
end;
ob := un;
li := GetDeviceCaps(Printer.Handle, PhysicalOffsetX) + 1 + links;
end;
if Printing then
EndDoc;
end;
end;
end;
end;
procedure frmPrint.sgDrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect;
State: TGridDrawState);
var
sg : TStringGrid;
c : TCanvas;
begin
sg := TStringGrid( Sender );
c := sg.Canvas;
if // Zellen
( sg.Cells[ACol,ARow] = 'XXXX' )
then begin
c.Brush.Style := bsDiagCross;
c.FillRect(Rect);
// c.Brush.Color := clblack;
end;
sg.Canvas.Pen.Color := clblack;
// "Set the Style property to bsClear to eliminate flicker when the object
// repaints" (I don't know if this helps).
sg.Canvas.Brush.Style := bsClear;
// Draw a line from the cell's top-right to its bottom-right:
sg.Canvas.MoveTo(Rect.Right, Rect.Top);
sg.Canvas.LineTo(Rect.Right, Rect.Bottom);
// Make the horizontal line.
sg.Canvas.LineTo(Rect.Left, Rect.Bottom);
// The other vertical line.
sg.Canvas.LineTo(Rect.Left, Rect.Top);
zmeneno:= false;
end;
In the printing code (frmPrint.Gridd()) you are missing the check for 'XXXX' and corresponding setting of Brush.Style and call to FillRect() instead of the call to DrawText().
In frmPrint.Gridd() in the second for x loop change this line:
DrawText(Canvas.Handle, PChar(grd.Cells[x, y]), length(grd.Cells[x, y]), r,
DT_SINGLELINE or DT_VCENTER);
to (untested):
if grd.Cells[x, y] = 'XXXX' then
begin
Canvas.Brush.Style := bsDiagCross;
Canvas.FillRect(r);
Canvas.Brush.Style := bsClear;
end
else
begin
DrawText(Canvas.Handle, PChar(grd.Cells[x, y]), length(grd.Cells[x, y]), r,
DT_SINGLELINE or DT_VCENTER);
end;
If the header row also may have those 'XXXX' cells then do the corresponding change also in the first for x loop.
Tom, thank you very much for your help!!
Solution is to swap the brush block behind draw
This works perfectly:
...
DrawText(Canvas.Handle, PChar(Grd.Cells[x,y]), length(Grd.Cells[x,y]), r, DT_SINGLELINE or DT_VCENTER);
li := re;
if grd.Cells[x, y] = 'XXXX' then
begin
Canvas.Brush.Style := bsDiagCross;
Canvas.FillRect(r);
Canvas.Brush.Style := bsClear;
end;
Related
I use Delphi 6.0, and I have TPanel, that contains TVirtualStringTree, that contains many nodes (more, than 1 screen).
I need to save this panel (with all nodes) to the BMP as a picture.
I use this method to save panel:
procedure TfrmDidTreeTime.cmSaveGantClick(Sender: TObject);
var
bmp : tBitmap;
cnt : Integer;
Dc : HDC;
R : TRect;
begin
inherited;
DC := GetDC ( pnlChart.handle);
R := pnlChart.boundsRect;
bmp := tBitmap.create;
bmp.width := R.Right-R.Left;
bmp.Height := R.Bottom - R.Top;
Bitblt(bmp.canvas.handle,0,0,bmp.Width,bmp.height,dc,r.left,r.top,srccopy);
spdSaveGraph.DefaultExt := 'bmp';
spdSaveGraph.FileName := 'Gant.bmp';
spdSaveGraph.Filter := 'Bitmap Picture|*.bmp';
if spdSaveGraph.Execute then
bmp.saveToFile (spdSaveGraph.FileName);
bmp.free;
end;
But this method saves only nodes that shows on the screen, but I need to save all of nodes.
procedure TfrmDidTreeTime.cmSaveDidTreeTimeClick(Sender: TObject);
var
bmp_total: tBitmap;
bmp_current : tBitmap;
r: TRect;
dc: HDC;
date_start: TDateTime;
h: integer;
bmp_current_position: integer;
scroll_position_current: integer;
scroll_position_total: integer;
screen_count: integer;
begin
inherited;
date_start := dtpDateStart.Value;
dc := GetDC (tvDidTimeTree.handle);
r := tvDidTimeTree.boundsRect;
bmp_total := tBitmap.create;
bmp_total.width := r.Right - r.Left - sbxVertical.Width - 3;
h := r.Bottom - r.Top - tvDidTimeTree.Header.Height;
if h < 0 then
h := 0;
SendMessage(tvDidTimeTree.Handle, WM_VSCROLL, SB_BOTTOM, 0);
scroll_position_total := GetScrollPos(tvDidTimeTree.Handle, sb_Vert);
screen_count := round(scroll_position_total / h);
bmp_total.Height := h * (screen_count + 1);
bmp_current_position := 0;
SendMessage(tvDidTimeTree.Handle, WM_VSCROLL, SB_TOP, 0);
tvDidTimeTree.Repaint;
while (scroll_position_current < scroll_position_total) do
begin
r := tvDidTimeTree.boundsRect;
dc := GetDC (tvDidTimeTree.handle);
bmp_current := tBitmap.create;
bmp_current.width := r.Right - r.Left - sbxVertical.Width - 3;
bmp_current.Height := h - 5;
Bitblt(bmp_total.canvas.handle, 0, bmp_current_position, bmp_current.Width, bmp_current.height, dc, r.left, r.top, srccopy);
scroll_position_current := GetScrollPos(tvDidTimeTree.Handle, sb_Vert);
SendMessage(tvDidTimeTree.Handle, WM_VSCROLL, SB_PAGEDOWN, 0);
tvDidTimeTree.Repaint;
bmp_current_position := bmp_current_position + bmp_current.Height;
end;
spdSaveGraph.DefaultExt := 'bmp';
spdSaveGraph.FileName := DateToStr(date_start) + '—' + DateToStr(IncMonth(date_start, 1)) + '.bmp';
spdSaveGraph.Filter := 'Bitmap Picture|*.bmp';
if spdSaveGraph.Execute then
bmp_total.saveToFile (spdSaveGraph.FileName);
bmp_total.free;
end;
How to draw the icons to the listview from imagelist?
I'm using this code to change the selection color in my listview, but it doesn't have the icons from the imagelist.
procedure TForm2.ListView1DrawItem(Sender: TCustomListView;
Item: TListItem; Rect: TRect; State: TOwnerDrawState);
var
x, y, i, w, h: integer;
begin
with ListView1, Canvas do
begin
if odSelected in State then
begin
Brush.Color := clRed;
Pen.Color := clWhite;
end else
begin
Brush.Color := Color;
Pen.Color := Font.Color;
end;
Brush.Style := bsSolid;
FillRect(rect);
h := Rect.Bottom - Rect.Top + 1;
x := Rect.Left + 1;
y := Rect.Top + (h - TextHeight('Hg')) div 2;
TextOut(x, y, Item.Caption);
inc(x, Columns[0].Width);
for i := 0 to Item.Subitems.Count - 1 do begin
TextOut(x, y, Item.SubItems[i]);
w := Columns[i + 1].Width;
inc(x, w);
end;
end;
end;
You have to draw images yourself, too.
procedure DrawListViewItem(ListView: TListView; Item: TListItem; Rect: TRect;
State: TOwnerDrawState; SelectedBrushColor, SelectedFontColor, BrushColor, FontColor: TColor);
var
x, y, i, w, h, iw, ih: integer;
begin
with ListView do
begin
if odSelected in State then
begin
Canvas.Brush.Color := SelectedBrushColor;
Canvas.Font.Color := SelectedFontColor;
end else
begin
Canvas.Brush.Color := BrushColor;
Canvas.Font.Color := FontColor;
end;
Canvas.Brush.Style := bsSolid;
Canvas.FillRect(rect);
h := Rect.Bottom - Rect.Top + 1;
if Assigned(SmallImages) then
begin
iw := SmallImages.Width;
ih := SmallImages.Height;
x := Rect.Left + 1;
if Item.ImageIndex >= 0 then
SmallImages.Draw(Canvas, Rect.Left + x, Rect.Top +(h - ih) div 2, Item.ImageIndex);
x := x + iw + 2;
end
else
begin
iw := 0;
ih := 0;
x := Rect.Left + 1;
end;
y := Rect.Top + (h - Canvas.TextHeight('Hg')) div 2;
Canvas.TextOut(x, y, Item.Caption);
inc(x, Columns[0].Width - iw);
for i := 0 to Item.Subitems.Count - 1 do begin
Canvas.TextOut(x, y, Item.SubItems[i]);
w := Columns[i + 1].Width;
inc(x, w);
end;
end;
end;
procedure TForm1.ListView1DrawItem(Sender: TCustomListView; Item: TListItem; Rect: TRect; State: TOwnerDrawState);
begin
DrawListViewItem(ListView1, Item, Rect, State, clRed, clWhite, ListView1.Color, ListView1.Font.Color);
end;
I have moved drawing code into separate function. That makes it reusable and a bit cleaner. Using with directly inside form method can have unwanted side effects. Same goes for double with clause, so I used only one (although I tend to avoid with completely in my code).
I have noticed that you used Pen.Color, but I changed that to Font.Color, because setting Pen has no effect whatsoever in your code, and I assume that you actually wanted to change color of the text.
I draw list view items with OwnerDraw, but I have bugs: please resize a column -> you will have a horizontal bar, scroll it -> items are drawn on a visible area :(
Please help me to edit a code below. Thanks for your attention and help!!!
Added:
I checked, Rect.Right and Rect.Left increase/decrease while scrolling. E.g. we scroll 50 px right, Rect.Right will be Rect.Right+50, Rect.Left will be -50 (0-50)
A normal view:
Bugs:
procedure TDownloadFrame.DownloadListDrawItem(Sender: TCustomListView;
Item: TListItem; Rect: TRect; State: TOwnerDrawState);
var
i: integer;
x1, x2: integer;
R: TRect;
s: string;
const
DT_ALIGN: array [TAlignment] of integer = (DT_LEFT, DT_RIGHT, DT_CENTER);
begin
if odSelected in State then
begin
Sender.Canvas.Font.Color := clWhite;
Sender.Canvas.Brush.Color := $00FF8000;
end
else
begin
Sender.Canvas.Font.Color := clBlack;
Sender.Canvas.Brush.Color := clWhite;
end;
Sender.Canvas.Brush.Style := bsSolid;
Sender.Canvas.FillRect(Rect);
x1 := 0;
x2 := 0;
R := Rect;
Sender.Canvas.Brush.Style := bsClear;
MainForm.Icons_16x16.Draw(DownloadList.Canvas, 3, R.Top + (R.Bottom - R.Top - 16) div 2, 1, true);
for i := 0 to DownloadList.Columns.Count - 1 do
begin
Inc(x2, ListView_GetColumnWidth(DownloadList.Handle,
DownloadList.Columns[i].Index));
R.Left := x1;
R.Right := x2;
if i = 0 then
begin
s := Item.Caption;
R.Left := 16 + 6;
end
else
s := Item.SubItems[i - 1];
if i <> 3 then
DrawText(Sender.Canvas.Handle, s, length(s), R, DT_SINGLELINE or
DT_ALIGN[DownloadList.Columns[i].Alignment] or DT_VCENTER or
DT_END_ELLIPSIS);
x1 := x2;
end;
end;
Change:
1)
x1 := 0;
x2 := 0;
to
x1 := Rect.Left;
x2 := Rect.Left;
2)
MainForm.Icons_16x16.Draw(DownloadList.Canvas, 3, R.Top + (R.Bottom - R.Top - 16) div 2, 1, true);
to
MainForm.Icons_16x16.Draw(DownloadList.Canvas, R.Left+3, R.Top + (R.Bottom - R.Top - 16) div 2, ImgIndex, true);
3)
if i = 0 then
begin
s := Item.Caption;
R.Left := 16 + 6;
end
to
if i = 0 then
begin
s := Item.Caption;
R.Left := R.Left + 16 + 6;
end
i came across a bug in the VCL recently where if i draw on a ListItem with an imagelist, then the listview's canvas would no longer honor any font color, font size, or font face changes of Sender.Canvas.Font:
Sender.Canvas.Font.Color := clHighlightText;
Sender.Canvas.Font.Size := 14;
Sender.Canvas.Font.Name := 'Consolas';
...none would work. This would only stop working if i first drew on the canvas using:
imageList.Draw(Sender.Canvas, ....);
If i removed the imageList.Draw everything was fine.
i was forced to set the font and colors using GDI directly:
savedDC := SaveDC(Sender.Canvas.Handle);
try
SetTextColor(Sender.Canvas.Handle, clHighlightText); //don't use clWhite, use the correct color
newfont := TFont.Create;
try
newFont.Assign(Sender.Canvas.Font);
newFont.Name := 'Consolas';
newfont.Size := 14;
SelectObject(Sender.Canvas.Handle, newFont.Handle);
szText = 'Hello, world!';
TextOut(Sender.Canvas.Handle, 0, 0, PChar(szText), Length(szText));
finally
newFont.Free;
end;
finally
RestoreDC(Sender.Canvas.Handle, savedDC);
end;
Note: Any code is released into the public domain. No attribution required.
Enable Autosize of columns and enable OwnerDraw for a List View. Then add a code below from HERE:
procedure TForm1.ListView1DrawItem(Sender: TCustomListView; Item: TListItem;
Rect: TRect; State: TOwnerDrawState);
var
i: Integer;
x1, x2: integer;
r: TRect;
S: string;
const
DT_ALIGN: array[TAlignment] of integer = (DT_LEFT, DT_RIGHT, DT_CENTER);
begin
if SameText(Item.SubItems[1], 'done') then
begin
Sender.Canvas.Font.Color := clWhite;
Sender.Canvas.Brush.Color := clGreen;
end
else
if Odd(Item.Index) then
begin
Sender.Canvas.Font.Color := clBlack;
Sender.Canvas.Brush.Color := $F6F6F6;
end
else
begin
Sender.Canvas.Font.Color := clBlack;
Sender.Canvas.Brush.Color := clWhite;
end;
if odSelected in State then // NEW!
begin // NEW!
Sender.Canvas.Font.Color := clWhite; // NEW!
Sender.Canvas.Brush.Color := clNavy; // NEW!
end; // NEW!
Sender.Canvas.Brush.Style := bsSolid;
Sender.Canvas.FillRect(Rect);
x1 := 0;
x2 := 0;
r := Rect;
Sender.Canvas.Brush.Style := bsClear;
Sender.Canvas.Draw(3, r.Top + (r.Bottom - r.Top - bm.Height) div 2, bm);
for i := 0 to ListView1.Columns.Count - 1 do
begin
inc(x2, ListView1.Columns[i].Width);
r.Left := x1;
r.Right := x2;
if i = 0 then
begin
S := Item.Caption;
r.Left := bm.Width + 6;
end
else
S := Item.SubItems[i - 1];
DrawText(Sender.Canvas.Handle,
S,
length(S),
r,
DT_SINGLELINE or DT_ALIGN[ListView1.Columns[i].Alignment] or
DT_VCENTER or DT_END_ELLIPSIS);
x1 := x2;
end;
if odFocused in State then // NEW!
DrawFocusRect(Sender.Canvas.Handle, Rect); // NEW!
end;
Actively resize the penultimate column if it has autosize. It bill be bugs:
How to prevent these bugs?
Thanks!
The bug is in the TListColumn.GetWidthin 'comctrls.pas'. The VCL is retrieving a wrong column width while resizing columns when 'AutoSize' on the columns is set, hence you're drawing item text all over the columns.
I looked at the VCL code for a few minutes and couldn't figure out what's wrong, but setting the value in a getter is suspicious enough.
Anyway, for a workaround, instead of
inc(x2, ListView1.Columns[i].Width);
use this:
inc(x2, ListView_GetColumnWidth(ListView1.Handle, ListView1.Columns[i].Index));
I am looking to draw an opacity ellipse in CodeGear Delphi 2010.
I had tried to draw to an another bitmap,
I had set the bitmap transparent color(for background)
Call the ellipse method.
And in my image I draw the bitmap with opacity parameter(from overload). But it doesn't work.
I want something like this http://www.java2s.com/Tutorial/VBImages/WPF-UseOpacityMaskAndRadialGradientBrush.PNG
Does anybody know an working method?
It works for me:
procedure TForm1.Button1Click(Sender: TObject);
var
bm1, bm2: TBitmap;
begin
bm1 := TBitmap.Create;
bm1.LoadFromFile('C:\Users\Andreas Rejbrand\Pictures\portrait.bmp');
bm2 := TBitmap.Create;
bm2.SetSize(bm1.Width, bm1.Height);
bm2.Canvas.Brush.Color := clRed;
bm2.Canvas.Pen.Style := psClear;
bm2.Canvas.Ellipse(0, 0, bm2.Width, bm2.Height);
Canvas.Draw(100, 100, bm1);
Canvas.Draw(100, 100, bm2, 127);
end;
If you want more control, you can always do the processing manually:
procedure TForm1.Button1Click(Sender: TObject);
type
TRGB32Array = packed array[0..MaxInt div SizeOf(TRGBQuad)-1] of TRGBQuad;
PRGB32Array = ^TRGB32Array;
TScanline = TRGB32Array;
PScanline = ^TScanline;
var
bm1, bm2, bm3: TBitmap;
sc1, sc2, sc3: PScanline;
i: Integer;
j: Integer;
var
transp: real;
const
opacity = 0.29;
begin
transp := 1 - opacity;
bm1 := TBitmap.Create;
bm1.LoadFromFile('C:\Users\Andreas Rejbrand\Pictures\portrait.bmp');
bm2 := TBitmap.Create;
bm2.SetSize(bm1.Width, bm1.Height);
bm2.Canvas.Brush.Color := clRed;
bm2.Canvas.Pen.Style := psClear;
bm2.Canvas.Ellipse(0, 0, bm2.Width, bm2.Height);
bm3 := TBitmap.Create;
bm3.SetSize(bm1.Width, bm1.Height);
bm1.PixelFormat := pf32bit;
bm2.PixelFormat := pf32bit;
bm3.PixelFormat := pf32bit;
for i := 0 to bm1.Height - 1 do
begin
sc1 := bm1.ScanLine[i];
sc2 := bm2.ScanLine[i];
sc3 := bm3.ScanLine[i];
for j := 0 to bm1.Width - 1 do
with sc3^[j] do
begin
rgbBlue := round(transp*sc1^[j].rgbBlue + opacity*sc2^[j].rgbBlue);
rgbGreen := round(transp*sc1^[j].rgbGreen + opacity*sc2^[j].rgbGreen);
rgbRed := round(transp*sc1^[j].rgbRed + opacity*sc2^[j].rgbRed);
end;
end;
Canvas.Draw(100, 100, bm3);
end;
You can for example let the background image be at 100 % opacity outside the ellipse:
...
for i := 0 to bm1.Height - 1 do
begin
sc1 := bm1.ScanLine[i];
sc2 := bm2.ScanLine[i];
sc3 := bm3.ScanLine[i];
for j := 0 to bm1.Width - 1 do
if sc2^[j].rgbBlue + sc2^[j].rgbGreen + sc2^[j].rgbRed = 3*255 then
sc3^[j] := sc1^[j]
else
with sc3^[j] do
begin
rgbBlue := round(transp*sc1^[j].rgbBlue + opacity*sc2^[j].rgbBlue);
rgbGreen := round(transp*sc1^[j].rgbGreen + opacity*sc2^[j].rgbGreen);
rgbRed := round(transp*sc1^[j].rgbRed + opacity*sc2^[j].rgbRed);
end;
end;
...
Not to mention all other cool stuff you can do with pixmap manipulation:
...
for i := 0 to bm1.Height - 1 do
begin
sc1 := bm1.ScanLine[i];
sc2 := bm2.ScanLine[i];
sc3 := bm3.ScanLine[i];
for j := 0 to bm1.Width - 1 do
if sc2^[j].rgbBlue + sc2^[j].rgbGreen + sc2^[j].rgbRed = 3*255 then
sc3^[j] := sc1^[j]
else
with sc3^[j] do
begin
rgbBlue := round(sin(transp*sc1^[j].rgbBlue + opacity*sc2^[j].rgbBlue));
rgbGreen := round(transp*sc1^[j].rgbGreen + opacity*sc2^[j].rgbGreen);
rgbRed := round(transp*sc1^[j].rgbRed + opacity*sc2^[j].rgbRed);
end;
end;
...
If you really don't want to do it manually, I just figured out, you can draw the ellipse on a copy of the first bitmap, and then blend these two bitmaps:
procedure TForm1.Button1Click(Sender: TObject);
var
bm1, bm2: TBitmap;
begin
bm1 := TBitmap.Create;
bm1.LoadFromFile('C:\Users\Andreas Rejbrand\Pictures\portrait.bmp');
bm2 := TBitmap.Create;
bm2.LoadFromFile('C:\Users\Andreas Rejbrand\Pictures\portrait.bmp');
bm2.Canvas.Brush.Color := clRed;
bm2.Canvas.Pen.Style := psClear;
bm2.Canvas.Ellipse(0, 0, bm2.Width, bm2.Height);
Canvas.Draw(100, 100, bm1);
Canvas.Draw(100, 100, bm2, 127);
end;