unit MiniGrid;
interface
uses
Windows, Messages, SysUtils, Classes, Controls, ExtCtrls, Graphics, ComCtrls, Dialogs, StdCtrls,
Forms, MiniCombobox, MiniDTPicker, MiniButton, MiniBoxLabel;
const
TEXT_LENGTH=64;
type
//TEditControlType=(_Edit,_Combobox,_DTPicker); //某个单元格要编辑的类型。
PEditCtrlInfo=^TEditCtrlInfo;
TEditCtrlInfo=record //
ACol: integer;
ARow: integer;
Text: string[TEXT_LENGTH];
Ctrl: TWinControl;
end;
type
PBufText=^TBufText;
TBufText=record
Checked: Boolean; //如果显示,则此元素代表值。
ImageIndex: integer; //显示图片的序号(TImageList的序号)
BackColor: TColor;
Text: array[0..TEXT_LENGTH-1] of Char; //string[64*SizeOf(Char)];array[0..ROW_BUFSIZE-1] of Char;
end;
TColData=record
Caption: array[0..TEXT_LENGTH-1] of Char; //string[64*SizeOf(Char)];
Width: WORD;
Alignment: TAlignment;
ShowCheckBox: Boolean; //是否显示选择框
Text: Pointer;
end;
const
TITLEHEIGHT=19; //标题条的高度。
SCROLLWIDTH=18; //滚动条的宽度。
SCROLLMINHEIGHT=8; //滚动条最矮的高度。
ROW_BUFSIZE=SizeOf(TBufText);
const
WM_INPUTTEXT=WM_USER+35;
type
TMiniGrid=class;
TTitles=class;
TTitle=class(TCollectionItem)
private
FWidth: WORD;
FAlignment: TAlignment;
FCaption: string;
FShowCheckBox: Boolean;
//FCollection: TTitles;
procedure SetWidth(Value: WORD);
procedure SetAlignment(Value: TAlignment);
procedure SetCaption(Value: string);
procedure SetShowCheckBox(Value: Boolean);
protected
function GetDisplayName: string; override;
public
constructor Create(Collection: TCollection); override;
destructor Destroy; override;
procedure Assign(Source: TPersistent); override;
published
property Width: WORD read FWidth write SetWidth;
property Alignment: TAlignment read FAlignment write SetAlignment;
property Caption: string read FCaption write SetCaption;
property ShowCheckBox: Boolean read FShowCheckBox write SetShowCheckBox;
end;
TTitles=class(TCollection)
private
FMiniGrid: TMiniGrid;
function GetItem(Index: integer): TTitle;
procedure SetItem(Index: integer; Value: TTitle);
protected
procedure Update(Item: TCollectionItem); override;
//procedure Notify(Item: TCollectionItem; Action: TCollectionNotification); override;
public
constructor Create(MiniGrid: TMiniGrid);
function Add: TTitle;
procedure Delete(Index: Integer);
property Items[Index: integer]: TTitle read GetItem write SetItem; default;
end;
TMouseState=(zxcDown,zxcUp);
TOnScroll=procedure(Sender: TObject; CurrentTopID: integer) of Object;
TMiniScroll=class(TCustomControl)
private
FOnScroll: TOnScroll;
BL: Single; //移动滚条一个点代表多少ROW的数量
ScrlCount: integer; //滚条可移动多少个点。
FHideCount: integer;
FShowRect: TRect;
//CurrPosition: integer; //当前滚条的位置。
//BarHeight: integer;
MouseState: TMouseState;
OldPoint: TPoint; //
bkBitmap: TBitmap;
procedure SetHideCount(Value: integer);
procedure SetShowRect(Value: TRect);
//procedure WMERASEBKGND(var Msg: TWMERASEBKGND); message WM_ERASEBKGND;
//procedure DrawScrollBar(NewPosition: integer);
protected
is3D: Boolean;
procedure Paint; override;
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
//procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override;
procedure Change(TopRowID: integer);
property OnScroll: TOnScroll read FOnScroll write FOnScroll;
property HideCount: integer read FHideCount write SetHideCount;
property ShowRect: TRect read FShowRect write SetShowRect;
end;
TEditType=(miniNUM,miniSINGLE,miniSTR);
TEditBox = class(TEdit)
private
bkCtrl: TMiniBoxLabel;
procedure ProcessInput;
procedure WmKillFocus(var Msg: TMessage); message WM_KILLFOCUS;
procedure CustomKeyPress(Sender: TObject; var Key: Char);
public
ARow: integer;
ACol: integer;
EditType: TEditType;
constructor Create(Aowner: TComponent; bkBoxLabel: TMiniBoxLabel); overload;
destructor Destroy; override;
end;
TComboboxBox = class(TMiniCombobox)
private
procedure ProcessInput;
//procedure WmKillFocus(var Msg: TMessage); message WM_KILLFOCUS;
procedure CustomKeyPress(Sender: TObject; var Key: Char);
procedure CustomExit(Sender: TObject);
public
ARow: integer;
ACol: integer;
constructor Create(Aowner: TComponent); override;
end;
TDTPickerBox = class(TMiniDTPicker)
private
procedure ProcessInput;
procedure WmKillFocus(var Msg: TMessage); message WM_KILLFOCUS;
procedure CustomKeyPress(Sender: TObject; var Key: Char);
public
ARow: integer;
ACol: integer;
constructor Create(Aowner: TComponent); override;
end;
TOnMouseEnter=procedure(Sender: TObject) of Object;
TOnMouseLeave=procedure(Sender: TObject) of Object;
TOnSelectChanged=procedure(Sender: TObject; ARow: integer) of Object;
TOnSetFontColor=procedure(Sender: TObject; ACol, ARow: integer; var RowColor: TColor) of object;
TOnChecked=procedure(Sender: TObject; ACol,ARow: integer; Checked: Boolean) of Object;
TOnSetEdit=procedure(Sender: TObject; ACol, ARow: integer; var CanEdit: Boolean; var EditType: TEditType; var MaxInputLength: integer) of object;
TOnSetCombobox=procedure(Sender: TObject; ACol, ARow: integer; var CanEdit: Boolean; var Style: TComboboxStyle; var InputList: TStringList) of object;
TOnSetDTPicker=procedure(Sender: TObject; ACol, ARow: integer; var CanEdit: Boolean; var ADateTime: TDateTime) of object;
TOnSetMouseDown=procedure(Sender: TObject; Button: TMouseButton; ACol, ARow: integer; var CanEdit: Boolean; var AText: string) of object;
TOnEditTextChanged=procedure(Sender: TObject; ACol, ARow: integer; Text: string) of object;
TMiniGrid = class(TCustomControl)
private
FOnSelectChanged: TOnSelectChanged;
FOnSetFontColor: TOnSetFontColor;
FOnMouseEnter: TOnMouseEnter;
FOnMouseLeave: TOnMouseLeave;
FOnChecked: TOnChecked;
FOnSetEdit: TOnSetEdit;
FOnSetCombobox: TOnSetCombobox;
FOnSetDTPicker: TOnSetDTPicker;
FOnSetMouseDown: TOnSetMouseDown;
FOnEditTextChanged: TOnEditTextChanged;
FBackBitmap: TBitmap;
//FBackPicture: TPicture;
FShowTitle: Boolean;
FTitles: TTitles;
FTitleFont: TFont;
FGridFont: TFont;
FRowCount: integer;
FRowHeight: integer;
FShowScrollBar: Boolean;
FShowSelection: Boolean;
Fis3D: Boolean;
FSelectionColor: TColor;
SelectionID: integer;
PenColor: TColor;
TitleBitmap: TBitmap; //标题条的自定义位图
_1BufferBtm: TBitmap; //整个控件的内存缓冲图。
_2BufferBtm: TBitmap;
Data: array of TColData; //网格数据
GridTop: integer; //网格相对于本控件的Y轴位置。
TopRowID: integer; //当前顶部所显示的Row的ID号.
ShowRowCount: integer; //根据当前控件高度得到的显示的Row的数量。
ScrollBar: TMiniScroll;
FImageList: TImageList;
FImgLstBitmap: TBitmap;
procedure SetShowTitle(Value: Boolean);
procedure SetTitles(Value: TTitles);
procedure SetRowCount(Value: integer);
procedure SetRowHeight(Value: integer);
procedure SetShowSelection(Value: Boolean);
procedure SetShowScrollBar(Value: Boolean);
procedure Setis3D(Value: Boolean);
procedure SetSelectionColor(Value: TColor);
function GetCells(ACol, ARow: Integer): string;
procedure SetCells(ACol, ARow: Integer; Value: string);
procedure SetTitleFont(Value: TFont);
procedure SetGridFont(Value: TFont);
procedure AdjustParameter;
procedure DrawTitles;
function PointToColRow(Pt: TPoint; var ACol,ARow: integer): Boolean;
procedure Show_Selection(NewARow,OldARow: integer);
procedure WmSize(var Msg: TMessage); message WM_SIZE;
procedure WMGetDlgCode(var Msg: TWMGetDlgCode); message WM_GETDLGCODE;
procedure WmKeyDown(var Msg: TMessage); message WM_KEYDOWN;
procedure WmMouseWheel(var Msg: TWmMouseWheel); message WM_MOUSEWHEEL;
//procedure WmLbuttonDown(var Msg: TMessage); message WM_LBUTTONDOWN;
procedure FontChanged(Sender: TObject);
procedure ScrollChanged(Sender: TObject; CurrentTopID: integer);
procedure DrawCell(ACol,ARow: integer);
//procedure PictureChanged(Sender: TObject);
procedure WmInputText(var Msg: TMessage); message WM_INPUTTEXT;
protected
procedure Paint; override;
procedure CreateWnd; override;
procedure CreateParams(var Params: TCreateParams); override;
procedure AdjustClientRect(var Rect: TRect); override;
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
procedure UpdateTitle(Item: TTitle);
procedure UpdateTitles;
procedure MouseEnter(var Msg: TMessage); message CM_MOUSEENTER;
procedure MouseLeave(var Msg: TMessage); message CM_MOUSELEAVE;
public
constructor Create(Aowner: TComponent); override;
destructor Destroy; override;
procedure DrawGrid;
procedure Clear;
function GetSelected: integer;
function GetRowAt(X,Y: integer): integer;
function GetColAt(X,Y: integer): integer;
function Delete(ARow: integer): Boolean;
function Add(ARow: integer): Boolean;
procedure MoveRow(Direction: integer; MoveCount: integer);
function ColRowToRect(ACol,ARow: integer; var R: TRect): Boolean;
function GetChecked(ACol,ARow: integer): Boolean;
procedure SetChecked(ACol,ARow: integer; Checked: Boolean);
procedure SetImage(ImageList: TImageList);
procedure SetCellImage(ACol,ARow: integer; ImageIndex: integer);
procedure SetRowColor(ARow, Color: TColor);
procedure SetBackgroudPicture(Picture: TBitmap);
property Cells[ACol, ARow: Integer]: string read GetCells write SetCells;
published
property ShowTitle: Boolean read FShowTitle write SetShowTitle;
property Titles: TTitles read FTitles write SetTitles;
property RowCount: integer read FRowCount write SetRowCount;
property RowHeight: integer read FRowHeight write SetRowheight;
property ShowSelection: Boolean read FShowSelection write SetShowSelection;
property ShowScrollBar: Boolean read FShowScrollBar write SetShowScrollBar;
property TitleFont: TFont read FTitleFont write SetTitleFont;
property GridFont: TFont read FGridFont write SetGridFont;
//property BackPicture: TPicture read FBackPicture write SetBackPicture;
property is3D: Boolean read Fis3D write Setis3D;
property SelectionColor: TColor read FSelectionColor write SetSelectionColor;
property Enabled;
property Hint;
property ShowHint;
property DragCursor;
property DragKind;
property DragMode;
property Color;
property Align;
property OnSelectChanged: TOnSelectChanged read FOnSelectChanged write FOnSelectChanged;
property OnSetFontColor: TOnSetFontColor read FOnSetFontColor write FOnSetFontColor;
property OnMouseDown;
property OnDblClick;
property OnKeyDown;
property OnkeyPress;
property OnEnter;
property OnExit;
property OnDragDrop;
property OnDragOver;
property OnResize;
property OnMouseEnter: TOnMouseEnter read FOnMouseEnter write FOnMouseEnter;
property OnMouseLeave: TOnMouseLeave read FOnMouseLeave write FOnMouseLeave;
property OnChecked: TOnChecked read FOnChecked write FOnChecked;
property OnSetEdit: TOnSetEdit read FOnSetEdit write FOnSetEdit;
property OnSetCombobox: TOnSetCombobox read FOnSetCombobox write FOnSetCombobox;
property OnSetDTPicker: TOnSetDTPicker read FOnSetDTPicker write FOnSetDTPicker;
property OnSetMouseDown: TOnSetMouseDown read FOnSetMouseDown write FOnSetMouseDown;
property OnEditTextChanged: TOnEditTextChanged read FOnEditTextChanged write FOnEditTextChanged;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('MiniControl', [TMiniGrid]);
end;
{ TMiniGrid }
constructor TMiniGrid.Create(Aowner: TComponent);
var
i,rC,gC,bC: integer;
begin
inherited Create(AOwner);
ControlStyle := ControlStyle+[csAcceptsControls];
Width := 185;
Height := 80;
FShowTitle:=True;
FRowCount:=0;
FRowHeight:=20;
FShowSelection:=False;
FShowScrollBar:=False;
Fis3D:=True;
FSelectionColor:=clSkyBlue;
PenColor:=RGB(0,200,255);
ParentColor:=False;
//Color:=$00F4F4F4;
TitleBitmap:=TBitmap.Create;
TitleBitmap.Width:=2;
TitleBitmap.Height:=18;
rC:=0; gC:=0; bC:=0;
for i:=0 to 17 do
begin
TitleBitmap.Canvas.Pen.Color:=RGB(255-rC,255-gC,255-bC);
TitleBitmap.Canvas.MoveTo(0,i);
TitleBitmap.Canvas.LineTo(TitleBitmap.Width,i);
Inc(rC,4);
Inc(gC,3);
Inc(bC,2);
end;
FTitleFont:=TFont.Create;
FGridFont:=TFont.Create;
FTitleFont.OnChange:=FontChanged;
FGridFont.OnChange:=FontChanged;
_1BufferBtm:=TBitmap.Create;
_2BufferBtm:=TBitmap.Create;
FBackBitmap:=TBitmap.Create;
FBackBitmap.Width:=0;
FTitles:=TTitles.Create(Self);
FImageList:=nil;
FImgLstBitmap:=TBitmap.Create;
end;
destructor TMiniGrid.Destroy;
var
i: integer;
begin
TitleBitmap.Free;
_1BufferBtm.Free;
_2BufferBtm.Free;
FBackBitmap.Free;
FTitleFont.Free;
FGridFont.Free;
FTitles.Free;
if ScrollBar<>nil then
ScrollBar.Free;
for i:=0 to High(Data) do
if Data[i].Text<>nil then
FreeMem(Data[i].Text,FRowCount*ROW_BUFSIZE);
FImgLstBitmap.Free;
inherited;
end;
procedure TMiniGrid.CreateWnd;
begin
inherited;
TopRowID:=0;
SelectionID:=0;
AdjustParameter;
end;
procedure TMiniGrid.AdjustParameter;
begin
_1BufferBtm.Width:=Width;
_1BufferBtm.Height:=Height;
_2BufferBtm.Width:=Width;
_2BufferBtm.Height:=Height;
if FShowTitle then
begin
GridTop:=TITLEHEIGHT;
if ((Height-TITLEHEIGHT) mod RowHeight-1)<>0 then
ShowRowCount:=((Height-TITLEHEIGHT) div RowHeight)+1
else
ShowRowCount:=((Height-TITLEHEIGHT) div RowHeight);
end
else
begin
GridTop:=0;
if (Height mod RowHeight)<>0 then
ShowRowCount:=(Height div RowHeight)+1
else
ShowRowCount:=(Height div RowHeight);
end;
if FShowScrollBar and(ScrollBar<>nil) then
begin
ScrollBar.ShowRect:=Rect(Width-SCROLLWIDTH-2,GridTop+2,Width-2,Height-2);
ScrollBar.HideCount:=FRowCount-ShowRowCount;
end;
end;
procedure TMiniGrid.AdjustClientRect(var Rect: TRect);
begin
//AdjustParameter;
inherited AdjustClientRect(Rect);
end;
procedure TMiniGrid.WmSize(var Msg: TMessage);
begin
AdjustParameter; //重新调整坐标等参数。
inherited; //调整后调用默认的过程重新画控件。
end;
function TMiniGrid.ColRowToRect(ACol, ARow: integer; var R: TRect): Boolean;
var
i,X,Y: integer;
begin
Result:=False;
if (FRowCount>0)and(ACol in[0..High(Data)])and(ARow>=TopRowID)and(ARow<=(TopRowID+ShowRowCount-1)) then
begin
X:=0;
for i:=0 to ACol do
Inc(X,Data[i].Width);
Y:=GridTop;
for i:=TopRowID to ARow do
Inc(Y,RowHeight);
R:=Rect(X-Data[ACol].Width+1,Y-RowHeight+1,X,Y); //是某个格子的内框。
Result:=True;
end;
end;
function TMiniGrid.GetCells(ACol, ARow: Integer): string;
var
lpText: PBufText;
begin
Result:='';
if (ACol in[0..High(Data)])and(ARow>=0)and(ARow<=(FRowCount-1)) then
begin
lpText:=Data[ACol].Text;
Inc(lpText,ARow);
Result:=lpText^.Text;
end;
end;
procedure TMiniGrid.SetCells(ACol, ARow: Integer; Value: string);
var
lpText: PBufText;
begin
if (not (ACol in[0..High(Data)]))or(ARow<0)or(ARow>(FRowCount-1)) then
Exit;
lpText:=Data[ACol].Text;
Inc(lpText,ARow);
if Length(Value)>TEXT_LENGTH then
System.Delete(Value,TEXT_LENGTH+1,Length(Value)-TEXT_LENGTH);
//lpText^.Text:=Value;
ZeroMemory(@lpText^.Text,Length(lpText^.Text)*SizeOf(Char));
CopyMemory(@lpText^.Text,Pointer(Value),Length(Value)*SizeOf(Char));
if (ARow>=TopRowID)and(ARow<=(TopRowID+ShowRowCount-1)) then //说明设置的格子是在当前显示区域内。则要重新画相应的格子。
begin
_1BufferBtm.Canvas.Font:=GridFont;
DrawCell(ACol,ARow);
if FShowSelection and(ARow=SelectionID) then
Show_Selection(SelectionID,-1);
end;
end;
procedure TMiniGrid.SetRowCount(Value: integer);
var
i: integer;
begin
if Value<0 then
Exit;
if FRowCount<>Value then
begin
if not (csDesigning in ComponentState) then
for i:=0 to High(Data) do
begin
if Data[i].Text=nil then //第一次分配。
begin
ReallocMem(Data[i].Text,Value*ROW_BUFSIZE);
ZeroMemory(Data[i].Text,Value*ROW_BUFSIZE);
end
else //再次调整内存大小。
begin
ReallocMem(Data[i].Text,Value*ROW_BUFSIZE);
if Value>FRowCount then //如果是把内存变大,需要清空增加的内存。
ZeroMemory(Pointer(DWORD(Data[i].Text)+FRowCount*ROW_BUFSIZE),(Value-FRowCount)*ROW_BUFSIZE);
end;
end;
TopRowID:=0;
SelectionID:=0;
FRowCount:=Value;
AdjustParameter;
DrawGrid;
//Repaint;
end;
end;
procedure TMiniGrid.SetRowHeight(Value: integer);
begin
if Value<=0 then
Exit;
if FRowHeight<>Value then
begin
FRowheight:=Value;
AdjustParameter;
Invalidate;
end;
end;
procedure TMiniGrid.SetShowTitle(Value: Boolean);
begin
if Value<>FShowTitle then
begin
FShowTitle:=Value;
AdjustParameter;
Invalidate;
end;
end;
procedure TMiniGrid.SetTitles(Value: TTitles);
begin
FTitles.Assign(Value);
end;
procedure TMiniGrid.DrawTitles;
var
i,X: integer;
R: TRect;
Text: string;
begin
if FShowTitle then
begin
Canvas.Font:=FTitleFont;
if Fis3D then
Canvas.CopyRect(Rect(1,1,Width-1,TITLEHEIGHT),TitleBitmap.Canvas,Rect(1,0,TitleBitmap.Width,TitleBitmap.Height))
else
if FBackBitmap.Width>0 then
BitBlt(Canvas.Handle,1,1,Width-2,TITLEHEIGHT,FBackBitmap.Canvas.Handle,1,1,SRCCOPY)
else
Canvas.FillRect(Rect(1,1,Width-1,TITLEHEIGHT));
Canvas.MoveTo(1,TITLEHEIGHT);
Canvas.LineTo(Width-1,TITLEHEIGHT);
SetBkMode(Canvas.Handle,TRANSPARENT);
//Canvas.Brush.Style:=bsClear;
//GetTextExtentPoint(Canvas.Handle,'MINI',Length('MINI'),Size);
X:=0;
for i:=0 to High(Data) do
begin
R:=Rect(X+1,1,X+Data[i].Width-1,TITLEHEIGHT-1);
X:=X+Data[i].Width;
Canvas.MoveTo(X,1);
Canvas.LineTo(X,TITLEHEIGHT);
Text:=Data[i].Caption;
DrawText(Canvas.Handle,PChar(Text),Length(Text),R,DT_CENTER or DT_VCENTER or DT_SINGLELINE);
end;
end;
end;
procedure TMiniGrid.DrawGrid;
var
i,j,X,Y,lCCount,lRCount: integer;
begin
_1BufferBtm.Canvas.Font:=FGridFont;
_1BufferBtm.Canvas.Pen.Color:=PenColor;
_1BufferBtm.Canvas.Brush.Style:=bsSolid;
_1BufferBtm.Canvas.Brush.Color:=Color;
if FBackBitmap.Width>0 then
begin
BitBlt(_1BufferBtm.Canvas.Handle,1,GridTop+1,Width-2,Height-2,FBackBitmap.Canvas.Handle,1,GridTop+1,SRCCOPY);
BitBlt(_2BufferBtm.Canvas.Handle,1,GridTop+1,Width-2,Height-2,FBackBitmap.Canvas.Handle,1,GridTop+1,SRCCOPY);
end
else
_1BufferBtm.Canvas.FillRect(Rect(1,GridTop+1,Width-1,Height-1));
if FRowCount>0 then
begin
if (FRowCount-TopRowID)<ShowRowCount then
lRCount:=FRowCount-TopRowID
else
lRCount:=ShowRowCount;
lCCount:=Length(Data);
X:=0;
for i:=0 to lCCount-1 do
begin
X:=X+Data[i].Width;
_1BufferBtm.Canvas.MoveTo(X,GridTop);
_1BufferBtm.Canvas.LineTo(X,GridTop+(lRCount*RowHeight)+1);
Y:=GridTop;
for j:=TopRowID to TopRowID+lRCount-1 do
begin
if Data[i].Text<>nil then //not(csDesigning in ComponentState) then
DrawCell(i,j);
if i=lCCount-1 then //i的最后一次循环时画ROW的横线。
begin
_1BufferBtm.Canvas.MoveTo(0,Y+RowHeight);
_1BufferBtm.Canvas.LineTo(X,Y+RowHeight);
end;
Inc(Y,RowHeight);
end;
end;
end;
Canvas.CopyRect(Rect(1,GridTop+1,Width-1,Height-1),_1BufferBtm.Canvas,Rect(1,GridTop+1,Width-1,Height-1));
if FShowSelection then
Show_Selection(SelectionID,-1);
end;
procedure TMiniGrid.DrawCell(ACol, ARow: integer);
var
R,R1: TRect;
Size: TSize;
Text: string;
lpText: PBufText;
lColor: TColor;
begin
if Data[ACol].Text<>nil then
begin
lpText:=Data[ACol].Text;
Inc(lpText,ARow);
Text:=lpText^.Text;
ColRowToRect(ACol,ARow,R);
if FBackBitmap.Width>0 then
Bitblt(_1BufferBtm.Canvas.Handle,R.Left,R.Top,R.Right-R.Left,R.Bottom-R.Top,_2BufferBtm.Canvas.Handle,R.Left,R.Top,SRCCOPY)
else
begin
_1BufferBtm.Canvas.Brush.Style:=bsSolid;
if lpText^.BackColor>0 then
_1BufferBtm.Canvas.Brush.Color:=lpText^.BackColor
else
_1BufferBtm.Canvas.Brush.Color:=Color;
{if Self.FShowSelection and (Self.GetSelected=ARow) then
_1BufferBtm.Canvas.Brush.Color:=Self.FSelectionColor; }
_1BufferBtm.Canvas.FillRect(R);
end;
_1BufferBtm.Canvas.Brush.Style:=bsClear;
R1:=R;
if Data[ACol].ShowCheckBox then
begin
_1BufferBtm.Canvas.Rectangle(R.Left+2,R.Top+2,R.Left+2+15,R.Top+2+15);//R.Bottom-1);
if lpText^.Checked then
begin
R1:=Rect(R.Left+2,R.Top+2,R.Left+2+15,R.Top+2+15);
_1BufferBtm.Canvas.Pen.Color:=PenColor;
_1BufferBtm.Canvas.Pen.Width:=2;
_1BufferBtm.Canvas.MoveTo(R1.Left+3,R1.Top+5);
_1BufferBtm.Canvas.LineTo(R1.Left+3,R1.Bottom-3);
_1BufferBtm.Canvas.LineTo(R1.Right-3,R1.Top+3);
_1BufferBtm.Canvas.Pen.Width:=1;
//_1BufferBtm.Canvas.Pen.Color:=PenColor;
end;
R1.Left:=R1.Right+1;
end;
if (lpText^.ImageIndex>0)and(FImageList<>nil) then
begin
FImgLstBitmap.Canvas.FillRect(Rect(0,0,FImgLstBitmap.Width,FImgLstBitmap.Height));
if FImageList.GetBitmap(lpText^.ImageIndex-1,FImgLstBitmap) then
begin
Size.cx:=0; Size.cy:=0;
if Text<>'' then
GetTextExtentPoint(_1BufferBtm.Canvas.Handle,PChar(Text),Length(Text),Size);
case Data[ACol].Alignment of
taLeftJustify: ;
taRightJustify: R1.Left:=R1.Right-(16+1+Size.cx);
taCenter: R1.Left:=R1.Left+(((R1.Right-R1.Left)-(16+1+Size.cx)) div 2);
end;
TransparentBlt(_1BufferBtm.Canvas.Handle,R1.Left,R1.Top+((R1.Bottom-R1.Top-16)div 2),16,16,FImgLstBitmap.Canvas.Handle,
0,0,FImgLstBitmap.Width,FImgLstBitmap.Height,FImgLstBitmap.Canvas.Pixels[0,FImgLstBitmap.Height-1]);
R1.Left:=R1.Left+1+16+1;
R1.Right:=R1.Left+Size.cx;
end;
end;
if Text<>'' then
begin
//SetBkMode(_1BufferBtm.Canvas.Handle,TRANSPARENT);
lColor:=0;
if Assigned(FOnSetFontColor) then
begin
lColor:=FGridFont.Color;
FOnSetFontColor(Self,ACol,ARow,lColor);
_1BufferBtm.Canvas.Font.Color:=lColor;
end;
//R1.Left:=R1.Left+1;
case Data[ACol].Alignment of
taLeftJustify: DrawText(_1BufferBtm.Canvas.Handle,PChar(Text),Length(Text),R1,DT_LEFT or DT_VCENTER or DT_SINGLELINE);
taRightJustify: DrawText(_1BufferBtm.Canvas.Handle,PChar(Text),Length(Text),R1,DT_RIGHT or DT_VCENTER or DT_SINGLELINE);
taCenter: DrawText(_1BufferBtm.Canvas.Handle,PChar(Text),Length(Text),R1,DT_CENTER or DT_VCENTER or DT_SINGLELINE);
end;
if _1BufferBtm.Canvas.Font.Color<>FGridFont.Color then
_1BufferBtm.Canvas.Font.Color:=FGridFont.Color;
end;
if R.Bottom>(Height-1) then
R.Bottom:=Height-1;
if R.Right>(Width-1) then
R.Right:=Width-1;
Canvas.CopyRect(R,_1BufferBtm.Canvas,R);
end;
end;
procedure TMiniGrid.Paint;
begin
Canvas.Pen.Color:=PenColor;
Canvas.Brush.Style:=bsSolid;
Canvas.Brush.Color:=Color;
Canvas.Rectangle(0,0,Width,Height);
{if FBackBitmap.Width>0 then
begin
SetStretchBltMode(_1BufferBtm.Canvas.Handle, HALFTONE); //防止图片缩小时失真。
SetStretchBltMode(_2BufferBtm.Canvas.Handle, HALFTONE); //防止图片缩小时失真。
StretchBlt(_1BufferBtm.Canvas.Handle,1,1,Width-2,Height-2,FBackBitmap.Canvas.Handle,0,0,FBackBitmap.Width,FBackBitmap.Height,SRCCOPY);
StretchBlt(_2BufferBtm.Canvas.Handle,1,1,Width-2,Height-2,FBackBitmap.Canvas.Handle,0,0,FBackBitmap.Width,FBackBitmap.Height,SRCCOPY);
end
else
_1BufferBtm.Canvas.FillRect(Rect(1,GridTop+1,Width-1,Height-1)); }
if Length(Data)>0 then
begin
if FShowTitle then
DrawTitles;
DrawGrid;
end;
end;
procedure TMiniGrid.UpdateTitle(Item: TTitle);
var
X: integer;
begin
if Titles.Count>0 then
begin
X:=Item.Index;
//Data[X].Caption:=Item.Caption;
ZeroMemory(@Data[X].Caption,Length(Data[X].Caption)*SizeOf(Char));
CopyMemory(@Data[X].Caption,Pointer(Item.Caption),Length(Item.Caption)*SizeOf(Char));
Data[X].Width:=Item.Width;
Data[X].Alignment:=Item.Alignment;
Data[X].ShowCheckBox:=Item.ShowCheckBox;
//SetLength(FData[i].Text,FRowCount);
Invalidate;
end;
end;
procedure TMiniGrid.UpdateTitles;
var
i: integer;
begin
if Length(Data)>0 then
begin
for i:=0 to High(Data) do
if Data[i].Text<>nil then
begin
FreeMem(Data[i].Text,FRowCount*ROW_BUFSIZE);
Data[i].Text:=nil;
end;
SetLength(Data,0);
Data:=nil;
end;
if Titles.Count>0 then
begin
SetLength(Data,Titles.Count);
for i:=0 to High(Data) do
begin
ZeroMemory(@Data[i].Caption,Length(Data[i].Caption)*SizeOf(Char));
CopyMemory(@Data[i].Caption,Pointer(Titles.Items[i].Caption),Length(Titles.Items[i].Caption)*SizeOf(Char));
//Data[i].Caption:=Titles.Items[i].Caption;
Data[i].Width:=Titles.Items[i].Width;
Data[i].Alignment:=Titles.Items[i].Alignment;
Data[i].ShowCheckBox:=Titles.Items[i].ShowCheckBox;
{if not (csDesigning in ComponentState) then
begin
GetMem(Data[i].Text,FRowCount*ROW_BUFSIZE);
ZeroMemory(Data[i].Text,FRowCount*ROW_BUFSIZE);
end; }
end;
end;
Invalidate;
end;
procedure TMiniGrid.Show_Selection(NewARow,OldARow: integer);
var
i: integer;
R,R1: TRect;
Size: TSize;
Text: string;
lpText: PBufText;
lColor: TColor;
begin
if (not FShowSelection) or (FRowCount=0) then
Exit;
if ColRowToRect(High(Data),OldARow,R) then
begin
R.Left:=1;
if R.Bottom>(Height-1) then
R.Bottom:=Height-1;
if R.Right>(Width-1) then
R.Right:=Width-1;
Canvas.CopyRect(R,_1BufferBtm.Canvas,R); //恢复老的选择区域。
end;
if ColRowToRect(High(Data),NewARow,R) then //画新的选择区域。
begin
Canvas.Font:=Self.GridFont;
for i:=0 to High(Data) do
if Data[i].Text<>nil then
begin
lpText:=Data[i].Text;
Inc(lpText,NewARow);
Text:=lpText^.Text;
ColRowToRect(i,NewARow,R);
Canvas.Brush.Color:=FSelectionColor;
Canvas.FillRect(R);
R1:=R;
if Data[i].ShowCheckBox then
begin
Canvas.Rectangle(R.Left+2,R.Top+2,R.Left+2+15,R.Top+2+15);//R.Bottom-1);
if lpText^.Checked then
begin
R1:=Rect(R.Left+2,R.Top+2,R.Left+2+15,R.Top+2+15);
Canvas.Pen.Color:=PenColor;
Canvas.Pen.Width:=2;
Canvas.MoveTo(R1.Left+3,R1.Top+5);
Canvas.LineTo(R1.Left+3,R1.Bottom-3);
Canvas.LineTo(R1.Right-3,R1.Top+3);
Canvas.Pen.Width:=1;
end;
R1.Left:=R1.Right+1;
end;
if (lpText^.ImageIndex>0)and(FImageList<>nil) then
begin
FImgLstBitmap.Canvas.FillRect(Rect(0,0,FImgLstBitmap.Width,FImgLstBitmap.Height));
if FImageList.GetBitmap(lpText^.ImageIndex-1,FImgLstBitmap) then
begin
Size.cx:=0; Size.cy:=0;
if Text<>'' then
GetTextExtentPoint(Canvas.Handle,PChar(Text),Length(Text),Size);
case Data[i].Alignment of
taLeftJustify: ;
taRightJustify: R1.Left:=R1.Right-(16+1+Size.cx);
taCenter: R1.Left:=R1.Left+(((R1.Right-R1.Left)-(16+1+Size.cx)) div 2);
end;
TransparentBlt(Canvas.Handle,R1.Left,R1.Top+((R1.Bottom-R1.Top-16)div 2),16,16,FImgLstBitmap.Canvas.Handle,
0,0,FImgLstBitmap.Width,FImgLstBitmap.Height,FImgLstBitmap.Canvas.Pixels[0,FImgLstBitmap.Height-1]);
R1.Left:=R1.Left+1+16+1;
R1.Right:=R1.Left+Size.cx;
end;
end;
if Text<>'' then
begin
//SetBkMode(_1BufferBtm.Canvas.Handle,TRANSPARENT);
lColor:=0;
if Assigned(FOnSetFontColor) then
begin
lColor:=FGridFont.Color;
FOnSetFontColor(Self,i,NewARow,lColor);
Canvas.Font.Color:=lColor;
end;
case Data[i].Alignment of
taLeftJustify: DrawText(Canvas.Handle,PChar(Text),Length(Text),R1,DT_LEFT or DT_VCENTER or DT_SINGLELINE);
taRightJustify: DrawText(Canvas.Handle,PChar(Text),Length(Text),R1,DT_RIGHT or DT_VCENTER or DT_SINGLELINE);
taCenter: DrawText(Canvas.Handle,PChar(Text),Length(Text),R1,DT_CENTER or DT_VCENTER or DT_SINGLELINE);
end;
if Canvas.Font.Color<>FGridFont.Color then
Canvas.Font.Color:=FGridFont.Color;
end;
end;
if ColRowToRect(High(Data),NewARow,R) then
if R.Bottom>(Height-1) then
begin
Canvas.Pen.Color:=PenColor;
Canvas.MoveTo(0,Height-1);
Canvas.LineTo(Width,Height-1);
end;
{R.Left:=1;
//R.Top:=R.Top+1;
//R.Bottom:=R.Bottom-1;
if R.Bottom>(Height-1) then
R.Bottom:=Height-1;
if R.Right>(Width-1) then
R.Right:=Width-1;
//Canvas.Brush.Color:=clSkyBlue;
//Canvas.FillRect(R);
Bitblt(Canvas.Handle,R.Left,R.Top,R.Right-R.Left,R.Bottom-R.Top,_1BufferBtm.Canvas.Handle,R.Left,R.Top,SRCCOPY);//NOTSRCCOPY);
Canvas.Brush.Style:=bsClear;
Canvas.Pen.Color:=clBlack;
Canvas.Rectangle(R); }
//TransparentBlt(Canvas.Handle,R.Left,R.Top,R.Right-R.Left,R.Bottom-R.Top,_1BufferBtm.Canvas.Handle,R.Left,R.Top,R.Right-R.Left,R.Bottom-R.Top,clRed);
end;
if Assigned(FOnSelectChanged) and (OldARow<>-1) and (NewARow<>OldARow) then
FOnSelectChanged(Self,NewARow);
end;
procedure TMiniGrid.MoveRow(Direction: integer; MoveCount: integer);
begin
case Direction of
VK_UP: begin //上移动
if FShowSelection then
begin
if (SelectionID-MoveCount)>=0 then
begin
if ((SelectionID-MoveCount)>=TopRowID)and((SelectionID-MoveCount)<=(TopRowID+ShowRowCount-1)) then //如果在当前显示范围内。
begin
Dec(SelectionID,MoveCount);
Show_Selection(SelectionID,SelectionID+MoveCount);
end
else
begin
Dec(SelectionID,MoveCount);
if (TopRowID-MoveCount)=SelectionID then
TopRowID:=SelectionID
else
begin
TopRowID:=SelectionID-ShowRowCount+1;
if TopRowID<0 then
TopRowID:=0;
end;
DrawGrid;
Show_Selection(SelectionID,SelectionID-MoveCount);
if FShowScrollBar and(ScrollBar<>nil) then
ScrollBar.Change(TopRowID);
end;
end
else
if TopRowID>0 then
begin
TopRowID:=0;
DrawGrid;
Show_Selection(SelectionID,-1);
if FShowScrollBar and(ScrollBar<>nil) then
ScrollBar.Change(TopRowID);
end;
end
else
if TopRowID>0 then
begin
Dec(TopRowID);
DrawGrid;
if ScrollBar.Visible then
ScrollBar.Change(TopRowID);
end;
end;
VK_DOWN: begin //下移动
if FShowSelection then
begin
if (SelectionID+MoveCount)<=(FRowCount-1) then
begin
if ((SelectionID+MoveCount)>=TopRowID)and((SelectionID+MoveCount)<=(TopRowID+ShowRowCount-1)) then
begin
Inc(SelectionID,MoveCount);
Show_Selection(SelectionID,SelectionID-MoveCount);
end
else
begin
Inc(SelectionID,MoveCount);
TopRowID:=SelectionID-ShowRowCount+1;
if TopRowID<0 then
TopRowID:=0;
DrawGrid;
Show_Selection(SelectionID,SelectionID-MoveCount);
if FShowScrollBar and(ScrollBar<>nil) then
ScrollBar.Change(TopRowID);
end;
end
else
if TopRowID<(SelectionID-ShowRowCount+2) then
begin
TopRowID:=SelectionID-ShowRowCount+2;
//Inc(TopRowID);
DrawGrid;
Show_Selection(SelectionID,SelectionID-1);
if FShowScrollBar and(ScrollBar<>nil) then
ScrollBar.Change(TopRowID);
end;
end
else
if (TopRowID+ShowRowCount)<=FRowCount then
begin
Inc(TopRowID);
DrawGrid;
if FShowScrollBar and(ScrollBar<>nil) then
ScrollBar.Change(TopRowID);
end;
end;
end;
end;
procedure TMiniGrid.WmKeyDown(var Msg: TMessage);
begin
inherited;
case Msg.WParam of
VK_UP: MoveRow(VK_UP,1); //上移动
VK_DOWN: MoveRow(VK_DOWN,1); //下移动
end;
end;
procedure TMiniGrid.WmMouseWheel(var Msg: TWmMouseWheel);
begin
if Msg.WheelDelta>0 then //上移动
MoveRow(VK_UP,1)
else //下移动
MoveRow(VK_DOWN,1);
end;
procedure TMiniGrid.WMGetDlgCode(var Msg: TWMGetDlgCode);
begin
Msg.Result:=DLGC_WANTARROWS; //防止移动方向键时移动控件的焦点!!!
end;
procedure TMiniGrid.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
with Params do
Style:=Style or WS_TABSTOP;
end;
function TMiniGrid.PointToColRow(Pt: TPoint; var ACol,
ARow: integer): Boolean;
var
X,Y,i,j,lRCount: integer;
begin
Result:=False;
if (TopRowID+ShowRowCount)<=FRowCount then
lRCount:=TopRowID+ShowRowCount
else
lRCount:=FRowCount;
X:=0;
for i:=0 to High(Data) do
begin
Inc(X,Data[i].Width);
Y:=GridTop;
for j:=TopRowID to lRCount-1 do
begin
Inc(Y,RowHeight);
if PtInRect(Rect(1,Y-RowHeight, X-1,Y),Pt) then
begin
ACol:=i;
ARow:=j;
Result:=True;
Break;
end;
end;
if Result then
Break;
end;
end;
{procedure TMiniGrid.WmLbuttonDown(var Msg: TMessage);
var
OldID,ACol,ARow: integer;
CurrP: TPoint;
begin
inherited;
Windows.SetFocus(Self.Handle);
CurrP:=Point(Msg.LParamLo,Msg.LParamHi);
//Windows.ScreenToClient(Handle,CurrP);
if PointToColRow(CurrP,ACol,ARow) then
if ARow<>SelectionID then
begin
OldID:=SelectionID;
SelectionID:=ARow;
Show_Selection(SelectionID,OldID);
end;
end; }
procedure TMiniGrid.Clear;
var
i: integer;
begin
FRowCount:=0;
TopRowID:=0;
SelectionID:=0;
for i:=0 to High(Data) do
if Data[i].Text<>nil then
begin
FreeMem(Data[i].Text,FRowCount*ROW_BUFSIZE);
Data[i].Text:=nil;
end;
//AdjustParameter;
if FShowScrollBar then
ScrollBar.HideCount:=0;
DrawGrid;
//Invalidate;
end;
procedure TMiniGrid.SetShowSelection(Value: Boolean);
begin
if FShowSelection<>Value then
begin
FShowSelection:=Value;
SelectionID:=TopRowID;
Invalidate;
end;
end;
procedure TMiniGrid.SetGridFont(Value: TFont);
begin
FGridFont.Assign(Value);
end;
procedure TMiniGrid.SetTitleFont(Value: TFont);
begin
FTitleFont.Assign(Value);
end;
procedure TMiniGrid.SetBackgroudPicture(Picture: TBitmap);
begin
FBackBitmap.Assign(Picture);
Invalidate;
end;
procedure TMiniGrid.FontChanged(Sender: TObject);
begin
Invalidate;
end;
procedure TMiniGrid.ScrollChanged(Sender: TObject; CurrentTopID: integer);
begin
TopRowID:=CurrentTopID;
DrawGrid;
if FShowSelection then
if (SelectionID>=TopRowID)and(SelectionID<=(TopRowID+ShowRowCount-1)) then
Show_Selection(SelectionID,-1);
end;
procedure TMiniGrid.SetShowScrollBar(Value: Boolean);
begin
if FShowScrollBar<>Value then
begin
FShowScrollBar:=Value;
if FShowScrollBar then
begin
ScrollBar:=TMiniScroll.Create(Self);
ScrollBar.Parent:=Self;
ScrollBar.ShowRect:=Rect(Width-SCROLLWIDTH-2,GridTop+2,Width-2,Height-2); //GridTop+4
ScrollBar.HideCount:=FRowCount-ShowRowCount;
ScrollBar.OnScroll:=ScrollChanged;
ScrollBar.Show;
end
else
if ScrollBar<>nil then
begin
ScrollBar.Free;
ScrollBar:=nil;
end;
end;
end;
procedure TMiniGrid.MouseDown(Button: TMouseButton; Shift: TShiftState; X,
Y: Integer);
var
i,OldID,ACol,ARow: integer;
CurrP: TPoint;
lpText:PBufText;
lColor: TColor;
lCanEdit: Boolean;
lEditType: TEditType;
lMaxInputLength: integer;
cStyle: TComboboxStyle;
InputList: TStringList;
ADateTime: TDateTime;
AText: string;
R: TRect;
Edit_: TEditBox;
BoxLabel_: TMiniBoxLabel;
Combobox_: TComboboxBox;
DTPicker_: TDTPickerBox;
isEdited: Boolean;
DC: HDC;
Size: TSize;
begin
isEdited:=False;
Windows.SetFocus(Self.Handle);
CurrP:=Point(X,Y);
if PointToColRow(CurrP,ACol,ARow) then
begin
OldID:=-1;
if ARow<>SelectionID then
begin
OldID:=SelectionID;
SelectionID:=ARow;
end;
Show_Selection(SelectionID,OldID);
//if Button=mbLeft then
if Assigned(FOnSetEdit) then
begin
lCanEdit:=False;
lEditType:=miniSTR;
lMaxInputLength:=0;
FOnSetEdit(Self,ACol,ARow,lCanEdit,lEditType,lMaxInputLength);
if lCanEdit and ColRowToRect(ACol,ARow,R) then
begin
BoxLabel_:=TMiniBoxLabel.Create(Self);
BoxLabel_.Parent:=Self;
BoxLabel_.Brush.Color:=clWhite; //Self.Color;
BoxLabel_.is3D:=False;
BoxLabel_.Left:=R.Left-1;
BoxLabel_.Top:=R.Top-1;
BoxLabel_.Width:=R.Right-R.Left+2;
BoxLabel_.Height:=R.Bottom-R.Top+2;
BoxLabel_.Show;
Edit_:=TEditBox.Create(Self,BoxLabel_);
Edit_.Parent:=Self;
Edit_.Font:=Self.FGridFont;
Edit_.Color:=clWhite;//Self.Color;
Edit_.EditType:=lEditType;
Edit_.MaxLength:=lMaxInputLength;
Edit_.Text:=Cells[ACol,ARow];
DC:=GetDC(Edit_.Handle);
GetTextExtentPoint(DC,'MINI',Length('MINI'),Size);
ReleaseDC(Edit_.Handle,DC);
Edit_.ARow:=ARow;
Edit_.ACol:=ACol;
Edit_.Width:=R.Right-R.Left;
Edit_.Height:=Size.cy-4;
if Edit_.Height>(R.Bottom-R.Top) then
Edit_.Height:=R.Bottom-R.Top;
Edit_.Left:=R.Left;
Edit_.Top:=R.Top+(((R.Bottom-R.Top)-Edit_.Height) div 2);
Edit_.Show;
Edit_.SetFocus;
isEdited:=True;
end;
end;
if (not isEdited) and Assigned(FOnSetCombobox) then
begin
lCanEdit:=False;
cStyle:=csDropDown;
InputList:=TStringList.Create;
try
FOnSetCombobox(Self,ACol,ARow,lCanEdit,cStyle,InputList);
if lCanEdit and ColRowToRect(ACol,ARow,R) then
begin
Combobox_:=TComboboxBox.Create(Self);
Combobox_.Parent:=Self;
Combobox_.Style:=cStyle;
//Combobox_.Text:=Cells[ACol,ARow];
Combobox_.ARow:=ARow;
Combobox_.ACol:=ACol;
Combobox_.Width:=R.Right-R.Left+2;
//Combobox_.Height:=R.Bottom-R.Top+2;
Combobox_.Left:=R.Left-1;
Combobox_.Top:=R.Top-1;
Combobox_.Show;
Combobox_.SetFocus;
Combobox_.Items.Assign(InputList);
for i:=0 to Combobox_.Items.Count-1 do
if Combobox_.Items.Strings[i]=Cells[ACol,ARow] then
begin
Combobox_.ItemIndex:=i;
Break;
end;
isEdited:=True;
end;
finally
InputList.Free;
end;
end;
if (not isEdited) and Assigned(FOnSetDTPicker) then
begin
lCanEdit:=False;
ADateTime:=Now;
FOnSetDTPicker(Self,ACol,ARow,lCanEdit,ADateTime);
if lCanEdit and ColRowToRect(ACol,ARow,R) then
begin
DTPicker_:=TDTPickerBox.Create(Self);
DTPicker_.Parent:=Self;
if Cells[ACol,ARow]='' then
DTPicker_.DateTime:=ADateTime
else
DTPicker_.DateTime:=StrToDate(Cells[ACol,ARow]);
//Combobox_.Text:=Cells[ACol,ARow];
DTPicker_.ARow:=ARow;
DTPicker_.ACol:=ACol;
DTPicker_.Width:=R.Right-R.Left+2;
//DTPicker_.Height:=20;
//DTPicker_.Height:=R.Bottom-R.Top;
DTPicker_.Left:=R.Left-1;
DTPicker_.Top:=R.Top-1;
DTPicker_.Show;
DTPicker_.SetFocus;
isEdited:=True;
end;
end;
if (not isEdited) and Assigned(FOnSetMouseDown) then
begin
lCanEdit:=False;
AText:='';
FOnSetMouseDown(Self,Button,ACol,ARow,lCanEdit,AText);
if lCanEdit and ColRowToRect(ACol,ARow,R) then
begin
SetCells(ACol,ARow,AText);
isEdited:=True;
end;
end;
if Data[ACol].ShowCheckBox then
begin
lpText:=Data[ACol].Text;
Inc(lpText,ARow);
if not lpText^.Checked then
begin
lpText^.Checked:=True;
DrawCell(ACol,ARow);
end
else
begin
lpText^.Checked:=False;
DrawCell(ACol,ARow);
end;
if Assigned(FOnChecked) then
FOnChecked(Self,ACol,ARow,lpText^.Checked);
{if Assigned(FOnSetFontColor) then
begin
lColor:=FGridFont.Color;
FOnSetFontColor(Self,ACol,ARow,lColor);
_1BufferBtm.Canvas.Font.Color:=lColor; //messagebeep(20);
for i:=0 to High(Data) do
DrawCell(i,ARow);
end;}
end;
end;
if not isEdited then //如果前面没有编辑动作,则调用默认的OnMouseDown事件.
inherited;
end;
function TMiniGrid.GetChecked(ACol, ARow: integer): Boolean;
var
lpText: PBufText;
begin
Result:=False;
if (not (ACol in[0..High(Data)]))or(ARow<0)or(ARow>(FRowCount-1)) then
Exit;
if not Data[ACol].ShowCheckBox then
Exit;
lpText:=Data[ACol].Text;
Inc(lpText,ARow);
if lpText<>nil then
Result:=lpText^.Checked;
end;
procedure TMiniGrid.SetChecked(ACol, ARow: integer; Checked: Boolean);
var
lpText: PBufText;
i: integer;
lColor: TColor;
begin
if (not (ACol in[0..High(Data)]))or(ARow<0)or(ARow>(FRowCount-1)) then
Exit;
if Data[ACol].ShowCheckBox then
begin
lpText:=Data[ACol].Text;
Inc(lpText,ARow);
if Checked then
begin
if not lpText^.Checked then
begin
lpText^.Checked:=True;
if (ARow>=TopRowID)and(ARow<=(TopRowID+ShowRowCount-1)) then //在当前显示区域。
DrawCell(ACol,ARow);
end;
end
else
if lpText^.Checked then
begin
lpText^.Checked:=False;
if (ARow>=TopRowID)and(ARow<=(TopRowID+ShowRowCount-1)) then //在当前显示区域。
DrawCell(ACol,ARow);
end;
if Assigned(FOnSetFontColor) then
begin
lColor:=FGridFont.Color;
FOnSetFontColor(Self,ACol,ARow,lColor);
_1BufferBtm.Canvas.Font.Color:=lColor;
for i:=0 to High(Data) do
if (ARow>=TopRowID)and(ARow<=(TopRowID+ShowRowCount-1)) then
DrawCell(i,ARow);
end;
if ARow=SelectionID then
Show_Selection(SelectionID,-1);
end;
end;
procedure TMiniGrid.SetImage(ImageList: TImageList);
begin
FImageList:=ImageList;
end;
procedure TMiniGrid.SetCellImage(ACol, ARow, ImageIndex: integer);
var
lpText: PBufText;
begin
if (not (ACol in[0..High(Data)]))or(ARow<0)or(ARow>(FRowCount-1)) then
Exit;
if Data[ACol].ShowCheckBox then
Exit;
if FImageList=nil then
Exit;
lpText:=Data[ACol].Text;
Inc(lpText,ARow);
lpText^.ImageIndex:=ImageIndex+1; //因为初始化时是0,为了区别+1,在DrawCell中判断是否画时,再-1.
if (ARow>=TopRowID)and(ARow<=(TopRowID+ShowRowCount-1)) then //在当前显示区域。
begin
DrawCell(ACol,ARow); //messagebeep(20);
if FShowSelection and(ARow=SelectionID) then
Show_Selection(SelectionID,-1);
end;
end;
procedure TMiniGrid.SetRowColor(ARow, Color: TColor);
var
lpText: PBufText;
i: integer;
begin
if (ARow<0)or(ARow>(FRowCount-1)) then
Exit;
for i:=0 to High(Data) do
begin
lpText:=Data[i].Text;
Inc(lpText,ARow);
lpText^.BackColor:=Color;
end;
if (ARow>=TopRowID)and(ARow<=(TopRowID+ShowRowCount-1)) then //在当前显示区域。
begin
for i:=0 to High(Data) do
DrawCell(i,ARow); //messagebeep(20);
if FShowSelection and(ARow=SelectionID) then
Show_Selection(SelectionID,-1);
end;
end;
function TMiniGrid.GetRowAt(X, Y: integer): integer;
var
ACol,ARow: integer;
CurrP: TPoint;
begin
CurrP:=Point(X,Y);
if PointToColRow(CurrP,ACol,ARow) then
Result:=ARow
else
Result:=-1;
end;
function TMiniGrid.GetColAt(X, Y: integer): integer;
var
ACol,ARow: integer;
CurrP: TPoint;
begin
CurrP:=Point(X,Y);
if PointToColRow(CurrP,ACol,ARow) then
Result:=ACol
else
Result:=-1;
end;
function TMiniGrid.GetSelected: integer;
begin
if FShowSelection then
Result:=SelectionID
else
Result:=-1;
end;
function TMiniGrid.Delete(ARow: integer): Boolean;
var
i: integer;
begin
Result:=False;
if (FRowCount<1)or(ARow<0)or(ARow>=FRowCount) then
Exit;
for i:=0 to High(Data) do
begin
if Data[i].Text<>nil then
begin //再次调整内存大小。
if ARow<(FRowCount-1) then //如果不是最后一条记录。
MoveMemory(Pointer(DWORD(Data[i].Text)+ARow*ROW_BUFSIZE),Pointer(DWORD(Data[i].Text)+(ARow+1)*ROW_BUFSIZE),(FRowCount-1-ARow)*ROW_BUFSIZE);
ReallocMem(Data[i].Text,(FRowCount-1)*ROW_BUFSIZE);
if (FRowCount-1)=0 then
Data[i].Text:=nil;
end;
end;
Result:=True;
Dec(FRowCount,1);
if TopRowID>0 then
Dec(TopRowID);
if SelectionID>=ARow then
if (SelectionID>0)or(FRowCount=0) then
begin
Dec(SelectionID,1);
//FOnSelectChanged(Self,SelectionID);
end;
AdjustParameter;
DrawGrid;
if FShowScrollBar and(ScrollBar<>nil) then
ScrollBar.Change(TopRowID);
end;
function TMiniGrid.Add(ARow: integer): Boolean;
var
i: integer;
begin
Result:=False;
if (ARow<0)or(ARow>FRowCount) then
Exit;
for i:=0 to High(Data) do
begin
if Data[i].Text=nil then //第一次分配。
begin
ReallocMem(Data[i].Text,ROW_BUFSIZE);
ZeroMemory(Data[i].Text,ROW_BUFSIZE);
end
else //再次调整内存大小。
begin
ReallocMem(Data[i].Text,(FRowCount+1)*ROW_BUFSIZE);
if ARow<FRowCount then
MoveMemory(Pointer(DWORD(Data[i].Text)+(ARow+1)*ROW_BUFSIZE),Pointer(DWORD(Data[i].Text)+ARow*ROW_BUFSIZE),(FRowCount-ARow)*ROW_BUFSIZE);
ZeroMemory(Pointer(DWORD(Data[i].Text)+ARow*ROW_BUFSIZE),ROW_BUFSIZE);
end;
end;
if (FRowCount>0)and(SelectionID>=ARow) then
begin
SelectionID:=SelectionID+1;
//FOnSelectChanged(Self,SelectionID);
end;
Inc(FRowCount,1);
//Inc(TopRowID,1);
AdjustParameter;
DrawGrid;
if FShowScrollBar and(ScrollBar<>nil) then
ScrollBar.Change(TopRowID);
end;
procedure TMiniGrid.MouseEnter(var Msg: TMessage);
begin
if Assigned(FOnMouseEnter) then
FOnMouseEnter(Self);
end;
procedure TMiniGrid.MouseLeave(var Msg: TMessage);
begin
if Assigned(FOnMouseLeave) then
FOnMouseLeave(Self);
end;
procedure TMiniGrid.Setis3D(Value: Boolean);
begin
if Fis3D<>Value then
begin
Fis3D:=Value;
Invalidate;
if ScrollBar<>nil then
begin
ScrollBar.is3D:=Value;
ScrollBar.Repaint;
end;
end;
end;
procedure TMiniGrid.WmInputText(var Msg: TMessage);
var
ACol,ARow: integer;
Text: string;
lpEditInfo: PEditCtrlInfo;
begin
lpEditInfo:=PEditCtrlInfo(Msg.WParam);
ACol:=lpEditInfo^.ACol;
ARow:=lpEditInfo^.ARow;
Text:=lpEditInfo^.Text;
lpEditInfo^.Ctrl.Free;
{if lpEditInfo^.Ctrl is TEditBox then
(lpEditInfo^.Ctrl as TEditBox).Free
else
if lpEditInfo^.Ctrl is TComboboxBox then
(lpEditInfo^.Ctrl as TComboboxBox).Free
else
(lpEditInfo^.Ctrl as TDTPickerBox).Free; }
Dispose(lpEditInfo);
SetCells(ACol,ARow,Text);
if Assigned(FOnEditTextChanged) then
OnEditTextChanged(Self,ACol,ARow,Text);
end;
procedure TMiniGrid.SetSelectionColor(Value: TColor);
begin
if FSelectionColor<>Value then
begin
FSelectionColor:=Value;
Invalidate;
end;
end;
{ TTitle }
constructor TTitle.Create(Collection: TCollection);
begin
FWidth:=40;
FAlignment:=taCenter;
FCaption:='';
FShowCheckBox:=False;
inherited Create(Collection);
end;
procedure TTitle.Assign(Source: TPersistent);
begin
if Source is TTitle then
begin
FCaption:=(Source as TTitle).Caption;
FAlignment:=(Source as TTitle).Alignment;
FWidth:=(Source as TTitle).Width;
FShowCheckBox:=(Source as TTitle).ShowCheckBox;
end
else
inherited Assign(Source);
end;
procedure TTitle.SetAlignment(Value: TAlignment);
begin
if FAlignment<>Value then
begin
FAlignment:=Value;
Self.Changed(False);
end;
end;
procedure TTitle.SetCaption(Value: string);
begin
if FCaption<>Value then
begin
FCaption:=Value;
Self.Changed(False);
end;
end;
procedure TTitle.SetWidth(Value: WORD);
begin
if FWidth<>Value then
begin
FWidth:=Value;
Self.Changed(False);
end;
end;
procedure TTitle.SetShowCheckBox(Value: Boolean);
begin
if FShowCheckBox<>Value then
begin
FShowCheckBox:=Value;
Self.Changed(False);
end;
end;
function TTitle.GetDisplayName: string;
begin
Result:=Caption;
if Result='' then
Result:=inherited GetDisplayName;
end;
destructor TTitle.Destroy;
begin
inherited;
end;
{ TTitles }
constructor TTitles.Create(MiniGrid: TMiniGrid);
begin
inherited Create(TTitle);
Self.FMiniGrid:=MiniGrid;
end;
function TTitles.Add: TTitle;
begin
Result:=TTitle(inherited Add);
end;
procedure TTitles.Delete(Index: Integer);
begin
inherited Delete(Index);
end;
function TTitles.GetItem(Index: integer): TTitle;
begin
Result:=TTitle(inherited GetItem(Index));
end;
procedure TTitles.SetItem(Index: integer; Value: TTitle);
begin
inherited SetItem(Index,Value);
end;
procedure TTitles.UpDate(Item: TCollectionItem);
begin
if Item<>nil then
FMiniGrid.UpDateTitle(TTitle(Item))
else
FMiniGrid.UpdateTitles;
end;
{ TMiniScroll }
//BL: Single; //移动滚条一个点代表多少ROW的数量
//RC: integer; //滚条可移动多少个点。
constructor TMiniScroll.Create(AOwner: TComponent);
var
rC,gC,bC: Byte;
i: integer;
begin
inherited Create(AOwner);
ScrlCount:=0; //滚条可移动多少个点。
FHideCount:=0;
FShowRect:=Rect(0,0,0,0);
Canvas.Pen.Color:=RGB(0,200,255);
//Canvas.Brush.Style:=bsClear;
MouseState:=zxcUp;
is3D:=TMiniGrid(AOwner).is3D;
bkBitmap:=TBitmap.Create;
bkBitmap.Height:=2;
bkBitmap.Width:=SCROLLWIDTH;
rC:=0; gC:=0; bC:=0;
for i:=0 to bkBitmap.Width-1 do
begin
bkBitmap.Canvas.Pen.Color:=RGB(255-rC,255-gC,255-bC);
bkBitmap.Canvas.MoveTo(i,0);
bkBitmap.Canvas.LineTo(i,1);
Inc(rC,4);
Inc(gC,3);
Inc(bC,2);
end;
end;
destructor TMiniScroll.Destroy;
begin
bkBitmap.Free;
inherited;
end;
procedure TMiniScroll.MouseDown(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
begin
if Button = mbLeft then
if ScrlCount>0 then
begin
MouseState:=zxcDown;
OldPoint:=Point(X,Y);
Parent.SetFocus;
end;
end;
procedure TMiniScroll.MouseUp(Button: TMouseButton; Shift: TShiftState; X,
Y: Integer);
begin
if Button = mbLeft then
MouseState:=zxcUp;
end;
procedure TMiniScroll.MouseMove(Shift: TShiftState; X, Y: Integer);
var
T,Temp: integer;
begin
if MouseState=zxcDown then //如果鼠标左键按下
begin
T:=Top+Y-OldPoint.Y;
if T<FShowRect.Top then
T:=FShowRect.Top;
if (T+Height)>FShowRect.Bottom then
T:=FShowRect.Bottom-Height;
if T<>Top then
begin
Top:=T;
if Top=FShowRect.Top then
Temp:=0
else
Temp:=Round((Top-FShowRect.Top)*BL);
if Assigned(FOnScroll) then
FOnScroll(Self,Temp);
end;
end;
end;
procedure TMiniScroll.Paint;
begin
Canvas.Brush.Style:=bsClear; //clBtnface;//$00F4F4F4;
if is3D then
Canvas.CopyRect(Rect(0,0,Width,Height*2),bkBitmap.Canvas,Rect(0,0,bkBitmap.Width,bkBitmap.Height));
Canvas.Rectangle(0,0,Width,Height);
end;
procedure TMiniScroll.SetHideCount(Value: integer);
begin
if FHideCount<>Value then
begin
FHideCount:=Value;
if FHideCount<=(FShowRect.Bottom-FShowRect.Top-SCROLLMINHEIGHT) then
ScrlCount:=FHideCount
else
ScrlCount:=FShowRect.Bottom-FShowRect.Top-SCROLLMINHEIGHT;
if FHideCount>0 then
BL:=FHideCount/ScrlCount;
if Value<=0 then
Height:=0
else
Height:=FShowRect.Bottom-FShowRect.Top-ScrlCount;
end;
end;
procedure TMiniScroll.Change(TopRowID: integer);
var
T: integer;
begin
if ScrlCount>0 then
begin
if TopRowID=0 then
T:=FShowRect.Top
else
T:=FShowRect.Top+Round(TopRowID/BL);
if (T+Height)>=FShowRect.Bottom then
Top:=FShowRect.Bottom-Height
else
Top:=T;
end;
Paint;
end;
procedure TMiniScroll.SetShowRect(Value: TRect);
begin
FShowRect:=Value;
Left:=FShowRect.Left;
Top:=FShowRect.Top;
Width:=SCROLLWIDTH;
end;
{ TEditBox }
constructor TEditBox.Create(Aowner: TComponent; bkBoxLabel: TMiniBoxLabel);
begin
inherited Create(Aowner);
EditType:=miniSTR;
Self.BorderStyle:=bsNone;
Self.OnKeyPress:=Self.CustomKeyPress;
bkCtrl:=bkBoxLabel;
end;
procedure TEditBox.ProcessInput;
var
lpEditInfo: PEditCtrlInfo;
begin
New(lpEditInfo);
lpEditInfo^.ACol:=ACol;
lpEditInfo^.ARow:=ARow;
lpEditInfo^.Text:=Self.Text;
lpEditInfo^.Ctrl:=Self;
PostMessage(Parent.Handle,WM_INPUTTEXT,integer(lpEditInfo),0);
end;
procedure TEditBox.CustomKeyPress(Sender: TObject; var Key: Char);
begin
if EditType=miniNUM then
begin
if not(Key in['0'..'9',#8,#13]) then
Key:=#0;
end
else
if EditType=miniSINGLE then
begin
if not(Key in['0'..'9','.',#8,#13]) then
Key:=#0;
end;
if Key=#13 then
begin
Key:=#0;
if (EditType=miniSINGLE)and(Text<>'') then
if Text[1]='.' then
Text:='0'+Text;
//ProcessInput;
Parent.SetFocus;
end;
end;
procedure TEditBox.WmKillFocus(var Msg: TMessage);
begin
inherited;
ProcessInput;
end;
destructor TEditBox.Destroy;
begin
if bkCtrl<>nil then
bkCtrl.Free;
inherited;
end;
{ TComboboxBox }
constructor TComboboxBox.Create(Aowner: TComponent);
begin
inherited;
Self.OnKeyPress:=Self.CustomKeyPress;
Self.OnExit:=Self.CustomExit;
end;
procedure TComboboxBox.CustomExit(Sender: TObject); //不能用WM_KILLFOCUS,可能有子控件响应此消息,造成多次发送
begin
ProcessInput;
end;
procedure TComboboxBox.CustomKeyPress(Sender: TObject; var Key: Char);
begin
if Key=#13 then
begin
Key:=#0;
Parent.SetFocus;
end;
end;
procedure TComboboxBox.ProcessInput;
var
lpEditInfo: PEditCtrlInfo;
begin
New(lpEditInfo);
lpEditInfo^.ACol:=ACol;
lpEditInfo^.ARow:=ARow;
lpEditInfo^.Text:=Self.Text;
lpEditInfo^.Ctrl:=Self;
PostMessage(Parent.Handle,WM_INPUTTEXT,integer(lpEditInfo),0);
end;
{procedure TComboboxBox.WmKillFocus(var Msg: TMessage);
begin
inherited;
//ProcessInput;
end; }
{ TDTPickerBox }
constructor TDTPickerBox.Create(Aowner: TComponent);
begin
inherited;
Self.OnKeyPress:=Self.CustomKeyPress;
end;
procedure TDTPickerBox.CustomKeyPress(Sender: TObject; var Key: Char);
begin
if Key=#13 then
begin
Key:=#0;
Parent.SetFocus;
end;
end;
procedure TDTPickerBox.ProcessInput;
var
lpEditInfo: PEditCtrlInfo;
begin
New(lpEditInfo);
lpEditInfo^.ACol:=ACol;
lpEditInfo^.ARow:=ARow;
lpEditInfo^.Text:=Self.Text;
lpEditInfo^.Ctrl:=Self;
PostMessage(Parent.Handle,WM_INPUTTEXT,integer(lpEditInfo),0);
end;
procedure TDTPickerBox.WmKillFocus(var Msg: TMessage);
begin
inherited;
ProcessInput;
end;
end.