Delphi:有可能有一个带有禁用项目的组合框吗?

cro*_*don 10 delphi combobox

如何让TComboBox包含一些禁用的项目?我需要用户查看这些项目,但无法选择它们.

谢谢!

And*_*and 16

是的,这是怎么做的:

放下TComboBox表单,然后设置StylecsOwnerDrawFixed.然后添加事件处理程序

procedure TForm1.ComboBox1DrawItem(Control: TWinControl; Index: Integer;
  Rect: TRect; State: TOwnerDrawState);
const
  INDENT = 3;
begin
  with TComboBox(Control) do
  begin
    FillRect(Canvas.Handle, Rect, GetStockObject(WHITE_BRUSH));
    inc(Rect.Left, INDENT);
    if boolean(Items.Objects[Index]) then
      SetTextColor(Canvas.Handle, clBlack)
    else
      SetTextColor(Canvas.Handle, clGray);
    DrawText(Canvas.Handle,
      PChar(Items[Index]),
      length(Items[Index]),
      Rect,
      DT_SINGLELINE or DT_LEFT or DT_VCENTER or DT_END_ELLIPSIS)
  end;
end;
Run Code Online (Sandbox Code Playgroud)

procedure TForm1.ComboBox1CloseUp(Sender: TObject);
begin
  with TComboBox(Sender) do
    if (ItemIndex <> -1) and not boolean(Items.Objects[ItemIndex]) then
    begin
      beep;
      Perform(CB_SHOWDROPDOWN, integer(true), 0);
    end;
end;
Run Code Online (Sandbox Code Playgroud)

此外,在表单的接口部分中,在声明表单类之前,添加

TComboBox = class(StdCtrls.TComboBox)
protected
  procedure WndProc(var Message: TMessage); override;
end;
Run Code Online (Sandbox Code Playgroud)

并实现WndProcas

procedure TComboBox.WndProc(var Message: TMessage);

  function NextItemIsDisabled: boolean;
  begin
    result := (ItemIndex < Items.Count - 1) and
      not boolean(Items.Objects[ItemIndex + 1]);
  end;

  procedure SelectNextEnabledItem;
  var
    i: Integer;
  begin
    for i := ItemIndex + 1 to Items.Count - 1 do
      if boolean(Items.Objects[i]) then
      begin
        ItemIndex := i;
        Exit;
      end;
    beep;
  end;

  procedure KillMessages;
  var
    msg: TMsg;
  begin
    while PeekMessage(msg,
      Handle,
      WM_KEYFIRST,
      WM_KEYLAST,
      PM_REMOVE) do;
  end;

  function PrevItemIsDisabled: boolean;
  begin
    result := (ItemIndex > 0) and
      not boolean(Items.Objects[ItemIndex - 1]);
  end;

  procedure SelectPrevEnabledItem;
  var
    i: Integer;
  begin
    for i := ItemIndex - 1 downto 0 do
      if boolean(Items.Objects[i]) then
      begin
        ItemIndex := i;
        Exit;
      end;
    beep;
  end;

begin
  case Message.Msg of
    WM_KEYDOWN:
      case Message.WParam of
        VK_DOWN:
          if NextItemIsDisabled then
          begin
            SelectNextEnabledItem;
            KillMessages;
            Exit;
          end;
        VK_UP:
          if PrevItemIsDisabled then
          begin
            SelectPrevEnabledItem;
            KillMessages;
            Exit;
          end;
      end;
  end;
  inherited;
end;
Run Code Online (Sandbox Code Playgroud)

例如,要测试组合框,请编写

procedure TForm1.FormCreate(Sender: TObject);
begin
  ComboBox1.Items.AddObject('Alpha', TObject(true));
  ComboBox1.Items.AddObject('Beta', TObject(true));
  ComboBox1.Items.AddObject('Gamma', TObject(false));
  ComboBox1.Items.AddObject('Delta', TObject(true));
end;
Run Code Online (Sandbox Code Playgroud)

我想你的意思true,并false在这里-它只是意味着enabled.

  • 努力+1,安德烈亚斯,虽然如果我们一起工作并且你使用了这个(我的用户也会这样),我会开枪.<g>他们习惯于像组合框一样的组合框.我没有发布任何接近代码的内容; 我想如果有人想以这种方式规避标准,他们应该做一些工作来弄清楚它的编码. (6认同)

Ken*_*ite 6

这并不容易(这是一个坏主意,因为这不是组合框在Windows上的表现).

你必须自己绘制组合框.使用Items.Objects数组来存储项目是否已启用或禁用,并在绘制每个项目之前检查该数组以便适当地设置颜色.

您还需要处理OnChangeOnClick事件,并添加一种方法来跟踪最后选择的内容ItemIndex.在OnChange/OnClick,您断开事件处理程序,检查Objects[ItemIndex]值以查看是否允许选择,如果没有设置ItemIndex回到上次选择ItemIndex,然后重新启用事件处理程序.

  • 如果用户点击下拉组合框中明显禁用的项目会发生什么?该框将关闭,用户可能没有意识到它已恢复为上次选择的值.那令人困惑! (4认同)