Chapter 18 - Package MdDataPack |
Package Structure
| MdDsList.pas |
unit MdDsList;
interface
uses
DB, Classes, SysUtils, Windows, Forms, Contnrs, MdDsCustom;
type
TMdListDataSet = class (TMdCustomDataSet)
protected
FList: TObjectList;
procedure InternalPreOpen; override;
procedure InternalClose; override;
function InternalRecordCount: Integer; override;
procedure InternalLoadCurrentRecord (Buffer: PChar); override;
end;
implementation
procedure TMdListDataSet.InternalPreOpen;
begin
FList := TObjectList.Create (True);
FRecordSize := 4;
end;
procedure TMdListDataSet.InternalClose;
begin
FList.Free;
inherited;
end;
procedure TMdListDataSet.InternalLoadCurrentRecord (Buffer: PChar);
begin
PInteger (Buffer)^ := fCurrentRecord;
with PMdRecInfo(Buffer + FRecordSize)^ do
begin
BookmarkFlag := bfCurrent;
Bookmark := fCurrentRecord;
end;
end;
function TMdListDataSet.InternalRecordCount: Integer;
begin
Result := fList.Count;
end;
end.
| MdDsCustom.pas |
unit MdDsCustom;
interface
uses
SysUtils, Classes, Db;
type
EMdDataSetError = class (Exception);
TMdRecInfo = record
Bookmark: Longint;
BookmarkFlag: TBookmarkFlag;
end;
PMdRecInfo = ^TMdRecInfo;
TMdCustomDataSet = class(TDataSet)
protected
FIsTableOpen: Boolean;
FRecordSize,
FRecordBufferSize,
FCurrentRecord,
BofCrack,
EofCrack: Integer;
procedure InternalOpen; override;
procedure InternalClose; override;
function IsCursorOpen: Boolean; override;
function InternalRecordCount: Integer; virtual; abstract;
procedure InternalPreOpen; virtual;
procedure InternalAfterOpen; virtual;
procedure InternalLoadCurrentRecord(Buffer: PChar); virtual; abstract;
function AllocRecordBuffer: PChar; override;
procedure InternalInitRecord(Buffer: PChar); override;
procedure FreeRecordBuffer(var Buffer: PChar); override;
function GetRecordSize: Word; override;
function GetRecord(Buffer: PChar; GetMode: TGetMode;
DoCheck: Boolean): TGetResult; override;
procedure InternalFirst; override;
procedure InternalLast; override;
function GetRecNo: Longint; override;
function GetRecordCount: Longint; override;
procedure SetRecNo(Value: Integer); override;
procedure InternalGotoBookmark(Bookmark: Pointer); override;
procedure InternalSetToRecord(Buffer: PChar); override;
procedure SetBookmarkData(Buffer: PChar; Data: Pointer); override;
procedure GetBookmarkData(Buffer: PChar; Data: Pointer); override;
procedure SetBookmarkFlag(Buffer: PChar; Value: TBookmarkFlag); override;
function GetBookmarkFlag(Buffer: PChar): TBookmarkFlag; override;
procedure InternalDelete; override;
procedure InternalAddRecord(Buffer: Pointer; Append: Boolean); override;
procedure InternalPost; override;
procedure InternalHandleException; override;
published
property Active;
property BeforeOpen;
property AfterOpen;
property BeforeClose;
property AfterClose;
property BeforeInsert;
property AfterInsert;
property BeforeEdit;
property AfterEdit;
property BeforePost;
property AfterPost;
property BeforeCancel;
property AfterCancel;
property BeforeDelete;
property AfterDelete;
property BeforeScroll;
property AfterScroll;
property OnCalcFields;
property OnDeleteError;
property OnEditError;
property OnFilterRecord;
property OnNewRecord;
property OnPostError;
end;
implementation
procedure TMDCustomDataSet.InternalOpen;
begin
InternalPreOpen;
InternalInitFieldDefs;
if DefaultFields then
CreateFields;
BindFields (True);
InternalAfterOpen;
BofCrack := -1;
EofCrack := InternalRecordCount;
FCurrentRecord := BofCrack;
FRecordBufferSize := FRecordSize + sizeof (TMdRecInfo);
BookmarkSize := sizeOf (Integer);
FIsTableOpen := True;
end;
procedure TMDCustomDataSet.InternalClose;
begin
BindFields (False);
if DefaultFields then
DestroyFields;
FIsTableOpen := False;
end;
function TMDCustomDataSet.IsCursorOpen: Boolean;
begin
Result := FIsTableOpen;
end;
procedure TMDCustomDataSet.InternalGotoBookmark (Bookmark: Pointer);
var
ReqBookmark: Integer;
begin
ReqBookmark := PInteger (Bookmark)^;
if (ReqBookmark >= 0) and (ReqBookmark < InternalRecordCount) then
FCurrentRecord := ReqBookmark
else
raise EMdDataSetError.Create ('Bookmark ' +
IntToStr (ReqBookmark) + ' not found');
end;
procedure TMDCustomDataSet.InternalSetToRecord (Buffer: PChar);
var
ReqBookmark: Integer;
begin
ReqBookmark := PMdRecInfo(Buffer + FRecordSize).Bookmark;
InternalGotoBookmark (@ReqBookmark);
end;
function TMDCustomDataSet.GetBookmarkFlag (
Buffer: PChar): TBookmarkFlag;
begin
Result := PMdRecInfo(Buffer + FRecordSize).BookmarkFlag;
end;
procedure TMDCustomDataSet.SetBookmarkFlag (Buffer: PChar;
Value: TBookmarkFlag);
begin
PMdRecInfo(Buffer + FRecordSize).BookmarkFlag := Value;
end;
procedure TMDCustomDataSet.InternalFirst;
begin
FCurrentRecord := BofCrack;
end;
procedure TMDCustomDataSet.InternalLast;
begin
EofCrack := InternalRecordCount;
FCurrentRecord := EofCrack;
end;
procedure TMDCustomDataSet.GetBookmarkData (
Buffer: PChar; Data: Pointer);
begin
PInteger(Data)^ :=
PMdRecInfo(Buffer + FRecordSize).Bookmark;
end;
procedure TMDCustomDataSet.SetBookmarkData (
Buffer: PChar; Data: Pointer);
begin
PMdRecInfo(Buffer + FRecordSize).Bookmark :=
PInteger(Data)^;
end;
function TMDCustomDataSet.GetRecordCount: Longint;
begin
CheckActive;
Result := InternalRecordCount;
end;
function TMDCustomDataSet.GetRecNo: Longint;
begin
UpdateCursorPos;
if FCurrentRecord < 0 then
Result := 1
else
Result := FCurrentRecord + 1;
end;
procedure TMDCustomDataSet.SetRecNo(Value: Integer);
begin
CheckBrowseMode;
if (Value >= 1) and (Value <= InternalRecordCount) then
begin
FCurrentRecord := Value - 1;
Resync([]);
end;
end;
function TMDCustomDataSet.GetRecord(Buffer: PChar;
GetMode: TGetMode; DoCheck: Boolean): TGetResult;
begin
Result := grOK;
case GetMode of
gmNext:
if FCurrentRecord < InternalRecordCount - 1 then
Inc (FCurrentRecord)
else
Result := grEOF;
gmPrior:
if FCurrentRecord > 0 then
Dec (FCurrentRecord)
else
Result := grBOF;
gmCurrent:
if FCurrentRecord >= InternalRecordCount then
Result := grError;
end;
if Result = grOK then
InternalLoadCurrentRecord (Buffer)
else
if (Result = grError) and DoCheck then
raise EMdDataSetError.Create ('GetRecord: Invalid record');
end;
procedure TMDCustomDataSet.InternalInitRecord(Buffer: PChar);
begin
FillChar(Buffer^, FRecordBufferSize, 0);
end;
procedure TMDCustomDataSet.FreeRecordBuffer (var Buffer: PChar);
begin
FreeMem (Buffer);
end;
function TMDCustomDataSet.GetRecordSize: Word;
begin
Result := FRecordSize;
end;
function TMDCustomDataSet.AllocRecordBuffer: PChar;
begin
GetMem (Result, FRecordBufferSize);
end;
procedure TMDCustomDataSet.InternalDelete;
begin
raise EMdDataSetError.Create ('Delete: Operation not supported');
end;
procedure TMDCustomDataSet.InternalHandleException;
begin
end;
procedure TMdCustomDataSet.InternalAddRecord(Buffer: Pointer;
Append: Boolean);
begin
raise EMdDataSetError.Create ('AddRecord: Operation not supported');
end;
procedure TMdCustomDataSet.InternalPost;
begin
raise EMdDataSetError.Create ('Post: Operation not supported');
end;
procedure TMdCustomDataSet.InternalAfterOpen;
begin
end;
procedure TMdCustomDataSet.InternalPreOpen;
begin
end;
end.
| MdDsDir.pas |
unit MdDsDir;
interface
uses
SysUtils, Classes, Db, MdDsList, MdDsCustom;
type
TMdDirDataset = class(TMdListDataSet)
private
FDirectory: string;
procedure SetDirectory(const NewDirectory: string);
protected
procedure InternalInitFieldDefs; override;
procedure SetFieldData(Field: TField; Buffer: Pointer); override;
function GetCanModify: Boolean; override;
procedure InternalAfterOpen; override;
public
function GetFieldData(Field: TField; Buffer: Pointer): Boolean; override;
published
property Directory: string read FDirectory write SetDirectory;
end;
TFileData = class
public
ShortFileName: string;
Time: TDateTime;
Size: Integer;
Attr: Integer;
constructor Create (var FileInfo: TSearchRec);
end;
procedure Register;
implementation
uses
TypInfo, Dialogs, Windows, Forms, Controls;
procedure TMdDirDataset.SetDirectory(const NewDirectory: string);
begin
if FIsTableOpen then
raise Exception.Create ('Cannot change directory while dataset is open');
fDirectory := NewDirectory;
end;
procedure TMdDirDataset.InternalAfterOpen;
var
Attr: Integer;
FileInfo: TSearchRec;
FileData: TFileData;
begin
Attr := faAnyFile;
FList.Clear;
if SysUtils.FindFirst(fDirectory, Attr, FileInfo) = 0 then
repeat
FileData := TFileData.Create (FileInfo);
FList.Add (FileData);
until SysUtils.FindNext(FileInfo) <> 0;
SysUtils.FindClose(FileInfo);
end;
procedure TMdDirDataset.InternalInitFieldDefs;
begin
if fDirectory = '' then
raise EMdDataSetError.Create ('Missing directory');
FieldDefs.Clear;
FieldDefs.Add ('FileName', ftString, 40, True);
FieldDefs.Add ('TimeStamp', ftDateTime);
FieldDefs.Add ('Size', ftInteger);
FieldDefs.Add ('Attributes', ftString, 3);
FieldDefs.Add ('Folder', ftBoolean);
end;
function DateTimeToNative(DataType: TFieldType; Data: TDateTime): TDateTimeRec;
var
TimeStamp: TTimeStamp;
begin
TimeStamp := DateTimeToTimeStamp(Data);
case DataType of
ftDate: Result.Date := TimeStamp.Date;
ftTime: Result.Time := TimeStamp.Time;
else
Result.DateTime := TimeStampToMSecs(TimeStamp);
end;
end;
function TMdDirDataset.GetFieldData (
Field: TField; Buffer: Pointer): Boolean;
var
FileData: TFileData;
Bool1: WordBool;
strAttr: string;
t: TDateTimeRec;
begin
FileData := fList [PInteger(ActiveBuffer)^] as TFileData;
case Field.Index of
0:
StrCopy (Buffer, pchar(FileData.ShortFileName));
1:
begin
t := DateTimeToNative (ftdatetime, FileData.Time);
Move (t, Buffer^, sizeof (TDateTime));
end;
2:
Move (FileData.Size, Buffer^, sizeof (Integer));
3: begin
strAttr := ' ';
if (FileData.Attr and SysUtils.faReadOnly) > 0 then
strAttr [1] := 'R';
if (FileData.Attr and SysUtils.faSysFile) > 0 then
strAttr [2] := 'S';
if (FileData.Attr and SysUtils.faHidden) > 0 then
strAttr [3] := 'H';
StrCopy (Buffer, pchar(strAttr));
end;
4: begin
Bool1 := FileData.Attr and SysUtils.faDirectory > 0;
Move (Bool1, Buffer^, sizeof (WordBool));
end;
end;
Result := True;
end;
procedure TMdDirDataset.SetFieldData(Field: TField; Buffer: Pointer);
begin
end;
function TMdDirDataset.GetCanModify: Boolean;
begin
Result := False;
end;
constructor TFileData.Create(var FileInfo: TSearchRec);
begin
ShortFileName := FileInfo.Name;
Time := FileDateToDateTime (FileInfo.Time);
Size := FileInfo.Size;
Attr := FileInfo.Attr;
end;
procedure Register;
begin
RegisterComponents ('Md', [TMdDirDataset]);
end;
end.
| MdDsStream.pas |
unit MdDsStream;
interface
uses
Classes, Db, MdDsCustom;
type
TMdDataFileHeader = record
VersionNumber: Integer;
RecordSize: Integer;
RecordCount: Integer;
end;
TMdDataSetStream = class(TMdCustomDataSet)
private
procedure SetTableName(const Value: string);
protected
FDataFileHeader: TMdDataFileHeader;
FDataFileHeaderSize,
FRecordCount: Integer;
FStream: TStream;
FTableName: string;
FFieldOffset: TList;
protected
procedure InternalPreOpen; override;
procedure InternalAfterOpen; override;
procedure InternalClose; override;
procedure InternalInitFieldDefs; override;
procedure InternalAddRecord(Buffer: Pointer; Append: Boolean); override;
procedure InternalPost; override;
procedure SetFieldData(Field: TField; Buffer: Pointer); override;
function InternalRecordCount: Integer; override;
procedure InternalLoadCurrentRecord(Buffer: PChar); override;
public
procedure CreateTable;
function GetFieldData(Field: TField; Buffer: Pointer): Boolean; override;
published
property TableName: string read FTableName write SetTableName;
end;
procedure Register;
implementation
uses
TypInfo, IniFiles, SysUtils;
const
HeaderVersion = 10;
procedure TMdDataSetStream.InternalPreOpen;
begin
FDataFileHeaderSize := sizeOf (TMdDataFileHeader);
if not FileExists (FTableName) then
raise EMdDataSetError.Create ('Open: Table file not found');
FStream := TFileStream.Create (FTableName, fmOpenReadWrite);
FStream.ReadBuffer (FDataFileHeader, FDataFileHeaderSize);
if FDataFileHeader.VersionNumber <> HeaderVersion then
raise EMdDataSetError.Create ('Illegal File Version');
FRecordCount := FDataFileHeader.RecordCount;
end;
procedure TMdDataSetStream.InternalAfterOpen;
begin
if FDataFileHeader.RecordSize <> FRecordSize then
raise EMdDataSetError.Create ('File record size mismatch');
if (FDataFileHeaderSize + FRecordCount * FRecordSize) <> FStream.Size then
raise EMdDataSetError.Create ('InternalOpen: Invalid Record Size');
end;
procedure TMdDataSetStream.InternalInitFieldDefs;
var
IniFileName, FieldName: string;
IniFile: TIniFile;
nFields, I, TmpFieldOffset, nSize: Integer;
FieldType: TFieldType;
begin
FFieldOffset := TList.Create;
FieldDefs.Clear;
TmpFieldOffset := 0;
IniFilename := ChangeFileExt(FTableName, '.ini');
Inifile := TIniFile.Create (IniFilename);
try
nFields := IniFile.ReadInteger ('Fields', 'Number', 0);
if nFields = 0 then
raise EMdDataSetError.Create ('InitFieldsDefs: 0 fields?');
for I := 1 to nFields do
begin
FieldType := TFieldType (GetEnumValue (
TypeInfo (TFieldType),
IniFile.ReadString (
'Field' + IntToStr (I), 'Type', '')));
FieldName := IniFile.ReadString (
'Field' + IntToStr (I), 'Name', '');
if FieldName = '' then
raise EMdDataSetError.Create (
'InitFieldsDefs: No name for field ' +
IntToStr (I));
nSize := IniFile.ReadInteger (
'Field' + IntToStr (I), 'Size', 0);
FieldDefs.Add (FieldName,
FieldType, nSize, False);
FFieldOffset.Add (Pointer (TmpFieldOffset));
case FieldType of
ftString:
Inc (TmpFieldOffset, nSize + 1);
ftBoolean, ftSmallInt, ftWord:
Inc (TmpFieldOffset, 2);
ftInteger, ftDate, ftTime:
Inc (TmpFieldOffset, 4);
ftFloat, ftCurrency, ftDateTime:
Inc (TmpFieldOffset, 8);
else
raise EMdDataSetError.Create (
'InitFieldsDefs: Unsupported field type');
end;
end;
finally
IniFile.Free;
end;
FRecordSize := TmpFieldOffset;
end;
procedure TMdDataSetStream.InternalClose;
begin
if (FDataFileHeader.RecordCount <> FRecordCount) or
(FDataFileHeader.RecordSize = 0) then
begin
FDataFileHeader.RecordSize := FRecordSize;
FDataFileHeader.RecordCount := FRecordCount;
if Assigned (FStream) then
begin
FStream.Seek (0, soFromBeginning);
FStream.WriteBuffer (
FDataFileHeader, FDataFileHeaderSize);
end;
end;
FFieldOffset.Free;
FStream.Free;
inherited InternalClose;
end;
procedure TMdDataSetStream.CreateTable;
begin
CheckInactive;
InternalInitFieldDefs;
if FileExists (FTableName) then
raise EMdDataSetError.Create ('File ' + FTableName + ' already exists');
FStream := TFileStream.Create (FTableName,
fmCreate or fmShareExclusive);
try
FDataFileHeader.VersionNumber := HeaderVersion;
FDataFileHeader.RecordSize := 0;
FDataFileHeader.RecordCount := 0;
FStream.WriteBuffer (
FDataFileHeader, FDataFileHeaderSize);
finally
FStream.Free;
end;
end;
procedure TMdDataSetStream.InternalLoadCurrentRecord (Buffer: PChar);
begin
FStream.Position := FDataFileHeaderSize +
FRecordSize * FCurrentRecord;
FStream.ReadBuffer (Buffer^, FRecordSize);
with PMdRecInfo(Buffer + FRecordSize)^ do
begin
BookmarkFlag := bfCurrent;
Bookmark := FCurrentRecord;
end;
end;
procedure TMdDataSetStream.InternalPost;
begin
CheckActive;
if State = dsEdit then
begin
FStream.Position := FDataFileHeaderSize +
FRecordSize * FCurrentRecord;
FStream.WriteBuffer (ActiveBuffer^, FRecordSize);
end
else
begin
InternalLast;
FStream.Seek (0, soFromEnd);
FStream.WriteBuffer (ActiveBuffer^, FRecordSize);
Inc (FRecordCount);
end;
end;
procedure TMdDataSetStream.InternalAddRecord(
Buffer: Pointer; Append: Boolean);
begin
InternalLast;
FStream.Seek (0, soFromEnd);
FStream.WriteBuffer (ActiveBuffer^, FRecordSize);
Inc (FRecordCount);
end;
function TMdDataSetStream.GetFieldData (
Field: TField; Buffer: Pointer): Boolean;
var
FieldOffset: Integer;
Ptr: PChar;
begin
Result := False;
if not IsEmpty and (Field.FieldNo > 0) then
begin
FieldOffset := Integer (
FFieldOffset [Field.FieldNo - 1]);
Ptr := ActiveBuffer;
Inc (Ptr, FieldOffset);
if Assigned (Buffer) then
Move (Ptr^, Buffer^, Field.DataSize);
Result := True;
if (Field is TDateTimeField) and (PInteger(Ptr)^ = 0) then
Result := False;
end;
end;
procedure TMdDataSetStream.SetFieldData(Field: TField; Buffer: Pointer);
var
FieldOffset: Integer;
Ptr: PChar;
begin
if Field.FieldNo >= 0 then
begin
FieldOffset := Integer (
FFieldOffset [Field.FieldNo - 1]);
Ptr := ActiveBuffer;
Inc (Ptr, FieldOffset);
if Assigned (Buffer) then
Move (Buffer^, Ptr^, Field.DataSize)
else
raise Exception.Create (
'Very bad error in TMdDataSetStream.SetField data');
DataEvent (deFieldChange, Longint(Field));
end;
end;
procedure Register;
begin
RegisterComponents('Md', [TMdDataSetStream]);
end;
function TMdDataSetStream.InternalRecordCount: Integer;
begin
Result := FRecordCount;
end;
procedure TMdDataSetStream.SetTableName(const Value: string);
begin
if IsCursorOpen then
if csDesigning in ComponentState then
Close
else
raise Exception.Create ('Cannot assing an open dataset to a new file');
FTableName := Value;
end;
end.
| MdDbGrid.pas |
unit MdDbGrid;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Grids, DBGrids, Db;
type
TMdDbGrid = class(TDbGrid)
private
FLinesPerRow: Integer;
procedure SetLinesPerRow (Value: Integer);
protected
procedure DrawColumnCell(const Rect: TRect; DataCol: Integer;
Column: TColumn; State: TGridDrawState); override;
procedure LayoutChanged; override;
public
constructor Create (AOwner: TComponent); override;
published
property LinesPerRow: Integer
read FLinesPerRow write SetLinesPerRow
default 1;
end;
procedure Register;
implementation
constructor TMdDbGrid.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FLinesPerRow := 1;
end;
procedure TMdDbGrid.LayOutChanged;
var
PixelsPerRow, PixelsTitle, I: Integer;
begin
inherited LayOutChanged;
Canvas.Font := Font;
PixelsPerRow := Canvas.TextHeight('Wg') + 3;
if dgRowLines in Options then
Inc (PixelsPerRow, GridLineWidth);
Canvas.Font := TitleFont;
PixelsTitle := Canvas.TextHeight('Wg') + 4;
if dgRowLines in Options then
Inc (PixelsTitle, GridLineWidth);
RowCount := 1 + (Height - PixelsTitle) div
(PixelsPerRow * FLinesPerRow);
DefaultRowHeight := PixelsPerRow * FLinesPerRow;
RowHeights [0] := PixelsTitle;
for I := 1 to RowCount - 1 do
RowHeights [I] := PixelsPerRow * FLinesPerRow;
end;
procedure TMdDbGrid.DrawColumnCell(const Rect: TRect;
DataCol: Integer; Column: TColumn; State: TGridDrawState);
var
Bmp: TBitmap;
OutRect: TRect;
begin
if FLinesPerRow = 1 then
inherited DrawColumnCell(Rect, DataCol, Column, State)
else
begin
Canvas.FillRect (Rect);
OutRect := Rect;
InflateRect (OutRect, -2, -2);
if Column.Field is TGraphicField then
begin
Bmp := TBitmap.Create;
try
Bmp.Assign (Column.Field);
Canvas.StretchDraw (OutRect, Bmp);
finally
Bmp.Free;
end;
end
else if Column.Field is TMemoField then
begin
DrawText (Canvas.Handle,
PChar (Column.Field.AsString),
Length (Column.Field.AsString),
OutRect, dt_WordBreak or dt_NoPrefix)
end
else
DrawText (Canvas.Handle,
PChar (Column.Field.DisplayText),
Length (Column.Field.DisplayText),
OutRect, dt_vcenter or dt_SingleLine or dt_NoPrefix);
end;
end;
procedure TMdDbGrid.SetLinesPerRow(Value: Integer);
begin
if Value <> FLinesPerRow then
begin
FLinesPerRow := Value;
LayoutChanged;
end;
end;
procedure Register;
begin
RegisterComponents('Md', [TMdDbGrid]);
end;
end.
| MdRView.pas |
unit MdRView;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Grids, DB, StdCtrls;
type
TMdRecordView = class(TCustomGrid)
private
FDataLink: TDataLink;
function GetDataSource: TDataSource;
procedure SetDataSource (Value: TDataSource);
protected
procedure DrawCell(ACol, ARow: Longint; ARect: TRect;
AState: TGridDrawState); override;
procedure ColWidthsChanged; override;
procedure RowHeightsChanged; override;
public
constructor Create (AOwner: TComponent); override;
destructor Destroy; override;
procedure SetBounds (ALeft, ATop, AWidth,
AHeight: Integer); override;
property Canvas;
property Col;
property ColWidths;
property EditorMode;
property GridHeight;
property GridWidth;
property LeftCol;
property Selection;
property Row;
property RowHeights;
property TabStops;
property TopRow;
published
property DataSource: TDataSource
read GetDataSource write SetDataSource;
property Align;
property BorderStyle;
property Color;
property Ctl3D;
property DefaultColWidth;
property DefaultRowHeight;
property DragCursor;
property DragMode;
property Enabled;
property FixedColor;
property Font;
property GridLineWidth;
property ParentColor;
property ParentCtl3D;
property ParentFont;
property ParentShowHint;
property PopupMenu;
property ShowHint;
property TabOrder;
property TabStop;
property Visible;
property VisibleColCount;
property VisibleRowCount;
property OnClick;
property OnDblClick;
property OnDragDrop;
property OnDragOver;
property OnEndDrag;
property OnEnter;
property OnExit;
property OnKeyDown;
property OnKeyPress;
property OnKeyUp;
property OnMouseDown;
property OnMouseMove;
property OnMouseUp;
property OnStartDrag;
end;
procedure Register;
implementation
type
TMdRecordLink = class (TDataLink)
private
RView: TMdRecordView;
public
constructor Create (View: TMdRecordView);
procedure ActiveChanged; override;
procedure RecordChanged(Field: TField); override;
end;
constructor TMdRecordLink.Create (View: TMdRecordView);
begin
inherited Create;
RView := View;
end;
procedure TMdRecordLink.ActiveChanged;
var
I: Integer;
begin
if Assigned (DataSet) then
begin
RView.RowCount := DataSet.FieldCount;
for I := 0 to DataSet.FieldCount - 1 do
if DataSet.Fields [I] is TBlobField then
RView.RowHeights [I] := RView.DefaultRowHeight * 2;
RView.Invalidate;
end;
end;
procedure TMdRecordLink.RecordChanged;
begin
inherited;
RView.Invalidate;
end;
constructor TMdRecordView.Create (AOwner: TComponent);
begin
FDataLink := TMdRecordLink.Create (self);
inherited Create (AOwner);
RowCount := 2;
ColCount := 2;
FixedCols := 1;
FixedRows := 0;
Options := [goFixedVertLine, goFixedHorzLine,
goVertLine, goHorzLine, goRowSizing, goColSizing];
DefaultDrawing := False;
ScrollBars := ssVertical;
end;
destructor TMdRecordView.Destroy;
begin
FDataLink.Free;
FDataLink := nil;
inherited Destroy;
end;
procedure TMdRecordView.SetBounds (ALeft, ATop,
AWidth, AHeight: Integer);
begin
inherited;
ColWidths [1] := Width - ColWidths [0] -
GridLineWidth * 3 -
GetSystemMetrics (sm_CXVScroll)
- 2;
end;
procedure TMdRecordView.ColWidthsChanged;
begin
ColWidths [1] := Width - ColWidths [0] -
GridLineWidth * 3 -
GetSystemMetrics (sm_CXVScroll)
- 2;
end;
procedure TMdRecordView.DrawCell(ACol, ARow: Longint;
ARect: TRect; AState: TGridDrawState);
var
Text: string;
CurrField: TField;
Bmp: TBitmap;
begin
CurrField := nil;
Text := '[]';
if (ACol = 0) then
Canvas.Brush.Color := FixedColor
else
Canvas.Brush.Color := Color;
Canvas.FillRect (ARect);
InflateRect (ARect, -2, -2);
if (FDataLink.DataSource <> nil) and
FDataLink.Active then
begin
CurrField := FDataLink.DataSet.Fields[ARow];
if ACol = 0 then
Text := CurrField.DisplayName
else if CurrField is TMemoField then
Text := TMemoField (CurrField).AsString
else
Text := CurrField.DisplayText;
end;
if (ACol = 1) and (CurrField is TGraphicField) then
begin
Bmp := TBitmap.Create;
try
Bmp.Assign (CurrField);
Canvas.StretchDraw (ARect, Bmp);
finally
Bmp.Free;
end;
end
else if (ACol = 1) and (CurrField is TMemoField) then
begin
DrawText (Canvas.Handle,
PChar (Text), Length (Text),
ARect, dt_WordBreak or dt_NoPrefix)
end
else
DrawText (Canvas.Handle,
PChar (Text), Length (Text), ARect,
dt_vcenter or dt_SingleLine or dt_NoPrefix);
if gdFocused in AState then
Canvas.DrawFocusRect (ARect);
end;
function TMdRecordView.GetDataSource: TDataSource;
begin
Result := FDataLink.DataSource;
end;
procedure TMdRecordView.SetDataSource (Value: TDataSource);
begin
FDataLink.DataSource := Value;
end;
procedure Register;
begin
RegisterComponents('Md', [TMdRecordView]);
end;
procedure TMdRecordView.RowHeightsChanged;
begin
inherited;
(FDataLink as TMdRecordLink).ActiveChanged;
end;
end.
| MdRepPr.pas |
unit MdRepPr;
interface
uses
Windows, Messages, SysUtils, Classes, Controls, Forms,
ComCtrls, DB, DBCtrls;
type
TMdDbRepProgress = class(TProgressBar)
private
FDataLink: TFieldDataLink;
FPaintControl: TPaintControl;
function GetDataField: string;
procedure SetDataField (Value: string);
function GetDataSource: TDataSource;
procedure SetDataSource (Value: TDataSource);
function GetField: TField;
procedure CmGetDataLink (var Msg: TMessage);
message cm_GetDataLink;
procedure WmPaint (var Msg: TWmPaint);
message wm_Paint;
function GetPos: Integer;
protected
procedure WndProc(var Message: TMessage); override;
procedure DataChange (Sender: TObject);
public
constructor Create (AOwner: TComponent); override;
destructor Destroy; override;
property Field: TField read GetField;
published
property DataField: string
read GetDataField write SetDataField;
property DataSource: TDataSource
read GetDataSource write SetDataSource;
end;
procedure Register;
implementation
uses
Dialogs, CommCtrl, DbCGrids;
constructor TMdDbRepProgress.Create (AOwner: TComponent);
begin
inherited Create (AOwner);
FDataLink := TFieldDataLink.Create;
FDataLink.Control := self;
FDataLink.OnDataChange := DataChange;
ControlStyle := ControlStyle + [csReplicatable];
FPaintControl := TPaintControl.Create(
self, PROGRESS_CLASS);
end;
destructor TMdDbRepProgress.Destroy;
begin
FDataLink.Free;
FDataLink := nil;
FPaintControl.Free;
inherited Destroy;
end;
function TMdDbRepProgress.GetDataField: string;
begin
Result := FDataLink.FieldName;
end;
procedure TMdDbRepProgress.SetDataField (Value: string);
begin
FDataLink.FieldName := Value;
end;
function TMdDbRepProgress.GetDataSource: TDataSource;
begin
Result := FDataLink.DataSource;
end;
procedure TMdDbRepProgress.SetDataSource (Value: TDataSource);
begin
FDataLink.DataSource := Value;
end;
function TMdDbRepProgress.GetField: TField;
begin
Result := FDataLink.Field;
end;
procedure TMdDbRepProgress.DataChange (Sender: TObject);
begin
SendMessage(Handle, Wm_SetRedraw, 0, 0);
Position := GetPos;
SendMessage(Handle, Wm_SetRedraw, 1, 0);
if HandleAllocated then
RedrawWindow (Handle, nil, 0,
RDW_INVALIDATE or RDW_ERASE or RDW_FRAME);
end;
function TMdDbRepProgress.GetPos;
begin
if (FDataLink.Field <> nil) and
(FDataLink.Field is TNumericField) then
Result := FDataLink.Field.AsInteger
else
Result := Min;
end;
procedure TMdDbRepProgress.CmGetDataLink (var Msg: TMessage);
begin
Msg.Result := Integer (fDataLink);
end;
procedure TMdDbRepProgress.WmPaint (var Msg: TWmPaint);
begin
if not (csPaintCopy in ControlState) then
inherited
else
begin
SendMessage(FPaintControl.Handle, Wm_SetRedraw, 0, 0);
SendMessage(FPaintControl.Handle, PBM_SETRANGE32, Min, Max);
SendMessage(FPaintControl.Handle, PBM_SETPOS, GetPos, 0);
SendMessage(FPaintControl.Handle, PBM_SETSTEP, Step, 0);
SendMessage(FPaintControl.Handle, Wm_SetRedraw, 1, 0);
SendMessage(FPaintControl.Handle,
wm_Paint, Msg.DC, 0);
end;
end;
procedure TMdDbRepProgress.WndProc(var Message: TMessage);
begin
with Message do
if (Msg = WM_CREATE) or
(Msg = WM_WINDOWPOSCHANGED) then
FPaintControl.DestroyHandle;
inherited;
end;
procedure Register;
begin
RegisterComponents('Md', [TMdDbRepProgress]);
end;
end.
| MdProgr.pas |
unit MdProgr;
interface
uses
Windows, Messages, SysUtils, Classes, Controls, Forms,
ComCtrls, DB, DBCtrls;
type
TMdDbProgress = class(TProgressBar)
private
FDataLink: TFieldDataLink;
function GetDataField: string;
procedure SetDataField (Value: string);
function GetDataSource: TDataSource;
procedure SetDataSource (Value: TDataSource);
function GetField: TField;
protected
procedure DataChange (Sender: TObject);
public
constructor Create (AOwner: TComponent); override;
destructor Destroy; override;
property Field: TField read GetField;
published
property DataField: string
read GetDataField write SetDataField;
property DataSource: TDataSource
read GetDataSource write SetDataSource;
end;
procedure Register;
implementation
uses
Dialogs, CommCtrl, DbCGrids;
constructor TMdDbProgress.Create (AOwner: TComponent);
begin
inherited Create (AOwner);
FDataLink := TFieldDataLink.Create;
FDataLink.Control := self;
FDataLink.OnDataChange := DataChange;
end;
destructor TMdDbProgress.Destroy;
begin
FDataLink.Free;
FDataLink := nil;
inherited Destroy;
end;
function TMdDbProgress.GetDataField: string;
begin
Result := FDataLink.FieldName;
end;
procedure TMdDbProgress.SetDataField (Value: string);
begin
FDataLink.FieldName := Value;
end;
function TMdDbProgress.GetDataSource: TDataSource;
begin
Result := FDataLink.DataSource;
end;
procedure TMdDbProgress.SetDataSource (Value: TDataSource);
begin
FDataLink.DataSource := Value;
end;
function TMdDbProgress.GetField: TField;
begin
Result := FDataLink.Field;
end;
procedure TMdDbProgress.DataChange (Sender: TObject);
begin
if (FDataLink.Field <> nil) and
(FDataLink.Field is TNumericField) then
Position := FDataLink.Field.AsInteger
else
Position := Min;
end;
procedure Register;
begin
RegisterComponents('Md', [TMdDbProgress]);
end;
end.
| MdTrack.pas |
unit MdTrack;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ComCtrls, DB, DBCtrls;
type
TMdDbTrack = class(TTrackBar)
private
FDataLink: TFieldDataLink;
function GetDataField: string;
procedure SetDataField (Value: string);
function GetDataSource: TDataSource;
procedure SetDataSource (Value: TDataSource);
function GetField: TField;
procedure CNHScroll(var Message: TWMHScroll); message CN_HSCROLL;
procedure CNVScroll(var Message: TWMVScroll); message CN_VSCROLL;
procedure CMExit(var Message: TCMExit); message CM_EXIT;
protected
procedure DataChange (Sender: TObject);
procedure UpdateData (Sender: TObject);
procedure ActiveChange (Sender: TObject);
public
constructor Create (AOwner: TComponent); override;
destructor Destroy; override;
property Field: TField read GetField;
published
property DataField: string
read GetDataField write SetDataField;
property DataSource: TDataSource
read GetDataSource write SetDataSource;
end;
procedure Register;
implementation
constructor TMdDbTrack.Create (AOwner: TComponent);
begin
inherited Create (AOwner);
FDataLink := TFieldDataLink.Create;
FDataLink.Control := self;
FDataLink.OnDataChange := DataChange;
FDataLink.OnUpdateData := UpdateData;
FDataLink.OnActiveChange := ActiveChange;
Enabled := False;
end;
destructor TMdDbTrack.Destroy;
begin
FDataLink.Free;
FDataLink := nil;
inherited Destroy;
end;
function TMdDbTrack.GetDataField: string;
begin
Result := FDataLink.FieldName;
end;
procedure TMdDbTrack.SetDataField (Value: string);
begin
try
FDataLink.FieldName := Value;
finally
Enabled := FDataLink.Active and
(FDataLink.Field <> nil) and
not FDataLink.Field.ReadOnly;
end;
end;
function TMdDbTrack.GetDataSource: TDataSource;
begin
Result := FDataLink.DataSource;
end;
procedure TMdDbTrack.SetDataSource (Value: TDataSource);
begin
FDataLink.DataSource := Value;
Enabled := FDataLink.Active and
(FDataLink.Field <> nil) and
not FDataLink.Field.ReadOnly;
end;
function TMdDbTrack.GetField: TField;
begin
Result := FDataLink.Field;
end;
procedure TMdDbTrack.DataChange (Sender: TObject);
begin
if (FDataLink.Field <> nil) and
(FDataLink.Field is TNumericField) then
Position := FDataLink.Field.AsInteger
else
Position := Min;
end;
procedure TMdDbTrack.ActiveChange (Sender: TObject);
begin
Enabled := FDataLink.Active and
(FDataLink.Field <> nil) and
not FDataLink.Field.ReadOnly;
end;
procedure TMdDbTrack.CNHScroll(var Message: TWMHScroll);
begin
FDataLink.Edit;
inherited;
FDataLink.Modified;
end;
procedure TMdDbTrack.CNVScroll(var Message: TWMVScroll);
begin
FDataLink.Edit;
inherited;
FDataLink.Modified;
end;
procedure TMdDbTrack.CMExit(var Message: TCMExit);
begin
try
FDataLink.UpdateRecord;
except
SetFocus;
raise;
end;
inherited;
end;
procedure TMdDbTrack.UpdateData (Sender: TObject);
begin
if (FDataLink.Field <> nil) and
(FDataLink.Field is TNumericField) then
FDataLink.Field.AsInteger := Position;
end;
procedure Register;
begin
RegisterComponents('Md', [TMdDbTrack]);
end;
end.
|
|