Eine ComboBox in einer StringGrid-Zelle anzeigen

  • auf eine Form 1 StringGrid mit 4 Spalten setzten, FixedCols = 1, FixedRows = 1, Name = sgStringGrid
  • *.h
__published: // Von der IDE verwaltete Komponenten
void __fastcall FormResize(TObject *Sender);
void __fastcall FormCreate(TObject *Sender);
void __fastcall FormDestroy(TObject *Sender);
void __fastcall ComboEditorChange(TObject *Sender); void __fastcall ComboEditorDropDown(TObject *Sender);
void __fastcall sgStringGridTopLeftChanged(TObject *Sender);
void __fastcall sgStringGridMouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y);
void __fastcall sgStringGridMouseUp(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y);

private: // Anwender-Deklarationen

TComboBox *pComboEditor; // unsere ComboBox AnsiString sOldEditValue; //Zwischenspeicher für alten Zellinhalt
void __fastcall SetColWidth(TStringGrid *Grid);
void __fastcall SetzeComboBox(TStringGrid *Grid);
void __fastcall FillComboEditor(TComboBox *CBox);
  • *.cpp

// Eine ComboBox mit entspr. Eigenschaften erzeugen
void __fastcall TForm1::FormCreate(TObject *Sender)
{
   pComboEditor = new TComboBox(/*Groupbox oder Panel oder sonstwas*/);
   pComboEditor->Parent = /*Groupbox oder Panel oder sonstwas*/;
   pComboEditor->Visible = false;
   pComboEditor->Style = csDropDownList;
   pComboEditor->DropDownCount = 8;
   pComboEditor->BevelInner = bvLowered;
   pComboEditor->BevelOuter = bvSpace;
   pComboEditor->BevelKind = bkSoft;
   pComboEditor->OnChange = ComboEditorChange;
   pComboEditor->OnDropDown = ComboEditorDropDown;
   
   // Items in die ComboBox laden
   FillComboEditor(pComboEditor);
}

// Funktion zum Füllen der ComboBox
void __fastcall TForm1::FillComboEditor(TComboBox *CBox)
{
   CBox->Items->Clear(); CBox->Items->Add("Test1");
   CBox->Items->Add("Test2");
   CBox->Items->Add("Test3");
   CBox->ItemIndex = 0;
}

// bei Programmende die ComboBox wieder löschen
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
   if (pComboEditor)
   {
      delete pComboEditor;
      pComboEditor = NULL;
   }
}

// Falls das Formular / Stringgrid in der Größe geändert wird,
// die ComboBox mit anpassen
void __fastcall TForm1::FormResize(TObject *Sender)
{
   SetColWidth(sgStringGrid);
   SetzeComboBox(sgStringGrid);
}

// Die Größe der letzten StringGrid-Spalte immer auf maximal setzen
void __fastcall TForm1::SetColWidth(TStringGrid *Grid)
{
   // Breite der letzten StringGridspalte an die Formularbreite anpassen:
   int ilColWidthsSum = 0;

   for (int ilCol = 0; ilCol < Grid->ColCount-1; ilCol++)
   {
      ilColWidthsSum += Grid->
      ColWidths[ilCol] + Grid->GridLineWidth;
   }
   
   if (ilColWidthsSum < Grid->ClientWidth) Grid->ColWidths[Grid->ColCount-1] = Grid->ClientWidth - ilColWidthsSum - 1;
}

// Falls im StringGrid gescrollt wird
void __fastcall TForm1::sgStringGridTopLeftChanged(TObject *Sender)
{
   TStringGrid *Grid = (TStringGrid*)Sender;
   SetzeComboBox(Grid);
}

// die eigentliche Funktion zum Setzten der ComboBox
void __fastcall TForm1::SetzeComboBox(TStringGrid *Grid)
{
   int iCol = Grid->Col;
   int iRow = Grid->Row;
   int iCSpalte = 3; // Combobox wir in die 3. Spalte gesetzt

   if ((iCol == iCSpalte) && (Grid->Cells[0][iRow] != ""))
   {
      TRect Rect = Grid->CellRect(iCol, iRow);
      if (Rect.Width() -> 10)
      {  // ComboBox in das TRect der Zelle einpassen
         pComboEditor->Visible = false;
         pComboEditor->Top = Grid->Top; // wichtig!!
         pComboEditor->Left = Grid->Left;
         pComboEditor->ItemIndex = pComboEditor->Items->IndexOf(Grid->Cells[iCol][iRow]);
         pComboEditor->Top = pComboEditor->Top + Rect.Top + Grid->GridLineWidth - 1;
         pComboEditor->Left = pComboEditor->Left + Rect.Left + Grid->GridLineWidth - 1;
         pComboEditor->Height = Rect.Height() + 1;
         pComboEditor->Width = Rect.Width();
         pComboEditor->Visible = true;
         pComboEditor->SetFocus();
      }
      else pComboEditor->Visible = true;
   }
   else pComboEditor->Visible = false;
}

// wenn ein Eintrag ausgewählt wurde, dann in die StringGrid Zelle einsetzen
void __fastcall TForm1::ComboEditorChange(TObject *Sender)
{
   sgStringGrid->Cells[sgStringGrid->Col][sgStringGrid->Row] = pComboEditor->Items->Strings[pComboEditor->ItemIndex];
}

// wenn die ComboBox angeklickt wird, den alten Zellinhalt zwischenspeichern (für spätere Verwendung)
void __fastcall TForm1::ComboEditorDropDown(TObject *Sender)
{
   sOldEditValue = sgStringGrid->Cells[sgStringGrid->Col][sgStringGrid->Row];
}

// wenn im StringGrid geklickt wird, ComboBox setzten // könnte vielleicht auch im OnClick-Ereignis des StringGrids abgehandelt werden
void __fastcall TForm1::sgStringGridMouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
{
   TStringGrid *Grid = (TStringGrid*)Sender;
   if (Grid->Cells[0][1] != "")
   {
      Grid->Options << goEditing;
      SetzeComboBox(Grid);
   }
   else Grid->Options ->-> goEditing;
}

// Wenn im StringGrid die Maus losgelassen wird, nochmal die CBox-setzen
void __fastcall TForm1::sgStringGridMouseUp(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
{
   TStringGrid *Grid=(TStringGrid*)Sender;
   SetColWidth(Grid); Grid->Repaint();
   SetzeComboBox(Grid);
}