📄 oldschooldbnavigator.pas
字号:
{*******************************************************}
{ }
{ Borland Delphi Visual Component Library }
{ }
{ Copyright (c) 1995,99 Inprise Corporation }
{ }
{*******************************************************}
{$G+}
unit OldSchoolDBNavigator;
{$R-,H+,X+}
interface
uses Variants, Windows, SysUtils, Messages, Controls, Forms, Classes,
Graphics, Menus, StdCtrls, ExtCtrls, Mask, Buttons, ComCtrls, DB, DBCtrls;
type
{ TOldSchoolDBNavigator }
TOSDataLink = class;
TOSButton = class;
TOSButtonStyle = set of (nsAllowTimer, nsFocusRect);
TOldSchoolDBNavigator = class (TCustomPanel)
private
FDataLink: TOSDataLink;
FVisibleButtons: TButtonSet;
FHints: TStrings;
FDefHints: TStrings;
ButtonWidth: Integer;
MinBtnSize: TPoint;
FOnNavClick: ENavClick;
FBeforeAction: ENavClick;
FocusedButton: TNavigateBtn;
FConfirmDelete: Boolean;
FFlat: Boolean;
procedure BtnMouseDown (Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure ClickHandler(Sender: TObject);
function GetDataSource: TDataSource;
function GetHints: TStrings;
procedure HintsChanged(Sender: TObject);
procedure InitButtons;
procedure InitHints;
procedure SetDataSource(Value: TDataSource);
procedure SetFlat(Value: Boolean);
procedure SetHints(Value: TStrings);
procedure SetSize(var W: Integer; var H: Integer);
procedure SetVisible(Value: TButtonSet);
procedure WMSize(var Message: TWMSize); message WM_SIZE;
procedure WMSetFocus(var Message: TWMSetFocus); message WM_SETFOCUS;
procedure WMKillFocus(var Message: TWMKillFocus); message WM_KILLFOCUS;
procedure WMGetDlgCode(var Message: TWMGetDlgCode); message WM_GETDLGCODE;
procedure CMEnabledChanged(var Message: TMessage); message CM_ENABLEDCHANGED;
procedure WMWindowPosChanging(var Message: TWMWindowPosChanging); message WM_WINDOWPOSCHANGING;
protected
Buttons: array[TNavigateBtn] of TOSButton;
procedure DataChanged;
procedure EditingChanged;
procedure ActiveChanged;
procedure Loaded; override;
procedure KeyDown(var Key: Word; Shift: TShiftState); override;
procedure Notification(AComponent: TComponent;
Operation: TOperation); override;
procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override;
procedure CalcMinSize(var W, H: Integer);
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override;
procedure BtnClick(Index: TNavigateBtn); virtual;
published
property DataSource: TDataSource read GetDataSource write SetDataSource;
property VisibleButtons: TButtonSet read FVisibleButtons write SetVisible
default [nbFirst, nbPrior, nbNext, nbLast, nbInsert, nbDelete,
nbEdit, nbPost, nbCancel, nbRefresh];
property Align;
property Anchors;
property Constraints;
property DragCursor;
property DragKind;
property DragMode;
property Enabled;
property Flat: Boolean read FFlat write SetFlat default False;
property Ctl3D;
property Hints: TStrings read GetHints write SetHints;
property ParentCtl3D;
property ParentShowHint;
property PopupMenu;
property ConfirmDelete: Boolean read FConfirmDelete write FConfirmDelete default True;
property ShowHint;
property TabOrder;
property TabStop;
property Visible;
property BeforeAction: ENavClick read FBeforeAction write FBeforeAction;
property OnClick: ENavClick read FOnNavClick write FOnNavClick;
property OnContextPopup;
property OnDblClick;
property OnDragDrop;
property OnDragOver;
property OnEndDock;
property OnEndDrag;
property OnEnter;
property OnExit;
property OnResize;
property OnStartDock;
property OnStartDrag;
end;
{ TOSButton }
TOSButton = class(TSpeedButton)
private
FIndex: TNavigateBtn;
FNavStyle: TOSButtonStyle;
FRepeatTimer: TTimer;
procedure TimerExpired(Sender: TObject);
protected
procedure Paint; override;
procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer); override;
procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer); override;
public
destructor Destroy; override;
property NavStyle: TOSButtonStyle read FNavStyle write FNavStyle;
property Index : TNavigateBtn read FIndex write FIndex;
end;
{ TOSDataLink }
TOSDataLink = class(TDataLink)
private
FNavigator: TOldSchoolDBNavigator;
protected
procedure EditingChanged; override;
procedure DataSetChanged; override;
procedure ActiveChanged; override;
public
constructor Create(ANav: TOldSchoolDBNavigator);
destructor Destroy; override;
end;
function OkToChangeFieldAlignment(AField: TField; Alignment: TAlignment): Boolean;
function DBUseRightToLeftAlignment(AControl: TControl; AField: TField): Boolean;
procedure Register;
implementation
uses DBLogDlg, DBPWDlg, Clipbrd, DBConsts, VDBConsts, Dialogs, Math, Themes;
{$R DBCtrls.res}
{ BiDiMode support routines }
function OkToChangeFieldAlignment(AField: TField; Alignment: TAlignment): Boolean;
begin
{ dont change the alignment for these fields:
ftSmallInt ftInteger ftWord ftFloat ftCurrency
ftBCD ftDate ftTime ftDateTime ftAutoInc
ftTimeStamp ftFMTBcd}
if Assigned(AField) then with AField do
Result := (DataType < ftSmallInt) or
(DataType = ftBoolean) or
((DataType > ftDateTime) and (DataType <> ftAutoInc)
and (DataType <> ftFMTBcd))
else
Result := Alignment <> taCenter;
end;
{ AField is needed because TDBLookupComboBox, for its combobox, uses FListField
for its alignment characteristics not FField }
function DBUseRightToLeftAlignment(AControl: TControl; AField: TField): Boolean;
var
AAlignment: TAlignment;
begin
if Assigned(AField) then
AAlignment := AField.Alignment
else
AAlignment := taLeftJustify;
Result := (SysLocale.MiddleEast) and (AControl.BiDiMode = bdRightToLeft) and
(OkToChangeFieldAlignment(AField, AAlignment));
end;
{ TOldSchoolDBNavigator }
var
BtnTypeName: array[TNavigateBtn] of PChar = ('FIRST', 'PRIOR', 'NEXT',
'LAST', 'INSERT', 'DELETE', 'EDIT', 'POST', 'CANCEL', 'REFRESH');
BtnHintId: array[TNavigateBtn] of Pointer = (@SFirstRecord, @SPriorRecord,
@SNextRecord, @SLastRecord, @SInsertRecord, @SDeleteRecord, @SEditRecord,
@SPostEdit, @SCancelEdit, @SRefreshRecord);
constructor TOldSchoolDBNavigator.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
ControlStyle := ControlStyle - [csAcceptsControls, csSetCaption] + [csOpaque];
if not NewStyleControls then ControlStyle := ControlStyle + [csFramed];
FDataLink := TOSDataLink.Create(Self);
FVisibleButtons := [nbFirst, nbPrior, nbNext, nbLast, nbInsert,
nbDelete, nbEdit, nbPost, nbCancel, nbRefresh];
FHints := TStringList.Create;
TStringList(FHints).OnChange := HintsChanged;
InitButtons;
InitHints;
BevelOuter := bvNone;
BevelInner := bvNone;
Width := 241;
Height := 25;
ButtonWidth := 0;
FocusedButton := nbFirst;
FConfirmDelete := True;
FullRepaint := False;
end;
destructor TOldSchoolDBNavigator.Destroy;
begin
FDefHints.Free;
FDataLink.Free;
FHints.Free;
FDataLink := nil;
inherited Destroy;
end;
procedure TOldSchoolDBNavigator.InitButtons;
var
I: TNavigateBtn;
Btn: TOSButton;
X: Integer;
ResName: string;
begin
MinBtnSize := Point(20, 18);
X := 0;
for I := Low(Buttons) to High(Buttons) do
begin
Btn := TOSButton.Create (Self);
Btn.Flat := Flat;
Btn.Index := I;
Btn.Visible := I in FVisibleButtons;
Btn.Enabled := True;
Btn.SetBounds (X, 0, MinBtnSize.X, MinBtnSize.Y);
FmtStr(ResName, 'dbn_%s', [BtnTypeName[I]]);
Btn.Glyph.LoadFromResourceName(HInstance, ResName);
Btn.NumGlyphs := 2;
Btn.Enabled := False;
Btn.Enabled := True;
Btn.OnClick := ClickHandler;
Btn.OnMouseDown := BtnMouseDown;
Btn.Parent := Self;
Buttons[I] := Btn;
X := X + MinBtnSize.X;
end;
Buttons[nbPrior].NavStyle := Buttons[nbPrior].NavStyle + [nsAllowTimer];
Buttons[nbNext].NavStyle := Buttons[nbNext].NavStyle + [nsAllowTimer];
end;
procedure TOldSchoolDBNavigator.InitHints;
var
I: Integer;
J: TNavigateBtn;
begin
if not Assigned(FDefHints) then
begin
FDefHints := TStringList.Create;
for J := Low(Buttons) to High(Buttons) do
FDefHints.Add(LoadResString(BtnHintId[J]));
end;
for J := Low(Buttons) to High(Buttons) do
Buttons[J].Hint := FDefHints[Ord(J)];
J := Low(Buttons);
for I := 0 to (FHints.Count - 1) do
begin
if FHints.Strings[I] <> '' then Buttons[J].Hint := FHints.Strings[I];
if J = High(Buttons) then Exit;
Inc(J);
end;
end;
procedure TOldSchoolDBNavigator.HintsChanged(Sender: TObject);
begin
InitHints;
end;
procedure TOldSchoolDBNavigator.SetFlat(Value: Boolean);
var
I: TNavigateBtn;
begin
if FFlat <> Value then
begin
FFlat := Value;
for I := Low(Buttons) to High(Buttons) do
Buttons[I].Flat := Value;
end;
end;
procedure TOldSchoolDBNavigator.SetHints(Value: TStrings);
begin
if Value.Text = FDefHints.Text then
FHints.Clear else
FHints.Assign(Value);
end;
function TOldSchoolDBNavigator.GetHints: TStrings;
begin
if (csDesigning in ComponentState) and not (csWriting in ComponentState) and
not (csReading in ComponentState) and (FHints.Count = 0) then
Result := FDefHints else
Result := FHints;
end;
procedure TOldSchoolDBNavigator.GetChildren(Proc: TGetChildProc; Root: TComponent);
begin
end;
procedure TOldSchoolDBNavigator.Notification(AComponent: TComponent;
Operation: TOperation);
begin
inherited Notification(AComponent, Operation);
if (Operation = opRemove) and (FDataLink <> nil) and
(AComponent = DataSource) then DataSource := nil;
end;
procedure TOldSchoolDBNavigator.SetVisible(Value: TButtonSet);
var
I: TNavigateBtn;
W, H: Integer;
begin
W := Width;
H := Height;
FVisibleButtons := Value;
for I := Low(Buttons) to High(Buttons) do
Buttons[I].Visible := I in FVisibleButtons;
SetSize(W, H);
if (W <> Width) or (H <> Height) then
inherited SetBounds (Left, Top, W, H);
Invalidate;
end;
procedure TOldSchoolDBNavigator.CalcMinSize(var W, H: Integer);
var
Count: Integer;
I: TNavigateBtn;
begin
if (csLoading in ComponentState) then Exit;
if Buttons[nbFirst] = nil then Exit;
Count := 0;
for I := Low(Buttons) to High(Buttons) do
if Buttons[I].Visible then
Inc(Count);
if Count = 0 then Inc(Count);
W := Max(W, Count * MinBtnSize.X);
H := Max(H, MinBtnSize.Y);
if Align = alNone then W := (W div Count) * Count;
end;
procedure TOldSchoolDBNavigator.SetSize(var W: Integer; var H: Integer);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -