Italian community of Lazarus and Free Pascal

Programmazione => Generale => Topic aperto da: petrusic - Luglio 28, 2024, 04:40:16 pm

Titolo: [Risolto] StringGrid: impostare, da codice; fsBold in tutta urga
Inserito da: petrusic - Luglio 28, 2024, 04:40:16 pm
L'Evento drawcell della StringGrid continua  a mettermi in difficoltà, per me insormontabili.

Durante compilazione di una stringGrid, vorrei evidenziare un tipo particolare, impostando  lo style fsbold. Ho pensato di farlo  sfrtuttando l'evento onDrawCell, ma riesco ad applicare lo fsbold soltanto all cella indirizzata dalla coordinate, ma nemmeno bene.
Riporto sia il codice che il risultato pratico della prova:
Codice: [Seleziona]
procedure TForm8.GridPreAmmortDrawCell(Sender: TObject; aCol, aRow: Integer;
  aRect: TRect; aState: TGridDrawState);
var
  lun, p, totRg: Integer;

  cellaSel: String;

  allin : TTextStyle;    // tipo di allineamento

begin
  if (aRow <> 0) then
  begin
    cellaSel:= Form8.GridPreAmmort.Cells[aCol, aRow];    // punta alla casella selezionata
    if (Form8.GridPreAmmort.Cells[8, aRow] = 'X') and (Length(Form8.GridPreAmmort.Cells[7, aRow]) > 0) then
    begin
       bla, bla, bla
    end
    else begin
      p:= pos( 'Totali', cellaSel);     // <--- individuo ogni cella che contiene la sottostringa
      if (p > 0) then
      begin
        GridPreAmmort.Canvas.Font.Style:= [fsBold];
        lun:= Form8.GridPreAmmort.Canvas.TextWidth(cellaSel);
        allin:= Canvas.TextStyle;
        case Form8.GridPreAmmort.Canvas.TextStyle.Alignment of // rileva il tipo di allineamento dichiarato per la casella
          taLeftJustify:
            begin
              if (aCol = 0) then
              begin
                Form8.GridPreAmmort.Canvas.TextOut(aRect.Right - lun - 1, aRect.Top + 2, CellaSel);
              end
              else begin
                Form8.GridPreAmmort.Canvas.TextOut(aRect.Left + 2, aRect.Top + 2, CellaSel);
              end;
            end;
          taRightJustify:
            begin
              Form8.GridPreAmmort.Canvas.TextOut(aRect.Right - lun - 2, aRect.Top + 2, CellaSel);
            end;
          taCenter:
            begin
              Form8.GridPreAmmort.Canvas.TextOut(aRect.Left + ((lun div 2) - 7), aRect.Top + 2, CellaSel);
            end;
        end;
      end;
    end;
  end;
end;
Così facendo però riesco solo ad impostare ilo stile fsbold alla cella contetente la sottostringa "Totali", ma nemmeno bene, come si può vedere benissimo nell'allegato.

Ho scoperto poi che l'evento onDrawCell viene schedulato 2 volte, ... ma perchè?

Andando per gradi, la pima difficoltà da superare, per rispettare il titolo della discusione, credo che sia quella di capire come applicare il carattere fsbold a tutta la riga a cui appartiene la cella con la sottostringa "Totali", anche sporca come appare nell'allegato.

Titolo: Re:StringGrid: impostare, da codice; fsBold in tutta urga
Inserito da: DragoRosso - Luglio 28, 2024, 05:34:29 pm
Ho scoperto poi che l'evento onDrawCell viene schedulato 2 volte, ... ma perchè?

Proprietà "DefaultDrawing" a true della StringGrid ? In questo caso la stringgrid scrive comunque prima il suo default e poi chiama l'evento (e quindi ti sovrapponi a quanto già scritto).
Titolo: Re:StringGrid: impostare, da codice; fsBold in tutta urga
Inserito da: DragoRosso - Luglio 28, 2024, 05:37:17 pm
Andando per gradi, la pima difficoltà da superare, per rispettare il titolo della discusione, credo che sia quella di capire come applicare il carattere fsbold a tutta la riga a cui appartiene la cella con la sottostringa "Totali", anche sporca come appare nell'allegato.
Discussione già affrontata ? (https://www.lazaruspascal.it/index.php?topic=2388.msg16020;topicseen#msg16020 (https://www.lazaruspascal.it/index.php?topic=2388.msg16020;topicseen#msg16020))
Titolo: Re:StringGrid: impostare, da codice; fsBold in tutta urga
Inserito da: petrusic - Luglio 28, 2024, 06:38:43 pm
Discussione già affrontata ? (https://www.lazaruspascal.it/index.php?topic=2388.msg16020;topicseen#msg16020 (https://www.lazaruspascal.it/index.php?topic=2388.msg16020;topicseen#msg16020))

Le somiglia, ma, a mio avviso,  non lo è. Ora devo evidenziare con lo stile fsbold alcune le celle significative di tutte le righe contenenti una data sottostringa, prima della visualizzazione della StringGrid.

Ho scoperto poi che l'evento onDrawCell viene schedulato 2 volte, ... ma perchè?

Proprietà "DefaultDrawing" a true della StringGrid ? In questo caso la stringgrid scrive comunque prima il suo default e poi chiama l'evento (e quindi ti sovrapponi a quanto già scritto).

Si, è quello, ma, impostando la Proprietà "DefaultDrawing" a Fallse, non trovo più valorizzate tutte le altre righe (vedi allegato)
Titolo: Re:StringGrid: impostare, da codice; fsBold in tutta urga
Inserito da: DragoRosso - Luglio 28, 2024, 09:14:13 pm
Si, è quello, ma, impostando la Proprietà "DefaultDrawing" a False, non trovo più valorizzate tutte le altre righe (vedi allegato)

Bhè è certo. Se vuoi scrivere tu qualche cella ... le devi scrivere tutte. Come fà il controllo a sapere quale cella scrivere e quale no ?.

Le somiglia, ma, a mio avviso,  non lo è. Ora devo evidenziare con lo stile fsbold alcune le celle significative di tutte le righe contenenti una data sottostringa, prima della visualizzazione della StringGrid.

La tecnica è sempre la stessa, che poi è quella che hai usato tu. Devi solo controllare RIGA e COLONNA riportate nell'evento e decidere cosa fare (ad esempio a seconda del contenuto del testo o altro).
Il tuo problema è che devi conoscere a priori quale riga devi modificare, non puoi basarti sull'evento a meno di fare strani loop: potresti ogni volta che l'evento cambia riga ciclare sulla stringgrid  (sempre nell'evento) sui valori di quella riga e se trovi il valore "TOTALE" allora imposti il bold su ogni colonna della riga.

Però, a parte il discutibile stile (di programmazione  8) ), non sò se ci sono controindicazioni (ad esempio la lentezza nella visualizzazione o altro).

Ciao
Titolo: Re:StringGrid: impostare, da codice; fsBold in tutta urga
Inserito da: petrusic - Luglio 31, 2024, 05:06:34 pm
 :-\
Peggio di così non può andare.

Ho impostato a False la proprietà DefaultDrawing della StringGrid e da quel momento qualsiasi azione svolta sulle singole celle , NON produce più la visibilità del loro contenuto, perciò la StringGrid si mostra completamente vuota.
Riporto il codice interno alla procedura-evento GridPreAmmortDrawCell.
Codice: [Seleziona]
procedure TForm8.GridPreAmmortDrawCell(Sender: TObject; aCol, aRow: Integer;
  aRect: TRect; aState: TGridDrawState);

var
  swStylFsBold: Boolean = False;

  i, lun, p, totRg, ixCol, ixRg : Integer;

  cellaSel: String;

  allin : TTextStyle;    // tipo di allineamento

begin
  cellaSel:= GridPreAmmort.Cells[aCol, aRow];  // punta alla casella selezionata
  if (aRow = 0) then
  begin
    GridPreAmmort.Canvas.Font.Style:= [fsBold];
    allin:= Canvas.TextStyle;
  end;
  if (aCol = 0) and (aRow > 0) then
  begin
    GridPreAmmort.Canvas.Font.Style:= [fsBold];
    lun:= Form8.GridPreAmmort.Canvas.TextWidth(cellaSel);
    Dec(ARect.Right, varCellPadding);
    Dec(ARect.Right, 1);
    allin:= Canvas.TextStyle;
    allin.Alignment:= taRightJustify;
  end;
  if (aCol > 0) and (aRow > 0) then
  begin
    p:= pos( 'Totali', cellaSel);
    if (p > 0) then
    begin
      swStylFsBold:= True;
      GridPreAmmort.Canvas.Font.Style:= [fsBold];
      GridPreAmmort.Canvas.Rectangle(aRect);
    end
    else begin
      if swStylFsBold then
      begin
        GridPreAmmort.Canvas.Font.Style:= [fsBold];
      end
      else begin
        GridPreAmmort.Canvas.Font.Style:= [];
      end;
    end;
    case Form8.GridPreAmmort.Canvas.TextStyle.Alignment of // rileva il tipo di allineamento dichiarato per la casella
      taLeftJustify:
        begin
          Form8.GridPreAmmort.Canvas.TextOut(aRect.Left - lun - 1, aRect.Top, CellaSel);
        end;
      taRightJustify:
        begin
          Form8.GridPreAmmort.Canvas.TextOut(aRect.Right - lun - 2, aRect.Top, CellaSel);
        end;
      taCenter:
        begin
          Form8.GridPreAmmort.Canvas.TextOut(aRect.Left + ((lun div 2) - 7), aRect.Top, CellaSel);
        end;
    end;
 end;
end;                                           

Non capisco assolutamente dove sbaglio, ma può anche essere che:  dovrei eseguire qualcosa e non lo faccio.
Titolo: Re:StringGrid: impostare, da codice; fsBold in tutta urga
Inserito da: DragoRosso - Luglio 31, 2024, 11:43:07 pm
Ho provato il tuo codice pari pari (a parte il nome della stringgrid e della Form8), e a me funziona correttamente
Titolo: Re:StringGrid: impostare, da codice; fsBold in tutta urga
Inserito da: petrusic - Agosto 01, 2024, 10:25:45 am
Ho provato il tuo codice pari pari (a parte il nome della stringgrid e della Form8), e a me funziona correttamente
Non capisco.

Se a me non funziona, potrebbe dipendere allora da qualche impostazione di base nelle proprietà della StringGrid. Ieri ho cercato di capire come funziona il meccanismo parametrico interno alla StringGrid, impostando a False la proprietà DefaultDrawing, ma nonostante tuttie le prove fatte, non sono riuscito a vedere nemmeno una cella completa del suo contenuto.

Sarà una stupidata, ma intanto non posso andare avanti col programma.
Titolo: Re:StringGrid: impostare, da codice; fsBold in tutta urga
Inserito da: petrusic - Agosto 01, 2024, 12:12:45 pm
Pare che ho risolto.

Ho reimpostato la proprietà DefaultDrawing = True ed ho scritto le mie istruzioni di evidenziazione dentro la prtocedura legata all'Evento OnPrepareCanvas:
Codice: [Seleziona]
procedure TForm8.GridPreAmmortPrepareCanvas(Sender: TObject; aCol,
  aRow: Integer; aState: TGridDrawState);
var
  ts: TTextStyle;

  p: Integer;
  ixRg: Integer = (-1);

begin
  if (aCol = 0) then
  begin
    With GridPreAmmort.Canvas.Font do
    begin
      Name:= 'Noto Sans TJK TC';
      Size:= 9;
      Style := [fsBold];        // Stile Grassetto per la riga di testa
    end;
    ts := GridPreAmmort.Canvas.TextStyle;
    ts.Alignment := taRightJustify;
    GridPreAmmort.Canvas.TextStyle := ts;
  end;
  if (aCol = 3) and (aRow > 0) then
  begin
    p:= pos( 'Totali', GridPreAmmort.Cells[aCol, aRow]);
    if (p > 0) then
    begin
      GridPreAmmort.Canvas.Font.Style:= [fsBold];
      ixRg:= aRow;
    end;
    if (Length(GridPreAmmort.Cells[aCol, aRow]) > 0) and (aRow = iXRg)   then
    begin
       GridPreAmmort.Canvas.Font.Style:= [fsBold];
    end;
 end;
end;

Ecco il risultato

A questo punto l'Evento OnDrawCell non m'interessa più.
Titolo: Re:StringGrid: impostare, da codice; fsBold in tutta urga
Inserito da: DragoRosso - Agosto 01, 2024, 12:38:21 pm
Anche quella è una strada. Anzi in Lazarus è la strada consigliata se si devono cambiare solo gli attributi della cella.
Titolo: Re:StringGrid: impostare, da codice; fsBold in tutta urga
Inserito da: petrusic - Agosto 01, 2024, 05:23:50 pm
Bene. Ora ho terminato le mie prove e posso dire di avere Risolto.

Ho infatti superato anche il problema della selezione di righe multiple non sequenziali, sempre senza disturbare l'evento OnDrawCell

@ DragoRosso
Grazie per tutte le dritte che mi hai regalato.  ;D