Einzelnen Beitrag anzeigen

I.A

Registriert seit: 14. Jan 2007
83 Beiträge
 
#1

Combobox u.a. in Striggrid positionieren

  Alt 30. Mai 2007, 14:47
Hallo,

will grad ne Komponente testen, bevor ich sie installiere. Es geht um ein Editierfeld in einer Tabelle, das von

aussen gesteuert, je nach Datentyp ein passendes Editfeld bereitstellt.

- Für Boolsche Typen ---> eine Checkbox
- Für Listenauswahl ---> eine ComboBox
- Für komplexere Daten ---> ein Editfeld mit Button (wie im Objektinspektor die Ellipsenschaltfläche)

- Für alle anderen Daten wird der Spezialeditor nicht verwendet oder stellt ein einfaches Editfeld bereit.

Nun erscheint aber der Editor (CheckBox, ComboBox, Edit mit Button) immer in der linken oberen Ecke, statt
in der aktuellen Zelle meiner Tabelle. Wo liegt mein Denkfehler. Oder hab ich nur was kleines aber sehr

wichtiges übersehen?

Welcher Editortyp bei einer realen Datenbank letztlich für das Datenfeld generiert wird, hängt natürlich von der Art meiner Daten ab.

Hier ist der Quelltext.

Delphi-Quellcode:
unit DataEdit;

interface

uses
  Windows, Messages, SysUtils, Classes, Controls, ExtCtrls,
  Buttons, StdCtrls, Grids;

type
  TDataEditorKind = (ekBtnEdit,ekCheckBox,ekComboBox);

  { TDataEdit }

  TDataEdit = class(TPanel)
  private
    { Private declarations }
    FButton: TSpeedButton;
    FEdit: TEdit;
    FCheckBox: TCheckBox;
    FComboBox: TComboBox;
    FEditorKind : TDataEditorKind;
    FOnClick: TNotifyEvent;
    FOnDblClick: TNotifyEvent;
    FTable: TStringGrid;
    function GetText: String;
    procedure SetEditorKind(value: TDataEditorKind);
    procedure SetTable(value: TStringGrid);
    procedure SetText(value: String);
  protected
    { Protected declarations }
  public
    { Public declarations }
    constructor Create(AOwner: TComponent);
    destructor Destroy;
    procedure Click;
    procedure DblClick;
    function focused: Boolean; override;
    function IsDesignmode: Boolean;
    procedure SetRect(Rec: TRect);

    property Edit: TEdit read FEdit;
    property CheckBox: TCheckBox read FCheckBox;
    property ComboBox: TComboBox read FComboBox;
  published
    { Published declarations }
    property EditorKind: TDataEditorKind read FEditorKind write SetEditorKind;
    property OnClick: TNotifyEvent read FOnClick write FOnClick;
    property OnDblClick: TNotifyEvent read FOnDblClick write FOnDblClick;
    property Table: TStringGrid read FTable write SetTable;
    property Text: String read GetText write SetText;
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Samples', [TDataEdit]);
end;

function TDataEdit.GetText: String;
begin
  Result := '';
  case FEditorKind of
   ekBtnEdit:
    begin
      if Assigned(FEdit) then Result := FEdit.Text;
    end;
   ekCheckBox:
    begin
      if Assigned(FCheckBox) then Result := FCheckBox.Caption;
    end;
   ekComboBox:
    begin
      if Assigned(FComboBox) then Result := FComboBox.Text;
    end;
  end;
end;

procedure TDataEdit.SetEditorKind(value: TDataEditorKind);
begin
  if FEditorKind <> value then FEditorKind := value;
  case value of
   ekBtnEdit:
    begin
      if FCheckBox <> nil then FreeAndNil(FCheckBox);
      if FComboBox <> nil then FreeAndNil(FComboBox);
      FEdit := TEdit.Create(self);
      FEdit.Parent := self;
      FButton := TSpeedButton.Create(self);
      FButton.Parent := self;
      FButton.Width := Height;
      FButton.Height := Height;
      FEdit.Width := Width - FButton.Width;
      FButton.Left := FEdit.Width + 1;
      FEdit.Top := 0;
      FButton.Top := 0;
    end;
   ekCheckBox:
    begin
      if FButton <> nil then FreeAndNil(FButton);
      if FEdit <> nil then FreeAndNil(FEdit);
      FCheckBox := TCheckBox.Create(self);
      FCheckBox.Parent := self;
      FCheckBox.Align := alClient;
      //FCheckBox.Height := Height;
      //FCheckBox.Width := Width;
    end;
   ekComboBox:
    begin
      if FButton <> nil then FreeAndNil(FButton);
      if FEdit <> nil then FreeAndNil(FEdit);
      FComboBox := TComboBox.Create(self);
      FComboBox.Parent := self;
      FComboBox.Align := alClient;
      //FComboBox.Height := Height;
      //FComboBox.Width := Width;
    end;
  end;
end;

procedure TDataEdit.SetRect(Rec: TRect);
var r: TRect;
begin
  case FEditorKind of
   ekBtnEdit:
    with FEdit do begin
      CopyRect(r, Rec); // rec => r (Eck-Koordinaten an Hilfsrechteck übergeben)
      // Umrechnung der Eck-Koordinaten des Hilfsrechtecks:
      r.BottomRight := Parent.ScreenToClient(FTable.ClientToScreen(r.BottomRight));
      r.TopLeft := Parent.ScreenToClient(FTable.ClientToScreen(r.TopLeft));
      // Positionierung der Combobox (Left, Top, Width und Height werden zugewiesen):
      SetBounds(r.Left, r.Top, r.Right-r.Left, r.Bottom-r.Top);
      BringToFront // Combobox in Vordergrund bringen
    end;
   ekCheckBox:
    with FCheckBox do begin
      CopyRect(r, Rec); // rec => r (Eck-Koordinaten an Hilfsrechteck übergeben)
      // Umrechnung der Eck-Koordinaten des Hilfsrechtecks:
      r.BottomRight := Parent.ScreenToClient(FTable.ClientToScreen(r.BottomRight));
      r.TopLeft := Parent.ScreenToClient(FTable.ClientToScreen(r.TopLeft));
      // Positionierung der Combobox (Left, Top, Width und Height werden zugewiesen):
      SetBounds(r.Left, r.Top, r.Right-r.Left, r.Bottom-r.Top);
      BringToFront // Combobox in Vordergrund bringen
    end;
   ekComboBox:
    with FComboBox do begin
      CopyRect(r, Rec); // rec => r (Eck-Koordinaten an Hilfsrechteck übergeben)
      // Umrechnung der Eck-Koordinaten des Hilfsrechtecks:
      r.BottomRight := Parent.ScreenToClient(FTable.ClientToScreen(r.BottomRight));
      r.TopLeft := Parent.ScreenToClient(FTable.ClientToScreen(r.TopLeft));
      // Positionierung der Combobox (Left, Top, Width und Height werden zugewiesen):
      SetBounds(r.Left, r.Top, r.Right-r.Left, r.Bottom-r.Top);
      BringToFront // Combobox in Vordergrund bringen
    end;
  end;
end;

procedure TDataEdit.SetTable(value: TStringGrid);
begin
  if FTable = nil then FTable := value else
  if FTable <> value then
  begin
    FreeandNil(FTable);
    FTable := value;
    Width := FTable.DefaultColWidth;
    Height := FTable.DefaultRowHeight;
  end;
end;

procedure TDataEdit.SetText(value: String);
begin
  case FEditorKind of
   ekBtnEdit:
    begin
      FEdit.Text := value;
    end;
   ekCheckBox:
    begin
      FCheckBox.Caption := value;
    end;
   ekComboBox:
    begin
      FComboBox.Text := value;
    end;
  end;
end;

constructor TDataEdit.Create(AOwner: TComponent);
var Grid: TStringGrid;
begin
  inherited Create(AOwner);
  //Grid := TStringGrid.Create(AOwner);
  //Grid.DefaultColWidth := 80;
  //Grid.DefaultColHeight := 20;
  //SetTable(Grid);
  //Height := Grid.DefautRowHeight;
  //Width := Grid.DefaultColWidth;
end;

destructor TDataEdit.Destroy;
begin
  if FButton <> nil then FreeAndNil(FButton);
  if FCheckBox <> nil then FreeAndNil(FCheckBox);
  if FComboBox <> nil then FreeAndNil(FComboBox);
  if FEdit <> nil then FreeAndNil(FEdit);
  inherited Destroy;
end;

procedure TDataEdit.Click;
begin
  case FEditorKind of
   ekBtnEdit:
    begin
      if Assigned(FEdit) then
      begin
        //inherited FEdit.Click;
        FEdit.OnClick := FOnClick;
      end;
      if Assigned(FOnClick) then FOnClick(FEdit);
    end;
   ekCheckBox:
    begin
      if Assigned(FCheckBox) then
      begin
        //inherited FCheckBox.Click;
        FCheckBox.OnClick := FOnClick;
      end;
      if Assigned(FOnClick) then FOnClick(FCheckBox);
    end;
   ekComboBox:
    begin
      if Assigned(FComboBox) then
      begin
        //inherited FComboBox.Click;
        FComboBox.OnClick := FOnClick;
      end;
      if Assigned(FOnClick) then FOnClick(FComboBox);
    end;
  end;
end;

procedure TDataEdit.DblClick;
begin
  case FEditorKind of
   ekBtnEdit:
    begin
      if Assigned(FEdit) then
      begin
        //inherited FEdit.DblClick;
        FEdit.OnDblClick := FOnDblClick;
      end;
      if Assigned(FOnDblClick) then FOnDblClick(FEdit);
    end;
   ekCheckBox:
    begin
      if Assigned(FCheckBox) then
      begin
        //inherited FCheckBox.DblClick;
        //FCheckBox.OnClick := FOnDblClick(FCheckBox);
      end;
      if Assigned(FOnDblClick) then FOnDblClick(FCheckBox);
    end;
   ekComboBox:
    begin
      if Assigned(FComboBox) then
      begin
        //inherited FComboBox.DblClick;
        FComboBox.OnDblClick := FOnDblClick;
      end;
      if Assigned(FOnDblClick) then FOnDblClick(FComboBox);
    end;
  end;
end;

function TDataEdit.focused: Boolean;
var HasFocus: Boolean;
begin
  HasFocus := inherited focused;
  Result := HasFocus;
  if HasFocus then
  case FEditorKind of
   ekBtnEdit:
    begin
      FEdit.SetFocus;
      Result := true;
    end;
   ekCheckBox:
    begin
      FCheckBox.SetFocus;
      Result := true;
    end;
   ekComboBox:
    begin
      FComboBox.SetFocus;
      Result := true;
    end;
  end;
end;

function TDataEdit.IsDesignmode: Boolean;
begin
  Result := csDesigning IN ComponentState;
end;

end.
Und hier noch mein Formular mit der Tabelle:

Delphi-Quellcode:
unit ValueEdit;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Grids, DataEdit;

type
  TForm1 = class(TForm)
    Grid: TStringGrid;
    procedure FormCreate(Sender: TObject);
    procedure GridDrawCell(Sender: TObject; ACol, ARow: Integer;
      Rect: TRect; State: TGridDrawState);
    procedure GridTopLeftChanged(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    procedure SetRect(Rec: TRect);
  end;

var
  Form1: TForm1;
  Editor: TDataEdit;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  Editor := TDataEdit.Create(self);
  Editor.Parent := Grid;
  Editor.EditorKind := ekComboBox;
  Editor.Table := Grid;
  Editor.Height := Grid.DefaultRowHeight;
  Editor.Width := Grid.DefaultColWidth;
  Grid.ColWidths[0] := Grid.DefaultRowHeight;
end;

procedure TForm1.GridDrawCell(Sender: TObject; ACol, ARow: Integer;
  Rect: TRect; State: TGridDrawState);
begin
if (ACol >= Grid.FixedCols) and (ARow >= Grid.FixedRows) and
      (gdFocused in State) then SetRect(Rect);
end;

procedure TForm1.GridTopLeftChanged(Sender: TObject);
begin
  with Grid do setRect(CellRect(Col,Row));
end;

procedure TForm1.SetRect(Rec: TRect);
var r: TRect;
begin
  case Editor.EditorKind of
   ekBtnEdit:
    with Editor do begin
      CopyRect(r, Rec); // rec => r (Eck-Koordinaten an Hilfsrechteck übergeben)
      // Umrechnung der Eck-Koordinaten des Hilfsrechtecks:
      r.BottomRight := Parent.ScreenToClient(Table.ClientToScreen(r.BottomRight));
      r.TopLeft := Parent.ScreenToClient(Table.ClientToScreen(r.TopLeft));
      // Positionierung der Combobox (Left, Top, Width und Height werden zugewiesen):
      SetBounds(r.Left, r.Top, r.Right-r.Left, r.Bottom-r.Top);
      BringToFront; // Combobox in Vordergrund bringen
    end;
   ekCheckBox:
    with Editor.CheckBox do begin
      CopyRect(r, Rec); // rec => r (Eck-Koordinaten an Hilfsrechteck übergeben)
      // Umrechnung der Eck-Koordinaten des Hilfsrechtecks:
      r.BottomRight := Parent.ScreenToClient(Editor.Table.ClientToScreen(r.BottomRight));
      r.TopLeft := Parent.ScreenToClient(Editor.Table.ClientToScreen(r.TopLeft));
      // Positionierung der Combobox (Left, Top, Width und Height werden zugewiesen):
      SetBounds(r.Left, r.Top, r.Right-r.Left, r.Bottom-r.Top);
      BringToFront; // Combobox in Vordergrund bringen
    end;
   ekComboBox:
    with Editor.ComboBox do begin
      CopyRect(r, Rec); // rec => r (Eck-Koordinaten an Hilfsrechteck übergeben)
      // Umrechnung der Eck-Koordinaten des Hilfsrechtecks:
      r.BottomRight := Parent.ScreenToClient(Editor.Table.ClientToScreen(r.BottomRight));
      r.TopLeft := Parent.ScreenToClient(Editor.Table.ClientToScreen(r.TopLeft));
      // Positionierung der Combobox (Left, Top, Width und Height werden zugewiesen):
      SetBounds(r.Left, r.Top, r.Right-r.Left, r.Bottom-r.Top);
      BringToFront; // Combobox in Vordergrund bringen
      //Editor.SetRect(r);
    end;
  end;
end;

end.
  Mit Zitat antworten Zitat