2 {*****************************************************************************}
4 { Tnt Delphi Unicode Controls }
5 { http://www.tntware.com/delphicontrols/unicode/ }
8 { Copyright (c) 2002-2007, Troy Wolbrink (troy.wolbrink@tntware.com) }
10 {*****************************************************************************}
14 {$INCLUDE TntCompilers.inc}
19 Classes
, TntClasses
, Controls
, Windows
, Grids
, DBGrids
, Messages
, DBCtrls
, DB
, TntStdCtrls
;
22 {TNT-WARN TColumnTitle}
23 TTntColumnTitle
= class(TColumnTitle
{TNT-ALLOW TColumnTitle})
26 procedure SetInheritedCaption(const Value
: AnsiString
);
27 function GetCaption
: WideString
;
28 procedure SetCaption(const Value
: WideString
);
29 function IsCaptionStored
: Boolean;
31 procedure DefineProperties(Filer
: TFiler
); override;
33 procedure Assign(Source
: TPersistent
); override;
34 procedure RestoreDefaults
; override;
35 function DefaultCaption
: WideString
;
37 property Caption
: WideString read GetCaption write SetCaption stored IsCaptionStored
;
42 TTntColumn
= class(TColumn
{TNT-ALLOW TColumn})
44 FWidePickList
: TTntStrings
;
45 function GetWidePickList
: TTntStrings
;
46 procedure SetWidePickList(const Value
: TTntStrings
);
47 procedure HandlePickListChange(Sender
: TObject
);
48 function GetTitle
: TTntColumnTitle
;
49 procedure SetTitle(const Value
: TTntColumnTitle
);
51 procedure DefineProperties(Filer
: TFiler
); override;
52 function CreateTitle
: TColumnTitle
{TNT-ALLOW TColumnTitle}; override;
54 destructor Destroy
; override;
55 property WidePickList
: TTntStrings read GetWidePickList write SetWidePickList
;
58 property PickList
{TNT-ALLOW PickList}: TTntStrings read GetWidePickList write SetWidePickList
;
59 property Title
: TTntColumnTitle read GetTitle write SetTitle
;
62 { TDBGridInplaceEdit adds support for a button on the in-place editor,
63 which can be used to drop down a table-based lookup list, a stringlist-based
64 pick list, or (if button style is esEllipsis) fire the grid event
68 TDBGridInplaceEdit
{TNT-ALLOW TDBGridInplaceEdit} = class(TInplaceEditList
)
70 {$IFDEF COMPILER_6} // verified against VCL source in Delphi 6 and BCB 6
71 FDataList
: TDBLookupListBox
; // 1st field - Delphi/BCB 6 TCustomDBGrid assumes this
72 FUseDataList
: Boolean; // 2nd field - Delphi/BCB 6 TCustomDBGrid assumes this
74 {$IFDEF DELPHI_7} // verified against VCL source in Delphi 7
75 FDataList
: TDBLookupListBox
; // 1st field - Delphi 7 TCustomDBGrid assumes this
76 FUseDataList
: Boolean; // 2nd field - Delphi 7 TCustomDBGrid assumes this
78 {$IFDEF DELPHI_9} // verified against VCL source in Delphi 9
79 FDataList
: TDBLookupListBox
; // 1st field - Delphi 9 TCustomDBGrid assumes this
80 FUseDataList
: Boolean; // 2nd field - Delphi 9 TCustomDBGrid assumes this
82 {$IFDEF DELPHI_10} // verified against VCL source in Delphi 10
83 FDataList
: TDBLookupListBox
; // 1st field - Delphi 10 TCustomDBGrid assumes this
84 FUseDataList
: Boolean; // 2nd field - Delphi 10 TCustomDBGrid assumes this
86 FLookupSource
: TDatasource
;
87 FWidePickListBox
: TTntCustomListbox
;
88 function GetWidePickListBox
: TTntCustomListbox
;
90 procedure CloseUp(Accept
: Boolean); override;
91 procedure DoEditButtonClick
; override;
92 procedure DropDown
; override;
93 procedure UpdateContents
; override;
94 property UseDataList
: Boolean read FUseDataList
;
96 constructor Create(Owner
: TComponent
); override;
97 property DataList
: TDBLookupListBox read FDataList
;
98 property WidePickListBox
: TTntCustomListbox read GetWidePickListBox
;
102 {TNT-WARN TDBGridInplaceEdit}
103 TTntDBGridInplaceEdit
= class(TDBGridInplaceEdit
{TNT-ALLOW TDBGridInplaceEdit})
105 FInDblClick
: Boolean;
106 FBlockSetText
: Boolean;
107 procedure WMSetText(var Message: TWMSetText
); message WM_SETTEXT
;
109 function GetText
: WideString
; virtual;
110 procedure SetText(const Value
: WideString
); virtual;
112 procedure CreateWindowHandle(const Params
: TCreateParams
); override;
113 procedure UpdateContents
; override;
114 procedure DblClick
; override;
116 property Text: WideString read GetText write SetText
;
119 {TNT-WARN TDBGridColumns}
120 TTntDBGridColumns
= class(TDBGridColumns
{TNT-ALLOW TDBGridColumns})
122 function GetColumn(Index
: Integer): TTntColumn
;
123 procedure SetColumn(Index
: Integer; const Value
: TTntColumn
);
125 function Add
: TTntColumn
;
126 property Items
[Index
: Integer]: TTntColumn read GetColumn write SetColumn
; default
;
129 TTntGridDataLink
= class(TGridDataLink
)
131 OriginalSetText
: TFieldSetTextEvent
;
132 procedure GridUpdateFieldText(Sender
: TField
; const Text: AnsiString
);
134 procedure UpdateData
; override;
135 procedure RecordChanged(Field
: TField
); override;
138 {TNT-WARN TCustomDBGrid}
139 TTntCustomDBGrid
= class(TCustomDBGrid
{TNT-ALLOW TCustomDBGrid})
141 FEditText
: WideString
;
142 function GetHint
: WideString
;
143 procedure SetHint(const Value
: WideString
);
144 function IsHintStored
: Boolean;
145 procedure WMChar(var Msg
: TWMChar
); message WM_CHAR
;
146 function GetColumns
: TTntDBGridColumns
;
147 procedure SetColumns(const Value
: TTntDBGridColumns
);
149 procedure CreateWindowHandle(const Params
: TCreateParams
); override;
150 procedure ShowEditorChar(Ch
: WideChar
); dynamic;
151 procedure DefineProperties(Filer
: TFiler
); override;
152 function GetActionLinkClass
: TControlActionLinkClass
; override;
153 procedure ActionChange(Sender
: TObject
; CheckDefaults
: Boolean); override;
154 function CreateColumns
: TDBGridColumns
{TNT-ALLOW TDBGridColumns}; override;
155 property Columns
: TTntDBGridColumns read GetColumns write SetColumns
;
156 function CreateEditor
: TInplaceEdit
{TNT-ALLOW TInplaceEdit}; override;
157 function CreateDataLink
: TGridDataLink
; override;
158 function GetEditText(ACol
, ARow
: Longint): WideString
; reintroduce
;
159 procedure DrawCell(ACol
, ARow
: Integer; ARect
: TRect
; AState
: TGridDrawState
); override;
160 procedure SetEditText(ACol
, ARow
: Longint; const Value
: AnsiString
); override;
162 procedure DefaultDrawColumnCell(const Rect
: TRect
; DataCol
: Integer;
163 Column
: TTntColumn
; State
: TGridDrawState
); dynamic;
164 procedure DefaultDrawDataCell(const Rect
: TRect
; Field
: TField
;
165 State
: TGridDrawState
);
167 property Hint
: WideString read GetHint write SetHint stored IsHintStored
;
171 TTntDBGrid
= class(TTntCustomDBGrid
)
174 property SelectedRows
;
179 property BorderStyle
;
181 property Columns stored
False; //StoreColumns;
182 property Constraints
;
185 property DefaultDrawing
;
195 property ParentBiDiMode
;
196 property ParentColor
;
197 property ParentCtl3D
;
199 property ParentShowHint
;
207 property OnCellClick
;
210 property OnColumnMoved
;
211 property OnDrawDataCell
; { obsolete }
212 property OnDrawColumnCell
;
216 property OnEditButtonClick
;
224 {$IFDEF COMPILER_9_UP}
225 property OnMouseActivate
;
227 property OnMouseDown
;
228 {$IFDEF COMPILER_10_UP}
229 property OnMouseEnter
;
230 property OnMouseLeave
;
232 property OnMouseMove
;
234 property OnMouseWheel
;
235 property OnMouseWheelDown
;
236 property OnMouseWheelUp
;
237 property OnStartDock
;
238 property OnStartDrag
;
239 property OnTitleClick
;
245 SysUtils
, TntControls
, Math
, Variants
, Forms
,
246 TntGraphics
, Graphics
, TntDB
, TntActnList
, TntSysUtils
, TntWindows
;
250 procedure TTntColumnTitle
.DefineProperties(Filer
: TFiler
);
253 TntPersistent_AfterInherited_DefineProperties(Filer
, Self
);
256 function TTntColumnTitle
.DefaultCaption
: WideString
;
260 Field
:= Column
.Field
;
261 if Assigned(Field
) then
262 Result
:= Field
.DisplayName
264 Result
:= Column
.FieldName
;
267 function TTntColumnTitle
.IsCaptionStored
: Boolean;
269 Result
:= (cvTitleCaption
in Column
.AssignedValues
) and
270 (FCaption
<> DefaultCaption
);
273 procedure TTntColumnTitle
.SetInheritedCaption(const Value
: AnsiString
);
275 inherited Caption
:= Value
;
278 function TTntColumnTitle
.GetCaption
: WideString
;
280 if cvTitleCaption
in Column
.AssignedValues
then
281 Result
:= GetSyncedWideString(FCaption
, inherited Caption
)
283 Result
:= DefaultCaption
;
286 procedure TTntColumnTitle
.SetCaption(const Value
: WideString
);
288 if not (Column
as TTntColumn
).IsStored
then
289 inherited Caption
:= Value
291 if (cvTitleCaption
in Column
.AssignedValues
) and (Value
= FCaption
) then Exit
;
292 SetSyncedWideString(Value
, FCaption
, inherited Caption
, SetInheritedCaption
);
296 procedure TTntColumnTitle
.Assign(Source
: TPersistent
);
298 inherited Assign(Source
);
299 if Source
is TTntColumnTitle
then
301 if cvTitleCaption
in TTntColumnTitle(Source
).Column
.AssignedValues
then
302 Caption
:= TTntColumnTitle(Source
).Caption
;
306 procedure TTntColumnTitle
.RestoreDefaults
;
314 procedure TTntColumn
.DefineProperties(Filer
: TFiler
);
317 TntPersistent_AfterInherited_DefineProperties(Filer
, Self
);
320 function TTntColumn
.CreateTitle
: TColumnTitle
{TNT-ALLOW TColumnTitle};
322 Result
:= TTntColumnTitle
.Create(Self
);
325 function TTntColumn
.GetTitle
: TTntColumnTitle
;
327 Result
:= (inherited Title
) as TTntColumnTitle
;
330 procedure TTntColumn
.SetTitle(const Value
: TTntColumnTitle
);
332 inherited Title
:= Value
;
335 function TTntColumn
.GetWidePickList
: TTntStrings
;
337 if FWidePickList
= nil then begin
338 FWidePickList
:= TTntStringList
.Create
;
339 TTntStringList(FWidePickList
).OnChange
:= HandlePickListChange
;
341 Result
:= FWidePickList
;
344 procedure TTntColumn
.SetWidePickList(const Value
: TTntStrings
);
349 FWidePickList
:= nil;
350 (inherited PickList
{TNT-ALLOW PickList}).Clear
;
353 WidePickList
.Assign(Value
);
356 procedure TTntColumn
.HandlePickListChange(Sender
: TObject
);
358 inherited PickList
{TNT-ALLOW PickList}.Assign(WidePickList
);
361 destructor TTntColumn
.Destroy
;
369 TTntPopupListbox
= class(TTntCustomListbox
)
371 FSearchText
: WideString
;
372 FSearchTickCount
: Longint;
374 procedure CreateParams(var Params
: TCreateParams
); override;
375 procedure CreateWnd
; override;
376 procedure WMChar(var Message: TWMChar
); message WM_CHAR
;
377 procedure KeyPressW(var Key
: WideChar
);
378 procedure MouseUp(Button
: TMouseButton
; Shift
: TShiftState
; X
, Y
: Integer); override;
381 procedure TTntPopupListbox
.CreateParams(var Params
: TCreateParams
);
383 inherited CreateParams(Params
);
386 Style
:= Style
or WS_BORDER
;
387 ExStyle
:= WS_EX_TOOLWINDOW
or WS_EX_TOPMOST
;
388 AddBiDiModeExStyle(ExStyle
);
389 WindowClass
.Style
:= CS_SAVEBITS
;
393 procedure TTntPopupListbox
.CreateWnd
;
396 Windows
.SetParent(Handle
, 0);
397 CallWindowProc(DefWndProc
, Handle
, wm_SetFocus
, 0, 0);
400 procedure TTntPopupListbox
.WMChar(var Message: TWMChar
);
404 Key
:= GetWideCharFromWMCharMsg(Message);
406 SetWideCharForWMCharMsg(Message, Key
);
410 procedure TTntPopupListbox
.KeypressW(var Key
: WideChar
);
415 #8, #27: FSearchText
:= '';
418 TickCount
:= GetTickCount
;
419 if TickCount
- FSearchTickCount
> 2000 then FSearchText
:= '';
420 FSearchTickCount
:= TickCount
;
421 if Length(FSearchText
) < 32 then FSearchText
:= FSearchText
+ Key
;
422 if IsWindowUnicode(Handle
) then
423 SendMessageW(Handle
, LB_SelectString
, WORD(-1), Longint(PWideChar(FSearchText
)))
425 SendMessageA(Handle
, LB_SelectString
, WORD(-1), Longint(PAnsiChar(AnsiString(FSearchText
))));
431 procedure TTntPopupListbox
.MouseUp(Button
: TMouseButton
; Shift
: TShiftState
;
434 inherited MouseUp(Button
, Shift
, X
, Y
);
435 (Owner
as TDBGridInplaceEdit
{TNT-ALLOW TDBGridInplaceEdit}).CloseUp((X
>= 0) and (Y
>= 0) and
436 (X
< Width
) and (Y
< Height
));
439 { TTntPopupDataList }
441 TTntPopupDataList
= class(TPopupDataList
)
443 procedure Paint
; override;
446 procedure TTntPopupDataList
.Paint
;
448 FRecordIndex
: Integer;
449 FRecordCount
: Integer;
450 FKeySelected
: Boolean;
453 procedure UpdateListVars
;
457 FRecordIndex
:= ListLink
.ActiveRecord
;
458 FRecordCount
:= ListLink
.RecordCount
;
459 FKeySelected
:= not VarIsNull(KeyValue
) or
460 not ListLink
.DataSet
.BOF
;
465 FKeySelected
:= False;
469 if ListLink
.Active
and (KeyField
<> '') then
470 FKeyField
:= GetFieldProperty(ListLink
.DataSet
, Self
, KeyField
);
473 function VarEquals(const V1
, V2
: Variant
): Boolean;
483 I
, J
, W
, X
, TxtWidth
, TxtHeight
, LastFieldIndex
: Integer;
488 AAlignment
: TAlignment
;
492 TxtWidth
:= WideCanvasTextWidth(Canvas
, '0');
493 TxtHeight
:= WideCanvasTextHeight(Canvas
, '0');
494 LastFieldIndex
:= ListFields
.Count
- 1;
495 if ColorToRGB(Color
) <> ColorToRGB(clBtnFace
) then
496 Canvas
.Pen
.Color
:= clBtnFace
else
497 Canvas
.Pen
.Color
:= clBtnShadow
;
498 for I
:= 0 to RowCount
- 1 do
501 Canvas
.Font
.Color
:= Font
.Color
else
502 Canvas
.Font
.Color
:= clGrayText
;
503 Canvas
.Brush
.Color
:= Color
;
504 Selected
:= not FKeySelected
and (I
= 0);
505 R
.Top
:= I
* TxtHeight
;
506 R
.Bottom
:= R
.Top
+ TxtHeight
;
507 if I
< FRecordCount
then
509 ListLink
.ActiveRecord
:= I
;
510 if not VarIsNull(KeyValue
) and
511 VarEquals(FKeyField
.Value
, KeyValue
) then
513 Canvas
.Font
.Color
:= clHighlightText
;
514 Canvas
.Brush
.Color
:= clHighlight
;
518 for J
:= 0 to LastFieldIndex
do
520 Field
:= ListFields
[J
];
521 if J
< LastFieldIndex
then
522 W
:= Field
.DisplayWidth
* TxtWidth
+ 4 else
523 W
:= ClientWidth
- R
.Right
;
524 S
:= GetWideDisplayText(Field
);
526 AAlignment
:= Field
.Alignment
;
527 if UseRightToLeftAlignment
then ChangeBiDiModeAlignment(AAlignment
);
529 taRightJustify
: X
:= W
- WideCanvasTextWidth(Canvas
, S
) - 3;
530 taCenter
: X
:= (W
- WideCanvasTextWidth(Canvas
, S
)) div 2;
533 R
.Right
:= R
.Right
+ W
;
534 if SysLocale
.MiddleEast
then TControlCanvas(Canvas
).UpdateTextFlags
;
535 WideCanvasTextRect(Canvas
, R
, R
.Left
+ X
, R
.Top
, S
);
536 if J
< LastFieldIndex
then
538 Canvas
.MoveTo(R
.Right
, R
.Top
);
539 Canvas
.LineTo(R
.Right
, R
.Bottom
);
541 if R
.Right
>= ClientWidth
then Break
;
546 R
.Right
:= ClientWidth
;
547 if I
>= FRecordCount
then Canvas
.FillRect(R
);
549 Canvas
.DrawFocusRect(R
);
551 if FRecordCount
<> 0 then ListLink
.ActiveRecord
:= FRecordIndex
;
554 //-----------------------------------------------------------------------------------------
555 // TDBGridInplaceEdit - Delphi 6 and higher
556 //-----------------------------------------------------------------------------------------
558 constructor TDBGridInplaceEdit
{TNT-ALLOW TDBGridInplaceEdit}.Create(Owner
: TComponent
);
560 inherited Create(Owner
);
561 FLookupSource
:= TDataSource
.Create(Self
);
564 function TDBGridInplaceEdit
{TNT-ALLOW TDBGridInplaceEdit}.GetWidePickListBox
: TTntCustomListBox
;
566 PopupListbox
: TTntPopupListbox
;
568 if not Assigned(FWidePickListBox
) then
570 PopupListbox
:= TTntPopupListbox
.Create(Self
);
571 PopupListbox
.Visible
:= False;
572 PopupListbox
.Parent
:= Self
;
573 PopupListbox
.OnMouseUp
:= ListMouseUp
;
574 PopupListbox
.IntegralHeight
:= True;
575 PopupListbox
.ItemHeight
:= 11;
576 FWidePickListBox
:= PopupListBox
;
578 Result
:= FWidePickListBox
;
581 procedure TDBGridInplaceEdit
{TNT-ALLOW TDBGridInplaceEdit}.CloseUp(Accept
: Boolean);
588 if GetCapture
<> 0 then SendMessage(GetCapture
, WM_CANCELMODE
, 0, 0);
589 if ActiveList
= DataList
then
590 ListValue
:= DataList
.KeyValue
592 if WidePickListBox
.ItemIndex
<> -1 then
593 ListValue
:= WidePickListBox
.Items
[WidePickListBox
.ItemIndex
];
594 SetWindowPos(ActiveList
.Handle
, 0, 0, 0, 0, 0, SWP_NOZORDER
or
595 SWP_NOMOVE
or SWP_NOSIZE
or SWP_NOACTIVATE
or SWP_HIDEWINDOW
);
596 ListVisible
:= False;
597 if Assigned(FDataList
) then
598 FDataList
.ListSource
:= nil;
599 FLookupSource
.Dataset
:= nil;
602 if ActiveList
= DataList
then
603 with Grid
as TTntCustomDBGrid
, Columns
[SelectedIndex
].Field
do
605 MasterField
:= DataSet
.FieldByName(KeyFields
);
606 if MasterField
.CanModify
and DataLink
.Edit
then
607 MasterField
.Value
:= ListValue
;
610 if (not VarIsNull(ListValue
)) and EditCanModify
then
611 with Grid
as TTntCustomDBGrid
do
612 SetWideText(Columns
[SelectedIndex
].Field
, ListValue
)
616 procedure TDBGridInplaceEdit
{TNT-ALLOW TDBGridInplaceEdit}.DoEditButtonClick
;
618 (Grid
as TTntCustomDBGrid
).EditButtonClick
;
621 type TAccessTntCustomListbox
= class(TTntCustomListbox
);
623 procedure TDBGridInplaceEdit
{TNT-ALLOW TDBGridInplaceEdit}.DropDown
;
628 if not ListVisible
then
630 with (Grid
as TTntCustomDBGrid
) do
631 Column
:= Columns
[SelectedIndex
] as TTntColumn
;
632 if ActiveList
= FDataList
then
635 FDataList
.Color
:= Color
;
636 FDataList
.Font
:= Font
;
637 FDataList
.RowCount
:= Column
.DropDownRows
;
638 FLookupSource
.DataSet
:= LookupDataSet
;
639 FDataList
.KeyField
:= LookupKeyFields
;
640 FDataList
.ListField
:= LookupResultField
;
641 FDataList
.ListSource
:= FLookupSource
;
642 FDataList
.KeyValue
:= DataSet
.FieldByName(KeyFields
).Value
;
644 else if ActiveList
= WidePickListBox
then
646 WidePickListBox
.Items
.Assign(Column
.WidePickList
);
647 DropDownRows
:= Column
.DropDownRows
;
648 // this is needed as inherited doesn't know about our WidePickListBox
649 if (DropDownRows
> 0) and (WidePickListBox
.Items
.Count
>= DropDownRows
) then
650 WidePickListBox
.Height
:= DropDownRows
* TAccessTntCustomListbox(WidePickListBox
as TTntCustomListbox
).ItemHeight
+ 4
652 WidePickListBox
.Height
:= WidePickListBox
.Items
.Count
* TAccessTntCustomListbox(WidePickListBox
as TTntCustomListbox
).ItemHeight
+ 4;
654 WidePickListBox
.ItemIndex
:= -1
656 WidePickListBox
.ItemIndex
:= WidePickListBox
.Items
.IndexOf(Text);
657 J
:= WidePickListBox
.ClientWidth
;
658 for I
:= 0 to WidePickListBox
.Items
.Count
- 1 do
660 Y
:= WideCanvasTextWidth(WidePickListBox
.Canvas
, WidePickListBox
.Items
[I
]);
661 if Y
> J
then J
:= Y
;
663 WidePickListBox
.ClientWidth
:= J
;
669 procedure TDBGridInplaceEdit
{TNT-ALLOW TDBGridInplaceEdit}.UpdateContents
;
673 inherited UpdateContents
;
674 if EditStyle
= esPickList
then
675 ActiveList
:= WidePickListBox
;
678 if FDataList
= nil then
680 FDataList
:= TTntPopupDataList
.Create(Self
);
681 FDataList
.Visible
:= False;
682 FDataList
.Parent
:= Self
;
683 FDataList
.OnMouseUp
:= ListMouseUp
;
685 ActiveList
:= FDataList
;
687 with (Grid
as TTntCustomDBGrid
) do
688 Column
:= Columns
[SelectedIndex
] as TTntColumn
;
689 Self
.ReadOnly
:= Column
.ReadOnly
;
690 Font
.Assign(Column
.Font
);
691 ImeMode
:= Column
.ImeMode
;
692 ImeName
:= Column
.ImeName
;
695 //-----------------------------------------------------------------------------------------
697 { TTntDBGridInplaceEdit }
699 procedure TTntDBGridInplaceEdit
.CreateWindowHandle(const Params
: TCreateParams
);
701 TntCustomEdit_CreateWindowHandle(Self
, Params
);
704 function TTntDBGridInplaceEdit
.GetText
: WideString
;
706 Result
:= TntControl_GetText(Self
);
709 procedure TTntDBGridInplaceEdit
.SetText(const Value
: WideString
);
711 TntControl_SetText(Self
, Value
);
714 procedure TTntDBGridInplaceEdit
.WMSetText(var Message: TWMSetText
);
716 if (not FBlockSetText
) then
720 procedure TTntDBGridInplaceEdit
.UpdateContents
;
722 Grid
: TTntCustomDBGrid
;
724 Grid
:= Self
.Grid
as TTntCustomDBGrid
;
725 EditMask
:= Grid
.GetEditMask(Grid
.Col
, Grid
.Row
);
726 Text := Grid
.GetEditText(Grid
.Col
, Grid
.Row
);
727 MaxLength
:= Grid
.GetEditLimit
;
729 FBlockSetText
:= True;
733 FBlockSetText
:= False;
737 procedure TTntDBGridInplaceEdit
.DblClick
;
743 FInDblClick
:= False;
749 procedure TTntGridDataLink
.GridUpdateFieldText(Sender
: TField
; const Text: AnsiString
);
751 Sender
.OnSetText
:= OriginalSetText
;
752 if Assigned(Sender
) then
753 SetWideText(Sender
, (Grid
as TTntCustomDBGrid
).FEditText
);
756 procedure TTntGridDataLink
.RecordChanged(Field
: TField
);
761 if Grid
.HandleAllocated
then begin
762 CField
:= Grid
.SelectedField
;
763 if ((Field
= nil) or (CField
= Field
)) and
764 (Assigned(CField
) and (GetWideText(CField
) <> (Grid
as TTntCustomDBGrid
).FEditText
)) then
766 with (Grid
as TTntCustomDBGrid
) do begin
768 if InplaceEditor
<> nil then InplaceEditor
.Deselect
;
774 procedure TTntGridDataLink
.UpdateData
;
778 Field
:= (Grid
as TTntCustomDBGrid
).SelectedField
;
779 // remember "set text"
781 OriginalSetText
:= Field
.OnSetText
;
783 // redirect "set text" to self
785 Field
.OnSetText
:= GridUpdateFieldText
;
786 inherited; // clear modified !
788 // redirect "set text" to field
790 Field
.OnSetText
:= OriginalSetText
;
791 // forget original "set text"
792 OriginalSetText
:= nil;
796 { TTntDBGridColumns }
798 function TTntDBGridColumns
.Add
: TTntColumn
;
800 Result
:= inherited Add
as TTntColumn
;
803 function TTntDBGridColumns
.GetColumn(Index
: Integer): TTntColumn
;
805 Result
:= inherited Items
[Index
] as TTntColumn
;
808 procedure TTntDBGridColumns
.SetColumn(Index
: Integer; const Value
: TTntColumn
);
810 inherited Items
[Index
] := Value
;
815 procedure TTntCustomDBGrid
.CreateWindowHandle(const Params
: TCreateParams
);
817 CreateUnicodeHandle(Self
, Params
, '');
820 type TAccessCustomGrid
= class(TCustomGrid
);
822 procedure TTntCustomDBGrid
.WMChar(var Msg
: TWMChar
);
824 if (goEditing
in TAccessCustomGrid(Self
).Options
)
825 and (AnsiChar(Msg
.CharCode
) in [^H
, #32..#255]) then begin
826 RestoreWMCharMsg(TMessage(Msg
));
827 ShowEditorChar(WideChar(Msg
.CharCode
));
832 procedure TTntCustomDBGrid
.ShowEditorChar(Ch
: WideChar
);
835 if InplaceEditor
<> nil then begin
836 if Win32PlatformIsUnicode
then
837 PostMessageW(InplaceEditor
.Handle
, WM_CHAR
, Word(Ch
), 0)
839 PostMessageA(InplaceEditor
.Handle
, WM_CHAR
, Word(Ch
), 0);
843 procedure TTntCustomDBGrid
.DefineProperties(Filer
: TFiler
);
846 TntPersistent_AfterInherited_DefineProperties(Filer
, Self
);
849 function TTntCustomDBGrid
.IsHintStored
: Boolean;
851 Result
:= TntControl_IsHintStored(Self
);
854 function TTntCustomDBGrid
.GetHint
: WideString
;
856 Result
:= TntControl_GetHint(Self
)
859 procedure TTntCustomDBGrid
.SetHint(const Value
: WideString
);
861 TntControl_SetHint(Self
, Value
);
864 function TTntCustomDBGrid
.CreateColumns
: TDBGridColumns
{TNT-ALLOW TDBGridColumns};
866 Result
:= TTntDBGridColumns
.Create(Self
, TTntColumn
);
869 function TTntCustomDBGrid
.GetColumns
: TTntDBGridColumns
;
871 Result
:= inherited Columns
as TTntDBGridColumns
;
874 procedure TTntCustomDBGrid
.SetColumns(const Value
: TTntDBGridColumns
);
876 inherited Columns
:= Value
;
879 function TTntCustomDBGrid
.CreateEditor
: TInplaceEdit
{TNT-ALLOW TInplaceEdit};
881 Result
:= TTntDBGridInplaceEdit
.Create(Self
);
884 function TTntCustomDBGrid
.CreateDataLink
: TGridDataLink
;
886 Result
:= TTntGridDataLink
.Create(Self
);
889 function TTntCustomDBGrid
.GetEditText(ACol
, ARow
: Integer): WideString
;
893 Field
:= GetColField(RawToDataColumn(ACol
));
897 Result
:= GetWideText(Field
);
901 procedure TTntCustomDBGrid
.SetEditText(ACol
, ARow
: Integer; const Value
: AnsiString
);
903 if (InplaceEditor
as TTntDBGridInplaceEdit
).FInDblClick
then
906 FEditText
:= (InplaceEditor
as TTntDBGridInplaceEdit
).Text;
910 //----------------- DRAW CELL PROCS --------------------------------------------------
912 DrawBitmap
: TBitmap
= nil;
914 procedure WriteText(ACanvas
: TCanvas
; ARect
: TRect
; DX
, DY
: Integer;
915 const Text: WideString
; Alignment
: TAlignment
; ARightToLeft
: Boolean);
917 AlignFlags
: array [TAlignment
] of Integer =
918 ( DT_LEFT
or DT_WORDBREAK
or DT_EXPANDTABS
or DT_NOPREFIX
,
919 DT_RIGHT
or DT_WORDBREAK
or DT_EXPANDTABS
or DT_NOPREFIX
,
920 DT_CENTER
or DT_WORDBREAK
or DT_EXPANDTABS
or DT_NOPREFIX
);
921 RTL
: array [Boolean] of Integer = (0, DT_RTLREADING
);
927 I
:= ColorToRGB(ACanvas
.Brush
.Color
);
928 if GetNearestColor(ACanvas
.Handle
, I
) = I
then
929 begin { Use ExtTextOutW for solid colors }
930 { In BiDi, because we changed the window origin, the text that does not
931 change alignment, actually gets its alignment changed. }
932 if (ACanvas
.CanvasOrientation
= coRightToLeft
) and (not ARightToLeft
) then
933 ChangeBiDiModeAlignment(Alignment
);
936 Left
:= ARect
.Left
+ DX
;
938 Left
:= ARect
.Right
- WideCanvasTextWidth(ACanvas
, Text) - 3;
940 Left
:= ARect
.Left
+ (ARect
.Right
- ARect
.Left
) div 2
941 - (WideCanvasTextWidth(ACanvas
, Text) div 2);
943 WideCanvasTextRect(ACanvas
, ARect
, Left
, ARect
.Top
+ DY
, Text);
945 else begin { Use FillRect and Drawtext for dithered colors }
946 DrawBitmap
.Canvas
.Lock
;
948 with DrawBitmap
, ARect
do { Use offscreen bitmap to eliminate flicker and }
949 begin { brush origin tics in painting / scrolling. }
950 Width
:= Max(Width
, Right
- Left
);
951 Height
:= Max(Height
, Bottom
- Top
);
952 R
:= Rect(DX
, DY
, Right
- Left
- 1, Bottom
- Top
- 1);
953 B
:= Rect(0, 0, Right
- Left
, Bottom
- Top
);
955 with DrawBitmap
.Canvas
do
957 Font
:= ACanvas
.Font
;
958 Font
.Color
:= ACanvas
.Font
.Color
;
959 Brush
:= ACanvas
.Brush
;
960 Brush
.Style
:= bsSolid
;
962 SetBkMode(Handle
, TRANSPARENT
);
963 if (ACanvas
.CanvasOrientation
= coRightToLeft
) then
964 ChangeBiDiModeAlignment(Alignment
);
965 Tnt_DrawTextW(Handle
, PWideChar(Text), Length(Text), R
,
966 AlignFlags
[Alignment
] or RTL
[ARightToLeft
]);
968 if (ACanvas
.CanvasOrientation
= coRightToLeft
) then
971 ARect
.Left
:= ARect
.Right
;
974 ACanvas
.CopyRect(ARect
, DrawBitmap
.Canvas
, B
);
976 DrawBitmap
.Canvas
.Unlock
;
981 procedure TTntCustomDBGrid
.DefaultDrawDataCell(const Rect
: TRect
; Field
: TField
;
982 State
: TGridDrawState
);
984 Alignment
: TAlignment
;
987 Alignment
:= taLeftJustify
;
989 if Assigned(Field
) then
991 Alignment
:= Field
.Alignment
;
992 Value
:= GetWideDisplayText(Field
);
994 WriteText(Canvas
, Rect
, 2, 2, Value
, Alignment
,
995 UseRightToLeftAlignmentForField(Field
, Alignment
));
998 procedure TTntCustomDBGrid
.DefaultDrawColumnCell(const Rect
: TRect
;
999 DataCol
: Integer; Column
: TTntColumn
; State
: TGridDrawState
);
1004 if Assigned(Column
.Field
) then
1005 Value
:= GetWideDisplayText(Column
.Field
);
1006 WriteText(Canvas
, Rect
, 2, 2, Value
, Column
.Alignment
,
1007 UseRightToLeftAlignmentForField(Column
.Field
, Column
.Alignment
));
1010 procedure TTntCustomDBGrid
.DrawCell(ACol
, ARow
: Longint; ARect
: TRect
; AState
: TGridDrawState
);
1014 procedure DrawTitleCell(ACol
, ARow
: Integer; Column
: TTntColumn
; var AState
: TGridDrawState
);
1016 ScrollArrows
: array [Boolean, Boolean] of Integer =
1017 ((DFCS_SCROLLRIGHT
, DFCS_SCROLLLEFT
), (DFCS_SCROLLLEFT
, DFCS_SCROLLRIGHT
));
1019 MasterCol
: TColumn
{TNT-ALLOW TColumn};
1020 TitleRect
, TxtRect
, ButtonRect
: TRect
;
1022 InBiDiMode
: Boolean;
1024 TitleRect
:= CalcTitleRect(Column
, ARow
, MasterCol
);
1026 if MasterCol
= nil then
1028 Canvas
.FillRect(ARect
);
1032 Canvas
.Font
:= MasterCol
.Title
.Font
;
1033 Canvas
.Brush
.Color
:= MasterCol
.Title
.Color
;
1034 if [dgRowLines
, dgColLines
] * Options
= [dgRowLines
, dgColLines
] then
1035 InflateRect(TitleRect
, -1, -1);
1036 TxtRect
:= TitleRect
;
1037 I
:= GetSystemMetrics(SM_CXHSCROLL
);
1038 if ((TxtRect
.Right
- TxtRect
.Left
) > I
) and MasterCol
.Expandable
then
1040 Dec(TxtRect
.Right
, I
);
1041 ButtonRect
:= TitleRect
;
1042 ButtonRect
.Left
:= TxtRect
.Right
;
1043 I
:= SaveDC(Canvas
.Handle
);
1045 Canvas
.FillRect(ButtonRect
);
1046 InflateRect(ButtonRect
, -1, -1);
1047 IntersectClipRect(Canvas
.Handle
, ButtonRect
.Left
,
1048 ButtonRect
.Top
, ButtonRect
.Right
, ButtonRect
.Bottom
);
1049 InflateRect(ButtonRect
, 1, 1);
1050 { DrawFrameControl doesn't draw properly when orienatation has changed.
1051 It draws as ExtTextOutW does. }
1052 InBiDiMode
:= Canvas
.CanvasOrientation
= coRightToLeft
;
1053 if InBiDiMode
then { stretch the arrows box }
1054 Inc(ButtonRect
.Right
, GetSystemMetrics(SM_CXHSCROLL
) + 4);
1055 DrawFrameControl(Canvas
.Handle
, ButtonRect
, DFC_SCROLL
,
1056 ScrollArrows
[InBiDiMode
, MasterCol
.Expanded
] or DFCS_FLAT
);
1058 RestoreDC(Canvas
.Handle
, I
);
1061 with (MasterCol
.Title
as TTntColumnTitle
) do
1062 WriteText(Canvas
, TxtRect
, FrameOffs
, FrameOffs
, Caption
, Alignment
, IsRightToLeft
);
1063 if [dgRowLines
, dgColLines
] * Options
= [dgRowLines
, dgColLines
] then
1065 InflateRect(TitleRect
, 1, 1);
1066 DrawEdge(Canvas
.Handle
, TitleRect
, BDR_RAISEDINNER
, BF_BOTTOMRIGHT
);
1067 DrawEdge(Canvas
.Handle
, TitleRect
, BDR_RAISEDINNER
, BF_TOPLEFT
);
1069 AState
:= AState
- [gdFixed
]; // prevent box drawing later
1076 DrawColumn
: TTntColumn
;
1078 if csLoading
in ComponentState
then
1080 Canvas
.Brush
.Color
:= Color
;
1081 Canvas
.FillRect(ARect
);
1085 if (gdFixed
in AState
) and (RawToDataColumn(ACol
) < 0) then
1091 Dec(ARow
, FixedRows
);
1092 ACol
:= RawToDataColumn(ACol
);
1094 if (gdFixed
in AState
) and ([dgRowLines
, dgColLines
] * Options
=
1095 [dgRowLines
, dgColLines
]) then
1097 InflateRect(ARect
, -1, -1);
1105 DrawColumn
:= Columns
[ACol
] as TTntColumn
;
1106 if not DrawColumn
.Showing
then Exit
;
1107 if not (gdFixed
in AState
) then
1109 Font
:= DrawColumn
.Font
;
1110 Brush
.Color
:= DrawColumn
.Color
;
1113 DrawTitleCell(ACol
, ARow
+ FixedRows
, DrawColumn
, AState
)
1114 else if (DataLink
= nil) or not DataLink
.Active
then
1119 OldActive
:= DataLink
.ActiveRecord
;
1121 DataLink
.ActiveRecord
:= ARow
;
1122 if Assigned(DrawColumn
.Field
) then
1123 Value
:= GetWideDisplayText(DrawColumn
.Field
);
1124 Highlight
:= HighlightCell(ACol
, ARow
, Value
, AState
);
1127 Brush
.Color
:= clHighlight
;
1128 Font
.Color
:= clHighlightText
;
1131 Font
.Color
:= clGrayText
;
1132 if DefaultDrawing
then
1133 DefaultDrawColumnCell(ARect
, ACol
, DrawColumn
, AState
);
1134 if Columns
.State
= csDefault
then
1135 DrawDataCell(ARect
, DrawColumn
.Field
, AState
);
1136 DrawColumnCell(ARect
, ACol
, DrawColumn
, AState
);
1138 DataLink
.ActiveRecord
:= OldActive
;
1140 if DefaultDrawing
and (gdSelected
in AState
)
1141 and ((dgAlwaysShowSelection
in Options
) or Focused
)
1142 and not (csDesigning
in ComponentState
)
1143 and not (dgRowSelect
in Options
)
1144 and (UpdateLock
= 0)
1145 and (ValidParentForm(Self
).ActiveControl
= Self
) then
1146 Windows
.DrawFocusRect(Handle
, ARect
);
1149 if (gdFixed
in AState
) and ([dgRowLines
, dgColLines
] * Options
=
1150 [dgRowLines
, dgColLines
]) then
1152 InflateRect(ARect
, 1, 1);
1153 DrawEdge(Canvas
.Handle
, ARect
, BDR_RAISEDINNER
, BF_BOTTOMRIGHT
);
1154 DrawEdge(Canvas
.Handle
, ARect
, BDR_RAISEDINNER
, BF_TOPLEFT
);
1158 procedure TTntCustomDBGrid
.ActionChange(Sender
: TObject
; CheckDefaults
: Boolean);
1160 TntControl_BeforeInherited_ActionChange(Self
, Sender
, CheckDefaults
);
1164 function TTntCustomDBGrid
.GetActionLinkClass
: TControlActionLinkClass
;
1166 Result
:= TntControl_GetActionLinkClass(Self
, inherited GetActionLinkClass
);
1170 DrawBitmap
:= TBitmap
.Create
;