Results 1 to 14 of 14

Thread: stringgrid met combobox (en scrollbar)

  1. #1

    stringgrid met combobox (en scrollbar)

    Ik wil graag een stringgrid realiseren waarop een gebruiker bij sommige cellen een combobox te zien krijgt en daaruit zijn invoer kan kiezen.
    Hiervoor is een hoop code te vinden waarbij een losse combobox aan een cell gekoppeld wordt.
    Dit werkt op zich heel aardig echter zodra de stringgrid meer cellen heeft en er dus een scrollbar krijgt gaat het mis.
    De combobox is dan out of sync met de rij van de stringgrid.
    (Dit komt voornamelijk omdat de select cell functie eerder wordt uitgevoerd dan de actie waarbij het grid 1 cell verplaatst wordt)

    Weet iemand hier een oplossing voor waarbij er dus ook rekening gehouden wordt met de scrollbar

  2. #2
    Silly member NGLN's Avatar
    Join Date
    Aug 2004
    Location
    Werkendam
    Posts
    5,133
    Je kunt berekenen of de geselecteerde row de eerst of de laatst zichtbare is d.m.v. de property's TopRow en VisibleRowCount, als volgt:
    Delphi Code:
    1. procedure TForm1.StringGridSelectCell(Sender: TObject; ACol, ARow: Integer;
    2.   var CanSelect: Boolean);
    3. var
    4.   Rect: TRect;
    5. begin
    6.   ComboBox.Visible := ACol = 3;
    7.   if ARow = StringGrid.VisibleRowCount + StringGrid.TopRow then
    8.     Dec(ARow)
    9.   else if ARow < StringGrid.TopRow then
    10.     Inc(ARow);
    11.   Rect := StringGrid.CellRect(ACol, ARow);
    12.   Rect.Offset(StringGrid.GridLineWidth, StringGrid.GridLineWidth);
    13.   ComboBox.BoundsRect := Rect;
    14. end;
    (Sender as TNLDUser).Signature := 'Groeten van Albert';

  3. #3
    Ben idd daar nu wat mee aan het stoeien.
    Helaas komt je als volgt: stukje niet door

  4. #4
    Silly member NGLN's Avatar
    Join Date
    Aug 2004
    Location
    Werkendam
    Posts
    5,133
    procedure TForm1.StringGridSelectCell(Sender: TObject; ACol, ARow: Integer;
    var CanSelect: Boolean);
    var
    Rect: TRect;
    begin
    ComboBox.Visible := ACol = 3;
    if ARow = StringGrid.VisibleRowCount + StringGrid.TopRow then
    Dec(ARow)
    else if ARow < StringGrid.TopRow then
    Inc(ARow);
    Rect := StringGrid.CellRect(ACol, ARow);
    Rect.Offset(StringGrid.GridLineWidth, StringGrid.GridLineWidth);
    ComboBox.BoundsRect := Rect;
    end;
    (Sender as TNLDUser).Signature := 'Groeten van Albert';

  5. #5
    Wellicht eens kijken hoe dit gedaan wordt in TValueList?

    Bart

  6. #6
    Helaas komt met de code NGLN de combobox niet op de goeie plaatst
    Zelf heb ik onderstaande code gemaakt, aangezien ik maar 1 veld heb waar de combo te voorschijn moet komen (col = 1 en row =10) is dit voor mij voldoende. Wellicht zijn er nog mensen die het graag willen veralgemeniseren (be my guest)

    Code:
    procedure TForm4.StringGrid1SelectCell(Sender: TObject; ACol, ARow: Integer;
      var CanSelect: Boolean);
    var
    R: TRect;
    org: TPoint;
    begin
    Direction:=dirup;
    if prevRow<=Arow then Direction:=dirDown;
    
    prevRow:=Arow;
    
    if (Direction=DirDown) and (Tstringgrid(Sender).TopRow + Tstringgrid(Sender).VisibleRowCount =10) then
    begin
     Tstringgrid(Sender).TopRow :=Tstringgrid(Sender).TopRow +1;
     Tstringgrid(Sender).row:=Arow;
     exit;
    end;
    
    if (Direction=DirUp) and (Tstringgrid(Sender).TopRow-1 = ARow) then
    begin
     Tstringgrid(Sender).TopRow :=Tstringgrid(Sender).TopRow -1;
     Tstringgrid(Sender).row:=Arow;
     exit;
    end;
    
    With Sender As TStringgrid Do
    if (ACol = 1) and (ARow =10) Then
    Begin
     perform( WM_CANCELMODE, 0, 0 );
     R := CellRect( Acol, Arow );
     org:= Self.ScreenToClient( ClientToScreen( R.topleft ));
     With combobox1 do
     begin
      setbounds( org.X, org.Y, r.right-r.left, height );
      itemindex := Items.IndexOf( Cells[ acol, arow ] );
      Show;
      BringTofront;
      SetFocus;
      DroppedDown := true;
     end;
    end;
    
    end;

  7. #7
    Silly member NGLN's Avatar
    Join Date
    Aug 2004
    Location
    Werkendam
    Posts
    5,133
    Hihi, ik had getest met een StringGrid met Align=alClient, dus was vergeten te corrigeren voor positie van het grid op zijn parent.

    Hierbij aangepaste code, ervan uit gaande dat StringGrid.Parent = ComboBox.Parent:
    Code:
    procedure TForm1.GridSelectCell(Sender: TObject; ACol, ARow: Integer;
      var CanSelect: Boolean);
    var
      Rect: TRect;
    begin
      if ARow = Grid.VisibleRowCount + Grid.TopRow then
        Dec(ARow)
      else if ARow < Grid.TopRow then
        Inc(ARow);
      ComboBox.Visible := (ACol = 1) and (ARow = 10);
      Rect := Grid.CellRect(ACol, ARow);
      Rect.Offset(Grid.Left + Grid.GridLineWidth, Grid.Top + Grid.GridLineWidth);
      ComboBox.BoundsRect := Rect;
    end;
    En aangezien je hem in slechts één cell wilt tonen moet je denk ik OnTopLeftChanged ook nog even aanpassen voor het geval de gebruiker de scrollbalk gebruikt.
    Last edited by NGLN; 01-Apr-20 at 15:59.
    (Sender as TNLDUser).Signature := 'Groeten van Albert';

  8. #8
    Werkt nu wel, echter maar een kant op, wanneer ik van beneden naar boven ga komt de combobox op de verkeerde cel
    Wellicht nog iets om over na te denken ;-)

  9. #9
    Silly member NGLN's Avatar
    Join Date
    Aug 2004
    Location
    Werkendam
    Posts
    5,133
    @Bart: Ja, die werkt met een zogenaamde aangepaste InplaceEditor. Daartoe moet je wel een eigen TStringGrid-afgeleide aanmaken (en/of injecteren) waarin je o.a. CreateEditor override. Het standaard VCL component ondersteunt het inderdaad wel, maar zeker niet voor gemakkelijk gebruik.
    (Sender as TNLDUser).Signature := 'Groeten van Albert';

  10. #10
    mov rax,marcov; push rax marcov's Avatar
    Join Date
    Apr 2004
    Location
    Ehv, Nl
    Posts
    10,357
    Kijk ook eens naar de "advanced demo" van virtual string grid/tree

  11. #11
    Silly member NGLN's Avatar
    Join Date
    Aug 2004
    Location
    Werkendam
    Posts
    5,133
    Nou, het blijkt uiteindelijk nog wel mee te vallen om dit op de VCL-manier op te lossen.* Zoals Bart in post 5 zei doet de VCL dit immers zelf ook heel aardig in TValueListEditor. De zogenaamde InplaceEditor (een protected property van het grid) is standaard van het type TInplaceEdit, welke geen lijstje kan weergeven. TInplaceEditList kan dat wel. Die dient aangemaakt te worden in een afgeleide van CreateEditor. Hiertoe moet je het StringGrid zelf dus ook afleiden. Gelukkig is hiervoor een trucje beschikbaar door deze afgeleide ook weer TStringGrid te noemen zodat je geen nieuw component hoeft te installeren terwijl je verder gewoon wel het component kan designen.

    Kortom, het minimaal benodigde is:
    Delphi Code:
    1. unit Unit2;
    2.  
    3. interface
    4.  
    5. uses
    6.   System.Classes, Vcl.Controls, Vcl.Forms, Vcl.Grids;
    7.  
    8. type
    9.   TStringGrid = class(Vcl.Grids.TStringGrid)
    10.   protected
    11.     function CreateEditor: TInplaceEdit; override;
    12.     function GetEditStyle(ACol, ARow: Integer): TEditStyle; override;
    13.     procedure EditorGetPickListItems(ACol, ARow: Integer; Items: TStrings);
    14.   end;
    15.  
    16.   TForm2 = class(TForm)
    17.     StringGrid1: TStringGrid;
    18.   end;
    19.  
    20. implementation
    21.  
    22. {$R *.dfm}
    23.  
    24. { TStringGrid }
    25.  
    26. function TStringGrid.CreateEditor: TInplaceEdit;
    27. begin
    28.   Result := TInplaceEditList.Create(Self);
    29.   TInplaceEditList(Result).OnGetPickListitems := EditorGetPickListItems;
    30. end;
    31.  
    32. function TStringGrid.GetEditStyle(ACol, ARow: Integer): TEditStyle;
    33. begin
    34.   if (ACol = 1) and (ARow = 10) then
    35.     Result := esPickList
    36.   else
    37.     Result := esSimple;
    38. end;
    39.  
    40. procedure TStringGrid.EditorGetPickListItems(ACol, ARow: Integer;
    41.   Items: TStrings);
    42. begin
    43.   Items.Add('A');
    44.   Items.Add('B');
    45.   Items.Add('C');
    46. end;
    47.  
    48. end.
    Het voordeel hiervan is uiteraard dat de functionaliteit echt geïntegreerd is in de Cell, en dat zie en merk je. Zo wordt de DropDownButton pas zichtbaar als je de Cell gaat bewerken (met bijv. F2), de regelhoogte kun je instellen op een ander formaat dan die van een ComboBox (waarvan de hoogte fixed is), en er zweeft geen extra control boven je grid dat de focus wegneemt.

    * Ik had eerder geëxperimenteerd met dit soort aanpassingen voor NLDStringGrid, maar dat was ver weggezakt.
    Last edited by NGLN; 02-Apr-20 at 08:26.
    (Sender as TNLDUser).Signature := 'Groeten van Albert';

  12. #12
    Fornicatorus Formicidae VideoRipper's Avatar
    Join Date
    Mar 2005
    Location
    Vicus Saltus Orientalem
    Posts
    5,708
    Quote Originally Posted by NGLN View Post
    Nou, het blijkt uiteindelijk nog wel mee te vallen
    Op sommige andere fora kun je posts een duimpje/like geven, hier op NLDelphi (nog) niet: bij dezen!
    TMemoryLeak.Create(Nil);

  13. #13
    Heb nu het NLDStringrid werkend in delphi 10.3, maar zie nog niet helemaal hoe ik hier een combobox aan kan toevoegen

  14. #14
    Silly member NGLN's Avatar
    Join Date
    Aug 2004
    Location
    Werkendam
    Posts
    5,133
    NLDStringGrid biedt geen ondersteuning voor een PickList voor (een) specifieke cell(s), alleen voor gehele kolommen. Als je dat wilt: voeg dan eerst een of meerdere Columns toe en stel daarvan de EditStyle in.

    (Echter geen garanties dat NLDStringGrid in recente versies van Delphi werkt, want hij is gemaakt in D7!)
    (Sender as TNLDUser).Signature := 'Groeten van Albert';

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •