zeichnen Sie ein Kontrollkästchen in ein TListView
Muss ich zeichnen Sie ein Kontrollkästchen in einer bestimmten Spalte in einerTListView
, so überprüfe ich diese Frage Wie kann ich setup TListView mit Checkboxen nur bestimmte Spalten?
und in der akzeptierten Antwort vorschlagen, verwenden Sie die beschriebene Methode in diesem eine andere Frage setzen einer Checkbox TStringGrid in Delphi?
, jetzt die Portierung von code für die Arbeit mit einem ListView-ich komme mit diesem :
procedure TForm15.ListView1CustomDrawSubItem(Sender: TCustomListView; Item: TListItem; SubItem: Integer; State: TCustomDrawState; var DefaultDraw: Boolean);
const
PADDING = 4;
var
h : HTHEME;
s : TSize;
r : TRect;
Rect : TRect;
i : Integer;
Dx : Integer;
begin
if (SubItem=1) then
begin
DefaultDraw:=True;
Rect :=Item.DisplayRect(drBounds);
Dx:=0;
for i := 0 to SubItem do
Inc(Dx,Sender.Column[i].Width);
Rect.Left :=Rect.Left+Dx;
Rect.Right :=Rect.Left+Sender.Column[SubItem+1].Width;
FillRect(Sender.Canvas.Handle, Rect, GetStockObject(WHITE_BRUSH));
s.cx := GetSystemMetrics(SM_CXMENUCHECK);
s.cy := GetSystemMetrics(SM_CYMENUCHECK);
if UseThemes then
begin
h := OpenThemeData(Sender.Handle, 'BUTTON');
if h <> 0 then
try
GetThemePartSize(h, Sender.Canvas.Handle, BP_CHECKBOX, CBS_CHECKEDNORMAL, nil, TS_DRAW, s);
r.Top := Rect.Top + (Rect.Bottom - Rect.Top - s.cy) div 2;
r.Bottom := r.Top + s.cy;
r.Left := Rect.Left + PADDING;
r.Right := r.Left + s.cx;
DrawThemeBackground(h, Sender.Canvas.Handle, BP_CHECKBOX, IfThen(CompareText(Item.SubItems[1],'True')=0, CBS_CHECKEDNORMAL, CBS_UNCHECKEDNORMAL), r, nil);
finally
CloseThemeData(h);
end;
end
else
begin
r.Top := Rect.Top + (Rect.Bottom - Rect.Top - s.cy) div 2;
r.Bottom := r.Top + s.cy;
r.Left := Rect.Left + PADDING;
r.Right := r.Left + s.cx;
DrawFrameControl(Sender.Canvas.Handle, r, DFC_BUTTON, IfThen(CompareText(Item.SubItems[1],'True')=0, DFCS_CHECKED, DFCS_BUTTONCHECK));
end;
//r := Classes.Rect(r.Right + PADDING, Rect.Top, Rect.Right, Rect.Bottom);
// DrawText(Sender.Canvas.Handle, StringGrid1.Cells[ACol, ARow], length(StringGrid1.Cells[ACol, ARow]), r, DT_SINGLELINE or DT_VCENTER or DT_LEFT or DT_END_ELLIPSIS);
end
else
DefaultDraw:=False;
end;
aber ich scheitere kläglich bei meinem Versuch, ziehen Sie eine checkbox -: (, kann mir jemand zeigen in die richtige Richtung zu ziehen, die checkbox in der Listenansicht, (der code nicht zeichnen jede checkbox in der Listenansicht).
Listview ist im vsReport-Modus und hatte 3 Spalten ich möchte das Kontrollkästchen in der Dritten Spalte. bitte nicht schlagen, die eine dritt-party-Komponenten, die ich verwenden möchten, die TlistView-Steuerelement.
UPDATE 1 : Dank der sertac recomendattion Einstellung der DefaultDraw
Wert nun die Checkboxen angezeigt werden, aber die anderen Spalten sieht awfull.
UPDATE 2 , nach der Andreas-Vorschläge die listview jetzt besser Aussehen, aber immernoch die black box;
procedure TForm15.ListView1CustomDrawSubItem(Sender: TCustomListView; Item: TListItem; SubItem: Integer; State: TCustomDrawState; var DefaultDraw: Boolean);
var
h : HTHEME;
s : TSize;
r : TRect;
Rect : TRect;
i : Integer;
Dx : Integer;
begin
if (SubItem=2) then
begin
DefaultDraw:=False;
Rect :=Item.DisplayRect(drBounds);
Dx:=0;
for i := 0 to SubItem-1 do
Inc(Dx,Sender.Column[i].Width);
Rect.Left :=Rect.Left+Dx;
Rect.Right :=Rect.Left+Sender.Column[SubItem].Width;
FillRect(Sender.Canvas.Handle, Rect, GetStockObject(WHITE_BRUSH));
s.cx := GetSystemMetrics(SM_CXMENUCHECK);
s.cy := GetSystemMetrics(SM_CYMENUCHECK);
Dx := (Sender.Column[SubItem].Width-GetSystemMetrics(SM_CXMENUCHECK)) div 2;
if UseThemes then
begin
h := OpenThemeData(Sender.Handle, 'BUTTON');
if h <> 0 then
try
GetThemePartSize(h, Sender.Canvas.Handle, BP_CHECKBOX, CBS_CHECKEDNORMAL, nil, TS_DRAW, s);
r.Top := Rect.Top + (Rect.Bottom - Rect.Top - s.cy) div 2;
r.Bottom := r.Top + s.cy;
r.Left := Rect.Left + Dx;
r.Right := r.Left + s.cx;
DrawThemeBackground(h, Sender.Canvas.Handle, BP_CHECKBOX, IfThen(CompareText(Item.SubItems[SubItem-1],'True')=0, CBS_CHECKEDNORMAL, CBS_UNCHECKEDNORMAL), r, nil);
finally
CloseThemeData(h);
end;
end
else
begin
r.Top := Rect.Top + (Rect.Bottom - Rect.Top - s.cy) div 2;
r.Bottom := r.Top + s.cy;
r.Left := Rect.Left + Dx;
r.Right := r.Left + s.cx;
DrawFrameControl(Sender.Canvas.Handle, r, DFC_BUTTON, IfThen(CompareText(Item.SubItems[SubItem-1],'True')=0, DFCS_CHECKED, DFCS_BUTTONCHECK));
end;
end;
end;
- Du bist nicht die Einstellung 'DefaultDraw' false', deine Boxen sind wohl vorbei-gezogen von der VCL.
- Dank Sertac jetzt habe ich ein Fortschritt.
- Meine zweite Antwort behebt alle Probleme.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Einen relativ einfachen Weg, um loszuwerden, dieses Problem ist das owner-draw-die komplette Element. Set
OwnerDraw := true
ist, entfernen Sie IhreOnCustomDrawSubItem
routine, und fügen SieEin Beispiel für die Verwendung http://privat.rejbrand.se/listbugs.png
Den code oben muss weiter testen, aber ist wohl in die richtige Richtung. Jetzt ist es sehr spät, und ich muss gehen.
Zunächst sollten Sie festlegen
DefaultDraw
zufalse
beim zeichnen der checkbox-Spalte undtrue
sonst, weilDefaultDraw
bedeutet, dass die VCL nicht die Zeichnung, und nicht Sie. Derzeit tun Sie das Gegenteil.Darüber hinaus, aus irgendeinem seltsamen Grund, die Regelung, berücksichtigt die erste sub-Element
SubItem = 1
, und die zweite sub-ElementSubItem = 2
. Daher sollten Sie testenif SubItem = 2 then
statt.[Natürlich, dies bedeutet, die änderungen
]
Die schwarze Rechtecke erscheinen, um einen Fehler irgendwo in der union der VCL und Win32-code.
Ohne komplett Umschalten auf OwnerDraw, fand ich das folgende einigermaßen akzeptabel:
Verwenden Sie die CustomDrawSubItem routine ziehen Ihre Etiketten mit "TextOut", zum Beispiel:
ListView1.Canvas.TextOut(2, y, 'Mein label');
Dieser verbirgt die black Box, und Sie können sehen Ihre Beschriftungen. Allerdings funktioniert die Selektion nicht über den text. Kleiner Preis zu zahlen, obwohl, meiner Meinung nach.