11

特定の列のすべてのセルにDelphiのTCheckBox内部を配置したいと思います。TStringGridDelphiXEを使用しています。

4

3 に答える 3

29

有効になっている場合は、できれば視覚的なテーマを使用して、独自のチェックボックスを描画する必要があります。これは、その方法の簡単なスケッチです。

const
  Checked: array[1..4] of boolean = (false, true, false, true);

procedure TForm4.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
  Rect: TRect; State: TGridDrawState);
const
  PADDING = 4;
var
  h: HTHEME;
  s: TSize;
  r: TRect;
begin
  if (ACol = 2) and (ARow >= 1) then
  begin
    FillRect(StringGrid1.Canvas.Handle, Rect, GetStockObject(WHITE_BRUSH));
    s.cx := GetSystemMetrics(SM_CXMENUCHECK);
    s.cy := GetSystemMetrics(SM_CYMENUCHECK);
    if UseThemes then
    begin
      h := OpenThemeData(StringGrid1.Handle, 'BUTTON');
      if h <> 0 then
        try
          GetThemePartSize(h,
            StringGrid1.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,
            StringGrid1.Canvas.Handle,
            BP_CHECKBOX,
            IfThen(Checked[ARow], 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(StringGrid1.Canvas.Handle,
        r,
        DFC_BUTTON,
        IfThen(Checked[ARow], DFCS_CHECKED, DFCS_BUTTONCHECK));
    end;
    r := Classes.Rect(r.Right + PADDING, Rect.Top, Rect.Right, Rect.Bottom);
    DrawText(StringGrid1.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;
end;

もちろん、実際のシナリオでは、配列は定数ではないため、セルペイントイベント間でメトリックとテーマハンドルCheckedを保存することをお勧めします。しかし、原則はここにあります。sh

ここで欠けているのは、チェックボックスの状態を変更する機能です。OnClickハンドラーで状態を切り替えることをお勧めします。本当に真面目な場合は、マウスの動きに反応し、テーマが利用可能な場合はチェックボックスにマウスホバー効果を表示することもできます。

青みがかった編集:チェックボックスの状態を切り替えるには、この回答でメソッドの使用Invalidate方法を説明します。

于 2011-03-15T02:17:01.383 に答える
9

TCheckBox内に実際のコントロールを配置しようとしないでくださいTStringGrid。代わりに、Win32 API関数でグリッドのOnDrawCellイベントを使用してDrawFrameControl()、必要に応じて各セル内にチェックボックスコントロールの画像を描画します。OnClick/OnMouse...グリッドのプロパティでイベントを使用してObjects[][]、必要に応じて各セルのチェックされた状態を追跡できます。TStringGrid実際のコントロールをホストするように設計されていないため、これは管理がはるかに簡単です。

于 2011-03-15T01:20:30.790 に答える
3

チェックボックスをサポートする、 RomanMochalovによるExGridViewと呼ばれる仮想グリッドを使用します。

Unicodeなどに移植されたGridViewの私自身の変更されたフォークは、TGridViewの代わりにTExGridViewという名前で、チェックボックスのデモがあり、ここでは/ wpostma/exgridviewとしてbitbucketにあります。

ExGridViewコンポーネントのプロパティインスペクターにCheckboxプロパティがあり、これをtrueに設定する必要があります。次に、Columnのチェックボックスタイプがcheckboxまたはラジオボタンに設定されるようにColumnプロパティを設定する必要があります。次に、GetCheckStateイベントコールバックを実装する必要があります。bitbucketプロジェクトに含まれているデモを参照してください。

このコードの元のソースはここにありましたが、最近のバージョンではビルドできません。私のビットバケットバージョンは、Delphi 2007、2009、および2016年現在のすべてのバージョン(Delphi 10 Seattle)でテストされ、動作しています。

ここに画像の説明を入力してください

于 2011-03-15T02:39:13.873 に答える