Delphi: Возможно ли иметь поле со списком с отключенными элементами? - PullRequest
10 голосов
/ 07 апреля 2011

Как я могу иметь TComboBox с некоторыми отключенными предметами? Мне нужно, чтобы пользователь увидел эти элементы, но не смог их выбрать.

Спасибо!

Ответы [ 3 ]

16 голосов
/ 07 апреля 2011

Да, и вот как это сделать:

Удалите TComboBox на вашей форме и установите Style на csOwnerDrawFixed.Затем добавьте обработчики событий

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;

и

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;

Кроме того, в разделе интерфейса вашей формы перед объявлением класса формы добавьте

TComboBox = class(StdCtrls.TComboBox)
protected
  procedure WndProc(var Message: TMessage); override;
end;

и реализуйте WndProc как

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;

Чтобы проверить поле со списком, напишите, например,

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;

Я думаю, вы понимаете значение true и false здесь - это просто означает enabled.

6 голосов
/ 07 апреля 2011

Это нелегко (и это плохая идея, так как это не то, как комбо-боксы ведут себя в Windows).

Вы должны были бы сами нарисовать этот комбо-бокс.Используйте массив Items.Objects для хранения информации о том, включен элемент или нет, и проверьте этот массив перед прорисовкой каждого элемента, чтобы правильно установить цвета.

Вам также необходимо обработать OnChange и OnClick событий, и добавьте способ отслеживания последних выбранных ItemIndexOnChange/OnClick вы отключаете обработчик событий, проверяете значение Objects[ItemIndex], чтобы увидеть, разрешен ли выбор, если нет, установите ItemIndex обратно на последний выбранный ItemIndex, а затем снова включите обработчик событий.

0 голосов
/ 14 сентября 2015

просто добавьте следующий код в KeyPress процедуру

procedure Tform1.Combobox1editKeyPress(Sender: TObject; var Key: Char);
begin
   Key:=#0;
end;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...