If I were to create a new component in my private variables how do I put a TDataSource to notice inside the new object that is a change in the datasource? Which in turn is initialized with an external data source I use to populate a TDBGrid?
unit ExtDBListBox;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, Grids, sqldb, db;
type
TExtDBListBox = class(TStringGrid)
private
{ Private declarations }
MyDataSourceList: TDataSource; { il datasource che mi fa vedere i dati nel componente }
MyDataSourceIn: TDataSource; { il datasource che contiene i record sorgenti }
MySQLOut: TSQLQuery; { il datasource che contiene i record in output, ovvero quelli che vado a modificare }
ItemsSelected: array of boolean; { mi serve per capire se una (o più) riga è selezionata }
Intestazione: boolean; { se TRUE vuol dire che devo far vedere l'intestazione dei dati nel componente }
MyFieldList: string;
MyFieldIn: string;
MyFieldOutList, MyFieldOutIn: string;
MyAutoSizeColumns: BOOLEAN;
procedure InserisciRecord();
procedure EliminaRecord();
procedure ColoraComponente();
function EsisteRecord(ValIn: variant; ValoreList: variant): BOOLEAN;
protected
{ Protected declarations }
procedure SetDataSourceList(DataSourceList: TDataSource);
procedure SetDataSourceIn(DataSourceIn: TDataSource);
procedure SetQuerySQLOut(SQLOut: TSQLQuery);
procedure SetTitleColumns(TitleColumns: BOOLEAN);
procedure SetFieldList(FieldList: string);
procedure SetFieldIn(FieldIn: string);
procedure SetFieldOutList(FieldOutList: string);
procedure SetFieldOutIn(FieldOutIn: string);
procedure SetAutoSizeColumns(ColumnsAutoSize: BOOLEAN);
public
{ Public declarations }
constructor Create(TheOwner: TComponent); override;
procedure Requery();
procedure ColumnVisible(ColIndex: integer; Value: boolean);
procedure ColumnAlign(ColIndex: integer; Value: TAlignment);
procedure Click; override;
procedure DrawCell(aCol, aRow: Integer; aRect: TRect; aState: TGridDrawState); override;
procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
published
{ Published declarations }
//property OnClick;
property DataSourceList: TDataSource read MyDataSourceList write MyDataSourceList;
property DataSourceIn: TDataSource read MyDataSourceIn write MyDataSourceIn;
property SQLOut: TSQLQuery read MySQLOut write MySQLOut;
property TitleColumns: BOOLEAN read Intestazione write Intestazione;
property FieldList: string read MyFieldList write MyFieldList;
property FieldIn: string read MyFieldIn write MyFieldIn;
property FieldOutList: string read MyFieldOutList write MyFieldOutList;
property FieldOutIn: string read MyFieldOutIn write MyFieldOutIn;
property ColumnsAutoSize: BOOLEAN read MyAutoSizeColumns write MyAutoSizeColumns;
end;
procedure Register;
implementation
procedure Register;
begin
{$I ExtDBListBox_icon.lrs}
RegisterComponents('Standard',[TExtDBListBox]);
end;
constructor TExtDBListBox.Create(TheOwner: TComponent);
begin
inherited Create(TheOwner);
{cambio il layout della griglia per far si che si veda come se fosse una listbox}
Self.ColCount:=1;
Self.FixedCols:=0;
Self.FixedRows:=0;
Self.AutoEdit:=false;
Self.GridLineWidth:=0;
Intestazione:=FALSE;
Self.SetDataSourceList(nil); //mi prendo il datasource dal quale lavorare
Self.SetDataSourceIn(nil); //mi prendo il datasource dal quale lavorare
Self.SetQuerySQLOut(nil); //mi prendo il TSQlQuery dal quale lavorare
MyFieldList:='';
MyFieldIn:='';
MyFieldOutList:='';
MyFieldOutIn:='';
MyAutoSizeColumns:=FALSE;
end;
procedure TExtDBListBox.Requery();
var
NumRighe, NumColonne: LongInt;
Colonna, Riga: integer;
app:string;
MyTextStyle: TTextStyle;
begin
Self.SetDataSourceList(DataSourceList); //mi prendo il datasource dal quale lavorare
Self.SetDataSourceIn(DataSourceIn); //mi prendo il datasource dal quale lavorare
Self.SetQuerySQLOut(MySQLOut); //mi prendo il datasource dal quale lavorare
Self.SetFieldList(FieldList);
Self.SetFieldIn(FieldIn);
Self.SetFieldOutList(FieldOutList);
Self.SetFieldOutIn(FieldOutIn);
Self.Clear; //pulisco la listbox dai dati
{ora disegno il dataset}
if ((MyDataSourceList<>nil)AND(not MyDataSourceList.DataSet.EOF)) then
begin
{mi ricavo il numero di colonne che devo stampare a video}
NumColonne:=MyDataSourceList.DataSet.FieldCount;
For Colonna:=0 to (NumColonne-Self.Columns.Count)-1 do
Self.Columns.Add;
{mi scorro velocemente il recordset per capire quante righe ho}
MyDataSourceList.DataSet.First;
NumRighe:=0;
while not MyDataSourceList.DataSet.EOF do
begin
Inc(NumRighe);
MyDataSourceList.DataSet.Next;
end;
{ora che ho il numero di righe mi stampo la griglia}
if Intestazione=TRUE then
begin
Self.RowCount:=NumRighe+1;
{ora inserisco la testata}
for Colonna:=0 to NumColonne-1 do
begin
app:=MyDataSourceList.DataSet.FieldDefs[Colonna].Name;
if Length(Trim(app))<=0 then
app:='Col' + IntToStr(Colonna);
Self.Cells[Colonna,0]:=app;
end;
Riga:=1;
end
else
begin
//Self.Columns.Add.Create(nil);
Self.RowCount:=NumRighe;
Riga:=0;
end;
{ora inserisco i dati}
MyDataSourceList.DataSet.First;
while not MyDataSourceList.DataSet.EOF do
begin
{disegno la singola riga}
for Colonna:=0 to NumColonne-1 do
begin
Self.Cells[Colonna,Riga]:=MyDataSourceList.DataSet.Fields[Colonna].AsString;
end;
Inc(Riga);
MyDataSourceList.DataSet.Next;
end;
SetLength(ItemsSelected,NumRighe); //dimensiono il vettore che mi contiene se la riga è selezionata oppure no
For Riga:=0 to NumRighe-1 do
ItemsSelected[Riga]:=FALSE;
if Self.MyAutoSizeColumns=TRUE then
Self.AutoSizeColumns; //dimensiona le colonne correttamente
Self.ColoraComponente();
MyDataSourceList.DataSet.First; { se non faccio questo passo al prossimo requery che faccio mi trovo già al fondo e non posso fare niente }
end;
end;
procedure TExtDBListBox.ColumnVisible(ColIndex: integer; Value: boolean);
begin
Self.Columns[ColIndex].Visible:=Value;
end;
procedure TExtDBListBox.ColumnAlign(ColIndex: integer; Value: TAlignment);
begin
Self.Columns[ColIndex].Alignment:=Value;
end;
procedure TExtDBListBox.SetDataSourceList(DataSourceList: TDataSource);
begin
Self.MyDataSourceList:=DataSourceList;
end;
procedure TExtDBListBox.SetDataSourceIn(DataSourceIn: TDataSource);
begin
Self.MyDataSourceIn:=DataSourceIn;
end;
procedure TExtDBListBox.SetQuerySQLOut(SQLOut: TSQLQuery);
begin
Self.MySqlOut:=SqlOut;
end;
procedure TExtDBListBox.SetTitleColumns(TitleColumns: BOOLEAN);
begin
Self.Intestazione:=TitleColumns;
end;
procedure TExtDBListBox.SetFieldList(FieldList: string);
begin
Self.MyFieldList:=FieldList;
end;
procedure TExtDBListBox.SetFieldIn(FieldIn: string);
begin
Self.MyFieldIn:=FieldIn;
end;
procedure TExtDBListBox.SetFieldOutList(FieldOutList: string);
begin
Self.MyFieldOutList:=FieldOutList;
end;
procedure TExtDBListBox.SetFieldOutIn(FieldOutIn: string);
begin
Self.MyFieldOutIn:=FieldOutIn;
end;
procedure TExtDBListBox.SetAutoSizeColumns(ColumnsAutoSize: BOOLEAN);
begin
Self.MyAutoSizeColumns:=ColumnsAutoSize;
end;
procedure TExtDBListBox.Click;
var
Cont: integer;
begin
inherited Click;
if ((MyDataSourceList<>nil)AND(not MyDataSourceList.DataSet.EOF)) then
begin
MyDataSourceList.DataSet.First;
for Cont:=0 to Self.Row-1 do
MyDataSourceList.DataSet.Next;
end;
end;
procedure TExtDBListBox.DrawCell(aCol, aRow: Integer; aRect: TRect; aState: TGridDrawState);
var
app: integer;
app2: boolean;
begin
inherited DrawCell(aCol, aRow,aRect, aState);
Self.Canvas.Font.Color := clBlack; // colore di default
Self.Canvas.Brush.Color := clWhite;
if ((Intestazione = TRUE) AND (ARow = 0)) then // In primo luogo verificare se la riga o colonna fissa
begin
Self.Canvas.Brush.Color := clBtnFace;
end
else
begin
app:=Self.Row - 1;
app2:=ItemsSelected[Self.Row - 1];
if (ItemsSelected[aRow - 1] = True) then
begin // Will only color selected rows
Self.Canvas.Font.Color := clWhite;
Self.Canvas.Brush.Color := clBlue;
end;
end;
Self.Canvas.FillRect(aRect);
Self.Canvas.TextOut(aRect.Left, aRect.Top, Self.Cells[ACol, ARow]);
end;
procedure TExtDBListBox.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
mycol, myrow : Integer;
begin
inherited MouseUp(Button, Shift, X, Y);
Self.MouseToCell(X, Y, mycol, myrow); // This will tell us what cell (we need row) was selected
if ((row < Self.RowCount)) then // Again don't select fixed or blank row
if (((myrow > 0)AND(Intestazione=TRUE))OR(myrow >= 0)) then
if (ItemsSelected[Self.Row - 1] = True) then
begin
ItemsSelected[Self.Row - 1] := False;
Self.EliminaRecord();
end
else
begin
ItemsSelected[Self.Row - 1] := True;
Self.InserisciRecord();
end;
Self.Invalidate;
end;
procedure TExtDBListBox.ColoraComponente();
var
Cont: integer;
begin
Cont:=0;
MyDataSourceList.DataSet.First;
while not MyDataSourceList.DataSet.EOF do
begin
if Self.EsisteRecord(MyDataSourceIn.DataSet.FieldByName(MyFieldIn).Value,MyDataSourceList.DataSet.FieldByName(MyFieldList).Value)=TRUE then
begin
//colora la riga
ItemsSelected[Cont-1]:=TRUE;
end
else
begin
//non colorare la riga
ItemsSelected[Cont-1]:=FALSE;
end;
Inc(Cont);
MyDataSourceList.DataSet.Next;
end;
end;
function TExtDBListBox.EsisteRecord(ValIn: variant; ValoreList: variant): BOOLEAN;
begin
MySqlOut.First;
while not MySqlOut.EOF do
begin
if ((MySqlOut.FieldByName(MyFieldOutList).Value=ValoreList)AND(MySqlOut.FieldByName(MyFieldOutIn).Value=ValIn)) then
begin
EsisteRecord:=TRUE;
Exit;
end;
MySqlOut.Next;
end;
EsisteRecord:=FALSE;
end;
procedure TExtDBListBox.InserisciRecord();
begin
if Self.EsisteRecord(MyDataSourceIn.DataSet.FieldByName(MyFieldIn).Value, MyDataSourceList.DataSet.FieldByName(MyFieldList).Value)=FALSE then
begin
MySqlOut.Append;
MySqlOut.FieldByName(MyFieldOutIn).Value:=MyDataSourceIn.DataSet.FieldByName(MyFieldIn).Value;
MySqlOut.FieldByName(MyFieldOutList).Value:=MyDataSourceList.DataSet.FieldByName(MyFieldList).Value;
MySqlOut.Post;
MySqlOut.ApplyUpdates;
end;
end;
procedure TExtDBListBox.EliminaRecord();
begin
MySqlOut.First;
while not MySqlOut.EOF do
begin
if ((MySqlOut.FieldByName(MyFieldOutIn).Value=MyDataSourceIn.DataSet.FieldByName(MyFieldIn).Value)AND(MySqlOut.FieldByName(MyFieldOutList).Value=MyDataSourceList.DataSet.FieldByName(MyFieldList).Value)) then
begin
MySqlOut.Delete;
MySqlOut.ApplyUpdates;
Exit;
end
else
begin
MySqlOut.Next;
end;
end;
end;
end.