3

私は Delphi7 を使用しており、区切り項目を含む ComboBox が必要です (ポップアップ メニューのように)。

私はこれが Mozilla Sunbird で美しく実装されているのを見てきました (私は知っています、それは Delphi ではありません...) 次の方法:

  1. 区切り項目は、項目の中央に描かれたシンプルな灰色の線です

  2. マウスでセパレーターにカーソルを合わせると、選択範囲が表示されません

  3. ユーザーがセパレーターをクリックすると、それも選択されず、コンボボックスも閉じません。

No. 1 は DrawItem を使用して実装できます。No. 2 がなくても生きていける。

No.3 でお願いします。CBN_CLOSEUP メッセージを閉じた直後にコンボボックスに送信されることがわかりました。

ウィンドウ プロシージャをフックし、特定のコンボボックスに CBN_CLOSEUP が送信された場合に対処することを考えました。しかし、これが最善の解決策なのか、それとも他のよりエレガントな方法があるのか​​ わかりません。

解決策が何であれ、WinXP/Vista/7 テーマを適切にサポートする標準の ComboBox が欲しいです。

ありがとう!


編集:動作するコンポーネントについては、このスレッドを参照してください:

この非常に小さな C++ コンポーネントを Delphi に変換するのを手伝ってくれませんか?

4

3 に答える 3

1

クリックできないセパレーター項目を作成してみました (この回答で説明されています)。いくつかの UI の不具合に遭遇しました。問題は、コンボ ボックスの動作にいくつかの側面があり、正確に正しく表示するのが難しい場合があることです。

  • リストがドロップダウンされている間、上矢印キーと下矢印キーを押すと、リスト内を移動します。
  • Enter を押すとドロップダウン リストが閉じ、現在の項目が選択されます。
  • Escape を押すとドロップダウン リストが閉じ、現在の項目 (現在の項目が上下矢印キーで選択されている場合) または最後に選択された項目が選択されます。
  • コンボ ボックスにフォーカスがある場合、上下の矢印キーを押すと、リストを表示せずに現在の選択が変更されます。
  • コンボ ボックスにフォーカスがある場合、何かを入力すると、入力内容に一致するコンボ ボックス項目が選択されます。
  • コンボ ボックスにフォーカスがある場合、F4 キーを押すとコンボ ボックス リストがドロップダウンし、キーボードまたはマウスで制御できます。

無効化された区切り項目がこれらのイベントのいずれにも応答しないようにする (スクリーン リーダーなど、見逃している可能性のあるその他のイベントはありますか?) と、エラーが発生するようです。

代わりに、私が使用しているアプローチは、セパレーターをアイテムの一部として描画することです。

  1. 可変高のオーナー描画コンボ ボックスを使用します。
  2. セパレーターが必要なアイテムの高さに 3 ピクセルを追加します。
  3. 区切りが必要な各項目の上部に水平線を引きます。

これを実現するための C++Builder コードを次に示します。それを Delphi に翻訳するのは簡単なはずです。

void __fastcall TForm1::ComboBox1DrawItem(TWinControl *Control,
    int Index, TRect &Rect, TOwnerDrawState State)
{
  bool draw_separator = NeedsSeparator(Index) && 
      !State.Contains(odComboBoxEdit);

  TCanvas *canvas = dynamic_cast<TCustomCombo*>(Control)->Canvas;
  canvas->FillRect(Rect);

  TRect text_rect = Rect;
  // Add space for separator if needed.
  if (draw_separator) {
    text_rect.Top += 3;
  }

  canvas->TextOut(text_rect.Left + 3,
      (text_rect.Top + text_rect.Bottom) / 2 - 
        canvas->TextHeight(ComboBox1->Items->Strings[Index]) / 2), 
      ComboBox1->Items->Strings[Index]);

  // Draw a separator line above the item if needed.
  if (draw_separator) {
    canvas->Pen->Color = canvas->Font->Color;
    canvas->MoveTo(Rect.Left, Rect.Top + 1);
    canvas->LineTo(Rect.Right, Rect.Top + 1);
  }
}

void __fastcall TForm1::ComboBox1MeasureItem(
    TWinControl * /* Control */, int Index, int &Height)
{
  Height = ComboBox1->ItemHeight;

  // Add space for the separator if needed.
  if (Index != -1 && NeedsSeparator(Index)) {
    Height += 3;
  }
}
于 2011-02-03T16:44:32.567 に答える
1

あなたが望むのは、所有者が描いたコンボボックスです。これを参照してください:http://delphi.about.com/od/vclusing/a/drawincombobox.htm

また、これはアイテムを不可解にすることを解決するようです: http://borland.newsgroups.archived.at/public.delphi.vcl.components.using.win32/200708/0708225320.html

私の知る限り、これを行う VCL の方法はないため、コンボボックスをサブクラス化する必要があります。これらの機能をカプセル化したコンポーネントを作成して、簡単に再利用できるようにするとよいでしょう。

神のご加護を

于 2010-12-04T20:31:06.710 に答える
0

コントロールの見栄えを良くしたい場合は、無料のSpTBXLibを使用してください。ポップアップメニューを線でポップアップするコンボスタイルのコンポーネントをサポートしています。

于 2010-12-04T17:54:45.867 に答える