📄 bsdbgrids.pas
字号:
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
procedure Scroll(Distance: Integer); virtual;
procedure SetColumnAttributes; virtual;
procedure SetEditText(ACol, ARow: Longint; const Value: string); override;
function StoreColumns: Boolean;
procedure TimedScroll(Direction: TGridScrollDirection); override;
procedure TitleClick(Column: TbsColumn); dynamic;
procedure TopLeftChanged; override;
function UseRightToLeftAlignmentForField(const AField: TField;
Alignment: TAlignment): Boolean;
function BeginColumnDrag(var Origin, Destination: Integer;
const MousePt: TPoint): Boolean; override;
function CheckColumnDrag(var Origin, Destination: Integer;
const MousePt: TPoint): Boolean; override;
function EndColumnDrag(var Origin, Destination: Integer;
const MousePt: TPoint): Boolean; override;
property Columns: TbsDBGridColumns read FColumns write SetColumns;
property DefaultDrawing: Boolean read FDefaultDrawing write FDefaultDrawing default True;
property DataLink: TbsGridDataLink read FDataLink;
property IndicatorOffset: Byte read FIndicatorOffset;
property LayoutLock: Byte read FLayoutLock;
property Options: TbsDBGridOptions read FOptions write SetOptions
default [dgEditing, dgTitles, dgIndicator, dgColumnResize, dgColLines,
dgRowLines, dgTabs, dgConfirmDelete, dgCancelOnExit];
property ParentColor default False;
property ReadOnly: Boolean read FReadOnly write FReadOnly default False;
property SelectedRows: TbsBookmarkList read FBookmarks;
property TitleFont: TFont read FTitleFont write SetTitleFont;
property UpdateLock: Byte read FUpdateLock;
property SaveMultiSelection: Boolean read
FSaveMultiSelection write FSaveMultiSelection;
property OnColEnter: TNotifyEvent read FOnColEnter write FOnColEnter;
property OnColExit: TNotifyEvent read FOnColExit write FOnColExit;
property OnDrawDataCell: TDrawDataCellEvent read FOnDrawDataCell
write FOnDrawDataCell; { obsolete }
property OnDrawColumnCell: TDrawColumnCellEvent read FOnDrawColumnCell
write FOnDrawColumnCell;
property OnEditButtonClick: TNotifyEvent read FOnEditButtonClick
write FOnEditButtonClick;
property OnColumnMoved: TMovedEvent read FOnColumnMoved write FOnColumnMoved;
property OnCellClick: TDBGridClickEvent read FOnCellClick write FOnCellClick;
property OnTitleClick: TDBGridClickEvent read FOnTitleClick write FOnTitleClick;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure ChangeSkinData; override;
procedure DefaultDrawDataCell(const Rect: TRect; Field: TField;
State: TGridDrawState); { obsolete }
procedure DefaultDrawColumnCell(const Rect: TRect; DataCol: Integer;
Column: TbsColumn; State: TGridDrawState);
procedure DefaultHandler(var Msg); override;
function ExecuteAction(Action: TBasicAction): Boolean; override;
procedure ShowPopupEditor(Column: TbsColumn; X: Integer = Low(Integer);
Y: Integer = Low(Integer)); dynamic;
function UpdateAction(Action: TBasicAction): Boolean; override;
function ValidFieldIndex(FieldIndex: Integer): Boolean;
property SkinMessage: TbsSkinMessage read FSkinMessage write FSkinMessage;
property EditorMode;
property FieldCount: Integer read GetFieldCount;
property Fields[FieldIndex: Integer]: TField read GetFields;
property SelectedField: TField read GetSelectedField write SetSelectedField;
property SelectedIndex: Integer read GetSelectedIndex write SetSelectedIndex;
property DataSource: TDataSource read GetDataSource write SetDataSource;
property PickListBoxSkinDataName: String read FPickListBoxSkinDataName
write FPickListBoxSkinDataName;
property PickListBoxCaptionMode: Boolean read FPickListBoxCaptionMode
write FPickListBoxCaptionMode;
property MouseWheelSupport: Boolean
read FMouseWheelSupport write FMouseWheelSupport;
published
property Font;
end;
TbsSkinDBGrid = class(TbsSkinCustomDBGrid)
public
property Canvas;
property SelectedRows;
published
property DefaultRowHeight;
property DefaultColWidth;
property BiDiMode;
property MouseWheelSupport;
property SkinMessage;
property SaveMultiSelection;
property PickListBoxSkinDataName;
property PickListBoxCaptionMode;
property Align;
property Anchors;
property BorderStyle;
property Color;
property Columns stored False;
property Constraints;
property Ctl3D;
property DataSource;
property DefaultDrawing;
property DragCursor;
property DragKind;
property DragMode;
property Enabled;
property FixedColor;
property Font;
property ImeMode;
property ImeName;
property Options;
property ParentBiDiMode;
property ParentColor;
property ParentCtl3D;
property ParentFont;
property ParentShowHint;
property PopupMenu;
property ReadOnly;
property ShowHint;
property TabOrder;
property TabStop;
property TitleFont;
property Visible;
property OnCellClick;
property OnColEnter;
property OnColExit;
property OnColumnMoved;
property OnDrawDataCell; { obsolete }
property OnDrawColumnCell;
property OnDblClick;
property OnDragDrop;
property OnDragOver;
property OnEditButtonClick;
property OnEndDock;
property OnEndDrag;
property OnEnter;
property OnExit;
property OnKeyDown;
property OnKeyPress;
property OnKeyUp;
property OnMouseDown;
property OnMouseMove;
property OnMouseUp;
property OnStartDock;
property OnStartDrag;
property OnTitleClick;
end;
const
IndicatorWidth = 11;
implementation
uses Math, DBConsts, Dialogs {$IFDEF VER140}, Variants{$ENDIF}
{$IFDEF VER150}, Variants{$ENDIF}, bsConst;
{$R BSDBGRIDS.RES}
const
bmArrow = 'BSDBGARROW';
bmEdit = 'BSDBEDIT';
bmInsert = 'BSDBINSERT';
bmMultiDot = 'BSDBMULTIDOT';
bmMultiArrow = 'BSDBMULTIARROW';
MaxMapSize = (MaxInt div 2) div SizeOf(Integer); { 250 million }
type
TParentGrid = class(TbsSkinCustomDBGrid);
{ Error reporting }
procedure RaiseGridError(const S: string);
begin
// raise EInvalidGridOperation.Create(S);
end;
procedure KillMessage(Wnd: HWnd; Msg: Integer);
var
M: TMsg;
begin
M.Message := 0;
if PeekMessage(M, Wnd, Msg, Msg, pm_Remove) and (M.Message = WM_QUIT) then
PostQuitMessage(M.wparam);
end;
{ TDBGridInplaceEdit }
type
TEditStyle = (esSimple, esEllipsis, esPickList, esDataList);
TbsDBPopupListbox = class;
TDBGridInplaceEdit = class(TbsSkinInplaceEdit)
private
FButtonWidth: Integer;
FDataList: TDBLookupListBox;
FPickList: TbsDBPopupListbox;
FActiveList: TWinControl;
FLookupSource: TDatasource;
FEditStyle: TEditStyle;
FListVisible: Boolean;
FTracking: Boolean;
FPressed: Boolean;
procedure ListMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure SetEditStyle(Value: TEditStyle);
procedure StopTracking;
procedure TrackButton(X,Y: Integer);
procedure CMCancelMode(var Message: TCMCancelMode); message CM_CancelMode;
procedure WMCancelMode(var Message: TMessage); message WM_CancelMode;
procedure WMKillFocus(var Message: TMessage); message WM_KillFocus;
procedure WMLButtonDblClk(var Message: TWMLButtonDblClk); message wm_LButtonDblClk;
procedure WMPaint(var Message: TWMPaint); message wm_Paint;
procedure WMSetCursor(var Message: TWMSetCursor); message WM_SetCursor;
function OverButton(const P: TPoint): Boolean;
function ButtonRect: TRect;
protected
function IsValidChar(Key: Char): Boolean;
procedure KeyPress(var Key: Char); override;
procedure BoundsChanged; override;
procedure DoDropDownKeys(var Key: Word; Shift: TShiftState);
procedure DropDown;
procedure KeyDown(var Key: Word; Shift: TShiftState); override;
procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer); override;
procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer); override;
procedure PaintWindow(DC: HDC); override;
procedure UpdateContents; override;
procedure WndProc(var Message: TMessage); override;
property EditStyle: TEditStyle read FEditStyle write SetEditStyle;
property ActiveList: TWinControl read FActiveList write FActiveList;
property DataList: TDBLookupListBox read FDataList;
property PickList: TbsDBPopupListbox read FPickList;
public
procedure CloseUp(Accept: Boolean);
constructor Create(Owner: TComponent); override;
end;
{ TbsDBPopupListbox }
TbsDBPopupListbox = class(TbsPopupListBox)
protected
FListBoxWindowProc: TWndMethod;
procedure ListBoxWindowProcHook(var Message: TMessage);
procedure ListBoxMouseMove(Sender: TObject; Shift: TShiftState;
X, Y: Integer);
public
constructor Create(Owner: TComponent); override;
destructor Destroy; override;
end;
constructor TbsDBPopupListbox.Create(Owner: TComponent);
begin
inherited;
FListBoxWindowProc := ListBox.WindowProc;
ListBox.WindowProc := ListBoxWindowProcHook;
ListBox.OnMouseMove := ListBoxMouseMove;
end;
destructor TbsDBPopupListbox.Destroy;
begin
inherited;
end;
procedure TbsDBPopupListbox.ListBoxWindowProcHook(var Message: TMessage);
var
FOld: Boolean;
begin
FOld := True;
case Message.Msg of
WM_LBUTTONUP:
begin
TDBGridInPlaceEdit(Owner).CloseUp(True);
end;
WM_RBUTTONDOWN, WM_RBUTTONUP,
WM_MBUTTONDOWN, WM_MBUTTONUP,
WM_LBUTTONDOWN:
begin
FOLd := False;
end;
WM_MOUSEACTIVATE:
begin
Message.Result := MA_NOACTIVATE;
end;
end;
if FOld then FListBoxWindowProc(Message);
end;
procedure TbsDBPopupListbox.ListBoxMouseMove(Sender: TObject; Shift: TShiftState;
X, Y: Integer);
var
Index: Integer;
begin
Index := ListBox.ItemAtPos(Point (X, Y), True);
if (Index >= 0) and (Index < Items.Count)
then
ItemIndex := Index;
end;
constructor TDBGridInplaceEdit.Create(Owner: TComponent);
begin
inherited Create(Owner);
FLookupSource := TDataSource.Create(Self);
FButtonWidth := GetSystemMetrics(SM_CXVSCROLL);
FEditStyle := esSimple;
end;
procedure TDBGridInplaceEdit.KeyPress(var Key: Char);
begin
if not IsValidChar(Key) then
begin
Key := #0;
MessageBeep(0)
end;
if Key <> #0 then inherited KeyPress(Key);
end;
function TDBGridInplaceEdit.IsValidChar(Key: Char): Boolean;
var
CharCode: Integer;
DBGrid: TbsSkinCustomDBGrid;
FT: TFieldType;
CellIndex: Integer;
begin
DBGrid := TbsSkinCustomDBGrid(Grid);
if dgIndicator in DBGrid.Options
then
CellIndex := DBGrid.Col - 1
else
CellIndex := DBGrid.Col;
FT := DBGrid.Columns[CellIndex].Field.DataType;
if (Key = '-') or (Key = '+') or (Key = DecimalSeparator)
then
begin
case FT of
ftSmallint, ftInteger,
ftFloat, ftCurrency:
Result := not (
((Key = DecimalSeparator) and
(Pos(DecimalSeparator, Text) <> 0)) or
((Key = '-') and (Pos('-', Text) <> 0)) or
((Key = '+') and (Pos('+', Text) <> 0)));
else
Result := True;
end
end
else
Result := True;
end;
procedure TDBGridInplaceEdit.BoundsChanged;
var
R: TRect;
begin
Windows.SetRect(R, 2, 2, Width - 2, Height);
if FEditStyle <> esSimple then
if not TbsSkinCustomDBGrid(Owner).UseRightToLeftAlignment then
Dec(R.Right, FButtonWidth)
else
Inc(R.Left, FButtonWidth - 2);
SendMessage(Handle, EM_SETRECTNP, 0, LongInt(@R));
SendMessage(Handle, EM_SCROLLCARET, 0, 0);
if SysLocale.FarEast then
SetImeCompositionWindow(Font, R.Left, R.Top);
end;
procedure TDBGridInplaceEdit.CloseUp(Accept: Boolean);
var
MasterField: TField;
ListValue: Variant;
begin
if FListVisible then
begin
if GetCapture <> 0 then SendMessage(GetCapture, WM_CANCELMODE, 0, 0);
if FActiveList = FDataList then
ListValue := FDataList.KeyValue
else
if FPickList.ItemIndex <> -1 then
ListValue := FPickList.Items[FPicklist.ItemIndex];
TbsDBPopupListBox(FActiveList).Hide;
FActiveList.Visible := False;
FListVisible := False;
if Assigned(FDataList) then
FDataList.ListSource := nil;
FLookupSource.Dataset := nil;
Invalidate;
if Accept then
if FActiveList = FDataList then
with TbsSkinCustomDBGrid(Grid), Columns[SelectedIndex].Field do
begin
MasterField := DataSet.FieldByName(KeyFields);
if MasterField.CanModify and FDataLink.Edit then
MasterField.Value := ListValue;
end
else
if (not VarIsNull(ListValue)) and EditCanModify then
with TbsSkinCustomDBGrid(Grid), Columns[SelectedIndex].Field do
Text := ListValue;
end;
end;
procedure TDBGridInplaceEdit.DoDropDownKeys(var Key: Word; Shift: TShiftState);
begin
case Key of
VK_UP, VK_DOWN:
if ssAlt in Shift then
begin
if FListVisible then CloseUp(True) else DropDown;
Key := 0;
end;
VK_RETURN, VK_ESCAPE:
if FListVisible and not (ssAlt in Shift) then
begin
CloseUp(Key = VK_RETURN);
Key := 0;
end;
end;
end;
procedure TDBGridInplaceEdit.DropDown;
var
P: TPoint;
I,J,Y: Integer;
Column: TbsColumn;
begin
if not FListVisible and Assigned(FActiveList) then
begin
FActiveList.Width := Width;
with TbsSkinCustomDBGrid(Grid) do
Column := Columns[SelectedIndex];
if FActiveList = FDataList then
with Column.Field do
begin
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -