disqlite3_buffered_grid_form_main.pas
来自「DELPHI 访问SQLITE3 数据库的VCL控件」· PAS 代码 · 共 606 行 · 第 1/2 页
PAS
606 行
//------------------------------------------------------------------------------
function TfrmMain.ReadRow(const AID: Int64): PRowData;
begin
{ First try to retrieve the row from the cache. If it is already cached,
we are done and do not need to access the database. }
Result := FCache.GetItem(AID);
if not Assigned(Result) then
begin
{ If the row was not cached, add a new row to the cache. If the new count
exceeds MaxCount, the least recently used row will automatically be
reused for the new row. }
Result := FCache.AddItem(AID);
{ Bind the ID to the SQL statment's WHERE clause. }
sqlite3_check(sqlite3_bind_int64(FReadDataStmt, 1, AID), DB);
try
{ Execute the prepared statement ... }
if sqlite3_check(sqlite3_step(FReadDataStmt), DB) = SQLITE_ROW then
begin
{ ... and store the data to the row in the buffer. }
Result^.RandomText := sqlite3_column_str(FReadDataStmt, 0);
Result^.RandomInt := sqlite3_column_str(FReadDataStmt, 1);
end;
finally
{ Always reset the statement immediately after using it to avoid
conflicting database statments. }
sqlite3_check(sqlite3_reset(FReadDataStmt), DB);
end;
{ Report that we have accessed the database. }
Inc(FDatabaseReads);
StatusBar.Panels[1].Text := Format('%d reads', [FDatabaseReads]);
end;
end;
//------------------------------------------------------------------------------
procedure TfrmMain.WriteRow_Int(const AID: Int64; const AInt: Integer);
var
Stmt: TDISQLite3StatementHandle;
begin
sqlite3_check(sqlite3_prepare(
DB, // Database handle.
'UPDATE RandomTable SET RandomInt=? WHERE RowID=?;', // SQL to prepare.
-1, // Length of SQL or -1 if null-terminated.
@Stmt, // Pointer to store statement to.
nil), DB);
try
{ Invalidate this item in the cache to force the next draw to requrey the
database and return the most recent value. }
FCache.InvalidateItem(AID);
sqlite3_check(sqlite3_bind_int(Stmt, 1, AInt), DB);
sqlite3_check(sqlite3_bind_int64(Stmt, 2, AID), DB);
sqlite3_check(sqlite3_step(Stmt), DB);
finally
sqlite3_check(sqlite3_finalize(Stmt), DB);
end;
end;
//------------------------------------------------------------------------------
procedure TfrmMain.WriteRow_Text(const AID: Int64; const AText: AnsiString);
var
Stmt: TDISQLite3StatementHandle;
begin
sqlite3_check(sqlite3_prepare(
DB, // Database handle.
'UPDATE RandomTable SET RandomText=? WHERE RowID=?;', // SQL to prepare.
-1, // Length of SQL or -1 if null-terminated.
@Stmt, // Pointer to store statement to.
nil), DB);
try
{ Invalidate this item in the cache to force the next draw to requrey the
database and return the most recent value. }
FCache.InvalidateItem(AID);
sqlite3_check(sqlite3_bind_str(Stmt, 1, AText), DB);
sqlite3_check(sqlite3_bind_int64(Stmt, 2, AID), DB);
sqlite3_check(sqlite3_step(Stmt), DB);
finally
sqlite3_check(sqlite3_finalize(Stmt), DB);
end;
end;
//------------------------------------------------------------------------------
procedure TfrmMain.vt_BeforeCellPaint(
Sender: TBaseVirtualTree;
TargetCanvas: TCanvas;
Node: PVirtualNode;
Column: TColumnIndex;
CellRect: TRect);
const
Triangle: array[0..2] of TPoint =
((x: 4; y: 5), (x: 8; y: 9), (x: 4; y: 13));
begin
if Column = 0 then
begin
{ Simulate a fixed column by filling the main column with an edge similar to that of TCustomGrid. }
DrawEdge(TargetCanvas.Handle, CellRect, BDR_RAISEDINNER, BF_MIDDLE or BF_RECT or BF_SOFT);
if Node = Sender.FocusedNode then
begin
TargetCanvas.Brush.Color := clBlack;
TargetCanvas.Polygon(Triangle);
end;
end;
end;
//------------------------------------------------------------------------------
procedure TfrmMain.vt_FocusChanging(
Sender: TBaseVirtualTree;
OldNode, NewNode: PVirtualNode;
OldColumn, NewColumn: TColumnIndex;
var Allowed: Boolean);
begin
{ Don't allow focus to change to the fixed RowID column. }
Allowed := (NewColumn > NoColumn) and
not (coFixed in vt.Header.Columns[NewColumn].Options);
end;
//------------------------------------------------------------------------------
procedure TfrmMain.vt_GetText(
Sender: TBaseVirtualTree;
Node: PVirtualNode;
Column: TColumnIndex;
TextType: TVSTTextType;
var CellText: WideString);
var
NodeData: PNodeData;
begin
NodeData := Sender.GetNodeData(Node);
case Column of
0:
begin
CellText := IntToStr(NodeData^);
end;
1:
begin
CellText := ReadRow(NodeData^)^.RandomText;
end;
2:
begin
CellText := ReadRow(NodeData^)^.RandomInt;
end;
end;
end;
//------------------------------------------------------------------------------
procedure TfrmMain.vt_HeaderDragging(
Sender: TVTHeader;
Column: TColumnIndex;
var Allowed: Boolean);
begin
{ Don't allow dragging the fixed RowID column. }
Allowed := (Column > NoColumn) and
not (coFixed in Sender.Columns[Column].Options)
end;
//------------------------------------------------------------------------------
procedure TfrmMain.vt_MouseDown(
Sender: TObject;
Button: TMouseButton;
Shift: TShiftState;
x, y: Integer);
var
HitInfo: THitInfo;
begin
if tsLeftButtonDown in vt.TreeStates then
begin
vt.GetHitTestInfoAt(x, y, True, HitInfo);
if Assigned(HitInfo.HitNode) and
(HitInfo.HitColumn >= 0) and
(coFixed in vt.Header.Columns[HitInfo.HitColumn].Options) then
vt.FocusedNode := HitInfo.HitNode;
end;
end;
//------------------------------------------------------------------------------
procedure TfrmMain.vt_NewText(
Sender: TBaseVirtualTree;
Node: PVirtualNode;
Column: TColumnIndex;
NewText: WideString);
var
NodeData: PNodeData;
RowData: TRowData;
i: Integer;
begin
{ A record has been edited. Write the new text to the database. }
NodeData := Sender.GetNodeData(Node);
RowData := ReadRow(NodeData^)^;
case Column of
1:
WriteRow_Text(NodeData^, NewText);
2:
try
i := StrToInt(NewText);
WriteRow_Int(NodeData^, i);
except
on e: Exception do
ShowMessage(e.Message);
end;
else
Exit;
end;
end;
//------------------------------------------------------------------------------
procedure TfrmMain.btnAdd_Click(Sender: TObject);
var
NewID: Int64;
NewNode: PVirtualNode;
newnodedata: PNodeData;
begin
NewID := AddRow;
NewNode := vt.AddChild(nil);
newnodedata := vt.GetNodeData(NewNode);
newnodedata^ := NewID;
vt.EditNode(NewNode, 1);
end;
//------------------------------------------------------------------------------
procedure TfrmMain.btnDelete_Click(Sender: TObject);
var
FN: PVirtualNode;
NodeData: PNodeData;
begin
FN := vt.FocusedNode;
if Assigned(FN) then
begin
NodeData := vt.GetNodeData(FN);
DeleteRow(NodeData^);
vt.DeleteNode(FN, False);
end
else
ShowMessage('Please select a record to delete.');
end;
//------------------------------------------------------------------------------
procedure TfrmMain.btnEdit_Click(Sender: TObject);
var
FN: PVirtualNode;
begin
FN := vt.FocusedNode;
if Assigned(FN) then
vt.EditNode(FN, vt.FocusedColumn)
else
ShowMessage('Please select a cell to edit.');
end;
//------------------------------------------------------------------------------
procedure TfrmMain.btnReload_Click(Sender: TObject);
begin
LoadTable;
end;
//------------------------------------------------------------------------------
procedure TfrmMain.cbxMemory_Click(Sender: TObject);
begin
timer.Enabled := cbxMemory.Checked;
if timer.Enabled then
Timer_Timer(nil)
else
StatusBar.Panels[2].Text := '';
end;
//------------------------------------------------------------------------------
procedure TfrmMain.Timer_Timer(Sender: TObject);
begin
StatusBar.Panels[2].Text :=
Format('%d KB memory used', [(GetHeapStatus.TotalAllocated + 1) div 1024]);
end;
//------------------------------------------------------------------------------
// TOurCache
//------------------------------------------------------------------------------
procedure TOurCache.DoFinalizeItem(const AItem: Pointer);
begin
Finalize(PRowData(AItem)^);
end;
//------------------------------------------------------------------------------
procedure TOurCache.DoInitializeItem(const AItem: Pointer);
begin
FillChar(AItem^, ItemSize, 0);
end;
end.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?