ComboBox:每个项目上的按钮(从列表中删除项目)
ComboBox: a button on every item (to delete the item from list)
我需要在 ComboBox 的每个项目上添加一个按钮(也许是 TSpeedButton?)。单击该按钮时,相应的项目将从列表中删除。例如:
我在字符串网格中看到过关于 SpeedButtons 的类似讨论(此处:TStringGrid with SpeedButtons),但我不知道如何在 ComboBox 上实现所有这些内容。您能否给我一些建议或链接以进一步阅读该主题。
除了我同意的用户体验评论之外,问题的解决方案并不是那么难。
您可以通过将 Style
属性 设置为 csOwnerDrawFixed
,在 OnDrawItem
事件中自己绘制项目,并在 OnSelect
事件为例,如下:
unit Unit1;
interface
uses
Winapi.Windows, System.Classes, Vcl.Controls, Vcl.Forms, Vcl.StdCtrls,
Vcl.Imaging.PNGIMage;
type
TForm1 = class(TForm)
ComboBox1: TComboBox;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure ComboBox1DrawItem(Control: TWinControl; Index: Integer;
Rect: TRect; State: TOwnerDrawState);
procedure ComboBox1Select(Sender: TObject);
private
FDeleteGraphic: TPNGImage;
FDeleteRect: TRect;
end;
implementation
{$R *.dfm}
{ TForm1 }
procedure TForm1.ComboBox1DrawItem(Control: TWinControl; Index: Integer;
Rect: TRect; State: TOwnerDrawState);
begin
ComboBox1.Canvas.FillRect(Rect);
if Index >= 0 then
ComboBox1.Canvas.TextOut(Rect.Left + 2, Rect.Top, ComboBox1.Items[Index]);
if (odSelected in State) and not (odComboBoxEdit in State) then
begin
FDeleteRect := Rect;
FDeleteRect.Left := FDeleteRect.Right - FDeleteGraphic.Width;
ComboBox1.Canvas.Draw(FDeleteRect.Left, FDeleteRect.Top, FDeleteGraphic);
end;
end;
procedure TForm1.ComboBox1Select(Sender: TObject);
var
MousePos: TPoint;
begin
MousePos := ComboBox1.ScreenToClient(Mouse.CursorPos);
MousePos.Offset(0, -ComboBox1.Height);
if PtInRect(FDeleteRect, MousePos) then
begin
ComboBox1.Items.Delete(ComboBox1.ItemIndex);
ComboBox1.Invalidate;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
FDeleteGraphic := TPNGImage.Create;
FDeleteGraphic.LoadFromFile('H:\Icons\FamFam Common\Delete.png');
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
FDeleteGraphic.Free;
end;
end.
结果如下:
您可能想要(重新)存储之前的 ItemIndex
设置。根据您的意愿定制。
我需要在 ComboBox 的每个项目上添加一个按钮(也许是 TSpeedButton?)。单击该按钮时,相应的项目将从列表中删除。例如:
我在字符串网格中看到过关于 SpeedButtons 的类似讨论(此处:TStringGrid with SpeedButtons),但我不知道如何在 ComboBox 上实现所有这些内容。您能否给我一些建议或链接以进一步阅读该主题。
除了我同意的用户体验评论之外,问题的解决方案并不是那么难。
您可以通过将 Style
属性 设置为 csOwnerDrawFixed
,在 OnDrawItem
事件中自己绘制项目,并在 OnSelect
事件为例,如下:
unit Unit1;
interface
uses
Winapi.Windows, System.Classes, Vcl.Controls, Vcl.Forms, Vcl.StdCtrls,
Vcl.Imaging.PNGIMage;
type
TForm1 = class(TForm)
ComboBox1: TComboBox;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure ComboBox1DrawItem(Control: TWinControl; Index: Integer;
Rect: TRect; State: TOwnerDrawState);
procedure ComboBox1Select(Sender: TObject);
private
FDeleteGraphic: TPNGImage;
FDeleteRect: TRect;
end;
implementation
{$R *.dfm}
{ TForm1 }
procedure TForm1.ComboBox1DrawItem(Control: TWinControl; Index: Integer;
Rect: TRect; State: TOwnerDrawState);
begin
ComboBox1.Canvas.FillRect(Rect);
if Index >= 0 then
ComboBox1.Canvas.TextOut(Rect.Left + 2, Rect.Top, ComboBox1.Items[Index]);
if (odSelected in State) and not (odComboBoxEdit in State) then
begin
FDeleteRect := Rect;
FDeleteRect.Left := FDeleteRect.Right - FDeleteGraphic.Width;
ComboBox1.Canvas.Draw(FDeleteRect.Left, FDeleteRect.Top, FDeleteGraphic);
end;
end;
procedure TForm1.ComboBox1Select(Sender: TObject);
var
MousePos: TPoint;
begin
MousePos := ComboBox1.ScreenToClient(Mouse.CursorPos);
MousePos.Offset(0, -ComboBox1.Height);
if PtInRect(FDeleteRect, MousePos) then
begin
ComboBox1.Items.Delete(ComboBox1.ItemIndex);
ComboBox1.Invalidate;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
FDeleteGraphic := TPNGImage.Create;
FDeleteGraphic.LoadFromFile('H:\Icons\FamFam Common\Delete.png');
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
FDeleteGraphic.Free;
end;
end.
结果如下:
您可能想要(重新)存储之前的 ItemIndex
设置。根据您的意愿定制。