In DBGrid eine CheckBox ???



  • Hallo User's,

    kennt sich jemand von euch mit Borland C++ Builder und DBGrid aus?? Habe da ein kleines Problem !!!

    Ich Beziehe aus einem TTable Daten, die in einen DBGrid dargestellt werden. Beim verändern dieser DBGrid, Boolesche Ausdrücke, muss ich immer Falsch oder Wahr als Wort eingeben, ansonsten bekomme ich ein ERROR. Wie bekomme ich es hin, das dies durch eine CheckBox innerhalb einer DBGrid realisiert wird. Die PickList ist schon ein kleine Hilfe, nur leider hat der Anwender nicht das Gefühl in Windows zu leben 😉

    Würde mich über jede Lösung freuen 🙂

    Gruß Ralle



  • Hi,

    wenn du nur zum Editieren die Checkboxen haben willst, so überschreib den TInplaceEditor und mach ne Checkbox daraus. Wenn du bei boolschen- Werten grundsätzlich eine Checkbox angezeigt haben möchtest, so überschreibe OnDrawItem und platziere Instanzen einer Checkbox in die Cellen, in der ein boolscher Wert vorhanden ist.
    Du könntest dann auch gleich die Checkbox neu machen, und die Dantenbankfelds- änderungen direkt üer die Checkbox machen zu lassen oder das Event OnCheck so einfähren, das das gewünschte Datenbankfeld im Ereignis mit angegeben wird. Das würde den Verwaltungsaufwand um einiges reduzieren.
    Ist aber nicht notwendig, wenn du weisst, wo du welche Checkbox hingeschmissen hast.

    Generell würde ich aber eine neue Komponente vom DBGrid ableiten um dieses zu Implementieren. Der Vorteil ist halt, das es wiederverwendbar ist und du den ganzen Verwaltungskram der Checkboxen in der neuen Klasse kappseln kannst. Ein paar userfreundliche Ereignisse einfügen, ein paar Eigenschaften bereitstellen und jeder Anwendungsentwickler freut sich über ne neue Kompo.

    [ Dieser Beitrag wurde am 02.02.2003 um 11:50 Uhr von AndreasW editiert. ]



  • lösung gibts hier :
    www.tmssoftware.com und schau dir mal das advstringgrid an !

    ciao



  • gut, geht auch. Kostet aber...



  • ja aber lohnt sich wirklich !



  • Danke für Eure Antworten, habe mich nun für eine DBCheckBox außerhalb der DBGrid entschieden, ist halt leichter und nicht so aufwendig.

    Danke

    Gruß Ralle



  • Hi,

    OnDrawDataCell, OnColEnter, OnCellClick

    void __fastcall TForm1::DBGrid1DrawDataCell(TObject *Sender,
          const TRect &Rect, TField *Field, TGridDrawState State)
    {
     TDBGrid *dbg = dynamic_cast<TDBGrid *>(Sender);
     if (dbg && Field->FieldName == "ColumnBool" && !ADOQuery1->IsEmpty())
      {
      TRect TmpRect(Rect);
      TmpRect.Right = Rect.Left + Rect.Height();
      dbg->Canvas->FillRect(Rect);
    
      UINT Checked = (Field->AsBoolean && !Field->IsNull ? DFCS_BUTTONCHECK : DFCS_BUTTONCHECK | DFCS_CHECKED);
    
      DrawFrameControl(dbg->Canvas->Handle, &TmpRect, DFC_BUTTON, Checked);
     }
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::DBGrid1ColEnter(TObject *Sender)
    {
     TDBGrid *dbg = dynamic_cast<TDBGrid *>(Sender);
     if (dbg)
      {
       TDBGridOptions go(dbg->Options);
       go = (dbg->SelectedField->FieldName == "ColumnBool" ? go >> dgEditing : go << dgEditing);
       dbg->Options = go;
      }
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::DBGrid1CellClick(TColumn *Column)
    {
     if (Column->FieldName == "ColumnBool")
      {
       ADOQuery1->Edit();
       Column->Field->AsBoolean = !Column->Field->AsBoolean;
       ADOQuery1->Post();
      }
    }
    


  • Danke Blazek Jaroslav

    Habe den Code ein wenig geändert und nun funktioniert er auch bei TTable!

    Habe diesen auch in einen Test Programm zum laufen bekommen, leider funktioniert dieser Code nicht in meinen Hauptprogramm!! Komisch!!!

    void __fastcall TForm1::DBGrid1DrawDataCell(TObject *Sender,
          const TRect &Rect, TField *Field, TGridDrawState State)
    {
    
      TDBGrid *dbg = dynamic_cast<TDBGrid *>(Sender);
    // if (dbg && Field->FieldName == "OK" && ! Query1->IsEmpty())
      if (dbg && Field->FieldName == "OK")
      {
      TRect TmpRect(Rect);
      TmpRect.Right = Rect.Left + Rect.Height();
      dbg->Canvas->FillRect(Rect);
    
      UINT Checked = (Field->AsBoolean && !Field->IsNull ? DFCS_BUTTONCHECK : DFCS_BUTTONCHECK | DFCS_CHECKED);
    
      DrawFrameControl(dbg->Canvas->Handle, &TmpRect, DFC_BUTTON, Checked);
      }
    
    }  
    
    void __fastcall TForm1::DBGrid1ColEnter(TObject *Sender)
    {
     TDBGrid *dbg = dynamic_cast<TDBGrid *>(Sender);
     if (dbg)
      {
       TDBGridOptions go(dbg->Options);
       go = (dbg->SelectedField->FieldName == "OK" ? go >> dgEditing : go << dgEditing);
       dbg->Options = go;
      }
    }
    
    void __fastcall TForm1::DBGrid1CellClick(TColumn *Column)
    {
    if (Column->FieldName == "OK")
      {
      DataSource1->Edit();
       Column->Field->AsBoolean = !Column->Field->AsBoolean;
       //DataSource1->  Post();
      }
    }
    


  • Hallo,

    ich habe das gleiche Problem mit der Checkbox auf dem DBGrid. Ich habe den Quelltext so in mein Programm übernommen. Allerdings funktioniert bei mir nichts. Hab immer noch das Feld mit Wahr oder Falsch. Was mache ich falsch??

    void __fastcall TForm1::DBGrid1DrawDataCell(TObject *Sender,
          const TRect &Rect, TField *Field, TGridDrawState State)
    {
     TDBGrid *dbg = dynamic_cast<TDBGrid *>(Sender);
      if (dbg && Field->FieldName == "abc")
      {
      TRect TmpRect(Rect);
      TmpRect.Right = Rect.Left + Rect.Height();
      dbg->Canvas->FillRect(Rect);
    
      UINT Checked = (Field->AsBoolean && !Field->IsNull ? DFCS_BUTTONCHECK : DFCS_BUTTONCHECK | DFCS_CHECKED);
    
      DrawFrameControl(dbg->Canvas->Handle, &TmpRect, DFC_BUTTON, Checked);
      }
    
    }
    


  • Ich habe so ein ähnliches Problem und zwar mit dem StringGrid, und zwar würde ich die Zellen gerne mit einem MaskEdit überschreiben. Um so verschieden Masken (ShortTime) setzen zu können. Weiss jemand wie das geht?





  • Hallo,

    funkt. leider immer noch nicht. Hab aber das Gefühl, das er erst gar nicht in die Methode "DBGrid1DrawDataCell" hineingeht. Habe ein Breakpoint gesetzt und nichts kam. Was läuft da bei mir schief???

    Gruss,
    MTO



  • Hab aber das Gefühl, das er erst gar nicht in die Methode "DBGrid1DrawDataCell" hineingeht

    Hast Du auch TDBGrid::DefaultDrawing entsprechend gesetzt ?



  • ich hab die beispiele mal versucht aber im bcb 6 prof kann ich ihn nicht dazu bewegen in die funkion OnDrawDataCell zu gehen. lauf hilfe von borland soll man die funktion nicht mehr verwenden.

    hat jemand vielleicht noch eine andere idee wie man eine checkbox in ein dbgrid bringen kann??



  • Hier ist die Idee, welche bei mir tadellos funzt, allerdings auch noch ne andere frage, wie bekomme ich die checkbox mittig beim anklicken? und eine andere: wie kann ich testen, ob die aktuelle spalte ein boolean ist? wenn ich abfrage, mit: if(Column->Field->AsBoolean) klappt es nicht?!

    Hier die End-Lösung:

    Man positioniert eine DBCheckBox auf das Formular, und schlatet sie auf Visible=false;

    Im ColExit-Event:
    
        TDBGrid *dbg = dynamic_cast<TDBGrid *>(Sender);
        if(dbg->SelectedField->FieldName == DBCheckBox1->DataField)
            DBCheckBox1->Visible = false;
    
    Im DrawColumnCell-Event:
    
        TDBGrid *dbg = dynamic_cast<TDBGrid *>(Sender); 
    
        if(Column->FieldName == "aktiv")
        {
            UINT Checked = (Column->Field->AsBoolean && !Column->Field->IsNull ?  DFCS_BUTTONCHECK | DFCS_CHECKED : DFCS_BUTTONCHECK);
            TRect DrawRect;
            if (State.Contains(gdFocused))
            {
                if (Column->Field->FieldName == DBCheckBox1->DataField)
                {
                    DBCheckBox1->Left = Rect.Left + dbg->Left + 2;
                    DBCheckBox1->Top = Rect.Top + dbg->Top + 2;
                    DBCheckBox1->Width = Rect.Right - Rect.Left;
                    DBCheckBox1->Height = Rect.Bottom - Rect.Top;
                    DBCheckBox1->Visible = True;
                }
            }
            else
            {
                if (Column->Field->FieldName == DBCheckBox1->DataField)
                {
    
                    DrawRect=Rect;
                    InflateRect(&DrawRect,-1,-1);
                    dbg->Canvas->FillRect(Rect);
                    DrawFrameControl(dbg->Canvas->Handle, &DrawRect, DFC_BUTTON, Checked);
                }
            }
        }
    


  • Hi,

    um abzufragen, welchen Typ ein Feld hat, einfach den Klassennamen vergleichen,
    z.B.

    if(Field->ClassName == "TBooleanField")
      ...
    

    Die Eigenschaft "AsBoolean" wandelt nur den Feldinhalt in einen boolschen Typ (falls möglich).

    Um die Checkbox mittig in dem Feld zu setzen, mußt du die Formel
    Left = (ColumnWidth - CheckBoxWidth) / 2
    Top = (RowHeight - CheckBoxHeight) / 2
    benutzen.



  • das klappt leider nicht, bei der abfrage auf: ich benutze das (DrawColumnCell-Event)

    if(Column->Field->ClassName == "TBooleanField")
    

    Mache ich etwas falsch?

    gruß gerd



  • ok, lösung hierfür habe ich gefunden, allerdings weiss ich nicht, wie ich es für mehrere hinbekommen kann, sprich wenn ich zwei (oder am besten eine variable anzahl) bool columns habe. wie stelle ich es dort an?

    Lösung:

    if(AnsiString(Column->Field->ClassName()) == "TBooleanField")
    

    gruß gerd



  • evtl. besser

    if(Column->Field->DataType == ftBoolean)
    


  • viele dank, werde das auch testen.

    gruß gerd


Log in to reply