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.
Related
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;
How can I replace color on TCanvas on Delphi XE2? The following code works incredibly slow:
for y := ARect.Top to ARect.Top + ARect.Height - 1 do
for x := ARect.Left to ARect.Left + ARect.Width - 1 do
if Canvas.Pixels[x, y] = FixedColor then
Canvas.Pixels[x, y] := Canvas.Pixels[ARect.Left, ARect.Top];
Here are two function (with and without tolerance) to replace the color:
Bonus:
Code to test the functions also provided. Load your image in a TImage control, then use the MouseUp event to change the color under mouse.
procedure ReplaceColor(BMP: TBitmap; OldColor, NewColor: TColor);
VAR
x, y: Integer;
R,G,B: Byte;
R_,G_,B_: Byte;
aPixel: PRGBTriple;
begin
R:= GetRValue(OldColor);
G:= GetGValue(OldColor);
B:= GetBValue(OldColor);
R_:= GetRValue(NewColor);
G_:= GetGValue(NewColor);
B_:= GetBValue(NewColor);
BMP.PixelFormat := pf24bit;
for y := 0 to BMP.Height - 1 do
for x := 0 to BMP.Width - 1 do
begin
aPixel := BMP.ScanLine[y];
Inc(aPixel, x);
if (aPixel^.rgbtRed = R)
AND (aPixel^.rgbtGreen = G)
AND (aPixel^.rgbtBlue = B) then
begin
aPixel^.rgbtRed := R_;
aPixel^.rgbtGreen := G_;
aPixel^.rgbtBlue := B_;
end;
end;
end;
procedure ReplaceColor(BMP: TBitmap; OldColor, NewColor: TColor; ToleranceR, ToleranceG, ToleranceB: Byte);
VAR
x, y: Integer;
R,G,B: Byte;
R_,G_,B_: Byte;
aPixel: PRGBTriple;
begin
R:= GetRValue(OldColor);
G:= GetGValue(OldColor);
B:= GetBValue(OldColor);
R_:= GetRValue(NewColor);
G_:= GetGValue(NewColor);
B_:= GetBValue(NewColor);
BMP.PixelFormat := pf24bit;
for y := 0 to BMP.Height - 1 do
for x := 0 to BMP.Width - 1 do
begin
aPixel := BMP.ScanLine[y];
Inc(aPixel, x);
if (abs(aPixel^.rgbtRed - R)< ToleranceR)
AND (abs(aPixel^.rgbtGreen- G)< ToleranceG)
AND (abs(aPixel^.rgbtBlue - B)< ToleranceB) then
begin
aPixel^.rgbtRed := R_;
aPixel^.rgbtGreen := G_;
aPixel^.rgbtBlue := B_;
end;
end;
end;
procedure TfrmTester.imgOnMouseUp(Sender: TObject; Shift: TShiftState; X, Y: Integer);
VAR
PixelClr: TColor;
BMP: TBitmap;
begin
// Collect the new color, under mouse pointer
PixelClr:= imgReplaceOrig.Picture.Bitmap.Canvas.Pixels[x, y];
if PixelClr< 0 then EXIT;
Label1.Caption := 'x'+IntToStr(X)+':y='
+ IntToStr(Y)
+' r'+ IntToStr(GetRValue(Pixel))
+', g'+ IntToStr(GetGValue(Pixel))
+', b'+ IntToStr(GetBValue(Pixel));
BMP:= TBitmap.Create;
BMP.Assign(imgReplaceOrig.Picture.Bitmap);
// Replace the color
cGraphUtil.ReplaceColor(BMP, PixelClr, clBlue, 44, 44, 44);
imgReplace.Picture.Assign(BMP);
FreeAndNil(BMP);
end;
var
aBitmap: TBitmap;
x, y: Integer;
aPixel: PRGBTriple;
...
aBitmap := TBitmap.Create;
try
aBitmap.PixelFormat := pf24bit;
aBitmap.Height := ARect.Height;
aBitmap.Width := ARect.Width;
aBitmap.Canvas.CopyRect(TRect.Create(0, 0, aBitmap.Width, aBitmap.Height), Canvas, ARect);
for y := 0 to aBitmap.Height - 1 do
for x := 0 to aBitmap.Width - 1 do
begin
aPixel := aBitmap.ScanLine[y];
Inc(aPixel, x);
if (aPixel^.rgbtRed = GetRValue(FixedColor)) and (aPixel^.rgbtGreen = GetGValue(FixedColor)) and (aPixel^.rgbtBlue = GetBValue(FixedColor)) then
aPixel^ := PRGBTriple(aBitmap.ScanLine[y])^;
end;
Canvas.Draw(ARect.Left, ARect.Top, aBitmap);
finally
aBitmap.Free;
end;
Using Delphi 2010 and a TStringGrid component, I currently display five filds from a database query.
Here is a simplied example of what i am doing
//set up the grid
procedure TGriddata.FormCreate(Sender: TObject);
begin
grdMain.Rows[0].commatext:='"One","Two","Three","Four","Five"';
grdMain.ColWidths[0]:= 50;
grdMain.ColWidths[1]:= 175;
grdMain.ColWidths[2]:= 175;
grdMain.ColWidths[3]:= 100;
grdMain.ColWidths[4]:= 300;
end;
//display the data in the grid
//note, I am not showing my creation, execution, or destroy of the query
procedure TGriddata.load;
begin
...
grdMain.Cells[0,row]:= FieldByName('one').AsString;
grdMain.Cells[1,row]:= FieldByName('two').AsString;
grdMain.Cells[2,row]:= FieldByName('three').AsString;
grdMain.Cells[3,row]:= FieldByName('four').AsString;
//draw progress bar here
...
end;
One of the columns ("Five") needs to display a navy blue horizontal bar in the col. It should also diplay some text centered in the bar. I have no expereince using the custom drawing. What properties do i set to only custom draw the one column and use the default drawing for the other columns?
Add the text to the cells like you normally would. But you have to draw those bars in the OnDrawCell event. Leave DefaultDrawing as is (True by default), and erase the already drawn cell text in those columns by filling it in advance:
procedure TForm1.grdMainDrawCell(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);
var
Progress: Single;
R: TRect;
Txt: String;
begin
with TStringGrid(Sender) do
if (ACol = 4) and (ARow >= FixedRows) then
begin
Progress := StrToFloatDef(Cells[ACol, ARow], 0) / 100;
Canvas.FillRect(Rect);
R := Rect;
R.Right := R.Left + Trunc((R.Right - R.Left) * Progress);
Canvas.Brush.Color := clNavy;
Canvas.Rectangle(R);
Txt := Cells[ACol, ARow] + '%';
Canvas.Brush.Style := bsClear;
IntersectClipRect(Canvas.Handle, R.Left, R.Top, R.Right, R.Bottom);
Canvas.Font.Color := clHighlightText;
DrawText(Canvas.Handle, PChar(Txt), -1, Rect, DT_SINGLELINE or
DT_CENTER or DT_VCENTER or DT_END_ELLIPSIS or DT_NOPREFIX);
SelectClipRgn(Canvas.Handle, 0);
ExcludeClipRect(Canvas.Handle, R.Left, R.Top, R.Right, R.Bottom);
Canvas.Font.Color := clWindowText;
DrawText(Canvas.Handle, PChar(Txt), -1, Rect, DT_SINGLELINE or
DT_CENTER or DT_VCENTER or DT_END_ELLIPSIS or DT_NOPREFIX);
SelectClipRgn(Canvas.Handle, 0);
end;
end;
For more options, you might consider this DrawStatus routine.
Here you can view a sample (Draw percentage in a cell in a Grid), to draw a bar in a cell of a TStringGrid.
The explanation is in spanish, but you can download the code, that is very simple.
Also you can use authomatic translation on right of page.
procedure TFormDrawCell.DBGrid1DrawColumnCell(Sender: TObject;
const Rect: TRect; DataCol: Integer; Column: TColumn;
State: TGridDrawState);
const
STR_EMPTY = '';
CHAR_PERCENT = '%';
SPACE_TO_CENTER_CELLTEXT = 0;
var
fValue: Integer;
ActualPenColor, ActualBrushColor: TColor;
EmptyDS: Boolean;
DrawRect: TRect;
fWidth1, fLeft2: Integer;
StrValue: string;
begin
if not (Column.FieldName = 'Precent') then
Exit;
if not (cbdraw.Checked) then
Exit;
EmptyDS := ((TDBGrid(Sender).DataSource.DataSet.EoF) and
(TDBGrid(Sender).DataSource.DataSet.Bof));
if (Column.Field.IsNull) then begin
fValue := -1;
StrValue := STR_EMPTY;
end
else begin
fValue := Column.Field.AsInteger;
StrValue := IntToStr(fValue) + CHAR_PERCENT;
end;
DrawRect := Rect;
InflateRect(DrawRect, -1, -1);
fWidth1 := (((DrawRect.Right - DrawRect.Left) * fValue) DIV 100);
ActualPenColor := TDBGrid(Sender).Canvas.Pen.Color;
ActualBrushColor := TDBGrid(Sender).Canvas.Brush.Color;
TDBGrid(Sender).Canvas.Pen.Color := clHighlight;
TDBGrid(Sender).Canvas.Brush.Color := clWhite;
TDBGrid(Sender).Canvas.Rectangle(DrawRect);
if (fValue > 0) then begin
TDBGrid(Sender).Canvas.Pen.Color := clSkyBlue;
TDBGrid(Sender).Canvas.Brush.Color := clSkyBlue;
DrawRect.Right := DrawRect.Left + fWidth1;
InflateRect(DrawRect, -1, -1);
TDBGrid(Sender).Canvas.Rectangle(DrawRect);
end;
if not (EmptyDS) then begin
DrawRect := Rect;
InflateRect(DrawRect, -2, -2);
TDBGrid(Sender).Canvas.Brush.Style := bsClear;
fLeft2 := DrawRect.Left + (DrawRect.Right - DrawRect.Left) shr 1 -
(TDBGrid(Sender).Canvas.TextWidth(StrValue) shr 1);
TDBGrid(Sender).Canvas.TextRect(DrawRect, fLeft2,
DrawRect.Top + SPACE_TO_CENTER_CELLTEXT, StrValue);
end;
TDBGrid(Sender).Canvas.Pen.Color := ActualPenColor;
TDBGrid(Sender).Canvas.Brush.Color := ActualBrushColor;
end;
Regards.
I'm using the code posted in this link TSplitter enhanced with grab bar , to draw a grab bar in a splitter control,
procedure TSplitter.Paint;
var
R: TRect;
X, Y: integer;
DX, DY: integer;
i: integer;
Brush: TBitmap;
begin
R := ClientRect;
Canvas.Brush.Color := Color;
Canvas.FillRect(ClientRect);
X := (R.Left+R.Right) div 2;
Y := (R.Top+R.Bottom) div 2;
if (Align in [alLeft, alRight]) then
begin
DX := 0;
DY := 3;
end else
begin
DX := 3;
DY := 0;
end;
dec(X, DX*2);
dec(Y, DY*2);
Brush := TBitmap.Create;
try
Brush.SetSize(2, 2);
Brush.Canvas.Brush.Color := clBtnHighlight;
Brush.Canvas.FillRect(Rect(0,0,1,1));
Brush.Canvas.Pixels[0, 0] := clBtnShadow;
for i := 0 to 4 do
begin
Canvas.Draw(X, Y, Brush);
inc(X, DX);
inc(Y, DY);
end;
finally
Brush.Free;
end;
end;
the code works nicely but when I enabled the vcl styles, the colors used to draw the the splitter and the grab bar doesn´t fit the used by the vcl styles.
How I can draw the TSplitter using the Vcl style colors of the current theme?
The system color constants which uses the code (clBtnFace, clBtnHighlight, clBtnShadow) not store the vcl styles colors, you must use the StyleServices.GetSystemColor function to translate these to the vcl styles colors.
procedure TSplitter.Paint;
var
R: TRect;
X, Y: integer;
DX, DY: integer;
i: integer;
Brush: TBitmap;
begin
R := ClientRect;
if TStyleManager.IsCustomStyleActive then
Canvas.Brush.Color := StyleServices.GetSystemColor(clBtnFace)
else
Canvas.Brush.Color := Color;
Canvas.FillRect(ClientRect);
X := (R.Left+R.Right) div 2;
Y := (R.Top+R.Bottom) div 2;
if (Align in [alLeft, alRight]) then
begin
DX := 0;
DY := 3;
end else
begin
DX := 3;
DY := 0;
end;
dec(X, DX*2);
dec(Y, DY*2);
Brush := TBitmap.Create;
try
Brush.SetSize(2, 2);
if TStyleManager.IsCustomStyleActive then
Brush.Canvas.Brush.Color := StyleServices.GetSystemColor(clBtnHighlight)
else
Brush.Canvas.Brush.Color := clBtnHighlight;
Brush.Canvas.FillRect(Rect(0, 0, Brush.Height, Brush.Width));
if TStyleManager.IsCustomStyleActive then
Brush.Canvas.Pixels[0, 0] := StyleServices.GetSystemColor(clBtnShadow)
else
Brush.Canvas.Pixels[0, 0] := clBtnShadow;
for i := 0 to 4 do
begin
Canvas.Draw(X, Y, Brush);
inc(X, DX);
inc(Y, DY);
end;
finally
Brush.Free;
end;
end;
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.