📄 jvdblookuptreeview.pas
字号:
RCSfile: '$RCSfile: JvDBLookupTreeView.pas,v $';
Revision: '$Revision: 1.30 $';
Date: '$Date: 2005/02/18 14:17:23 $';
LogPath: 'JVCL\run'
);
{$ENDIF UNITVERSIONING}
implementation
uses
{$IFDEF HAS_UNIT_VARIANTS}
Variants,
{$ENDIF HAS_UNIT_VARIANTS}
{$IFDEF COMPILER6_UP}
VDBConsts,
{$ENDIF COMPILER6_UP}
CommCtrl, Graphics, DBConsts,
JvThemes;
//=== { TJvLookupDataSourceLink } ============================================
procedure TJvLookupDataSourceLink.ActiveChanged;
begin
if FDBLookupControl <> nil then
FDBLookupControl.DataLinkActiveChanged;
end;
procedure TJvLookupDataSourceLink.RecordChanged(Field: TField);
begin
if FDBLookupControl <> nil then
FDBLookupControl.DataLinkRecordChanged(Field);
end;
procedure TJvLookupDataSourceLink.FocusControl(Field: TFieldRef);
begin
if (Field^ <> nil) and (Field^ = FDBLookupControl.Field) and
(FDBLookupControl <> nil) and FDBLookupControl.CanFocus then
begin
Field^ := nil;
FDBLookupControl.SetFocus;
end;
end;
procedure TJvLookupListSourceLink.ActiveChanged;
begin
if FDBLookupControl <> nil then
FDBLookupControl.ListLinkActiveChanged;
end;
procedure TJvLookupListSourceLink.DataSetChanged;
begin
if FDBLookupControl <> nil then
FDBLookupControl.ListLinkDataChanged;
end;
//=== { TJvDBLookupControl } =================================================
function VarEquals(const V1, V2: Variant): Boolean;
begin
Result := False;
try
Result := V1 = V2;
except
end;
end;
constructor TJvDBLookupControl.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
if NewStyleControls then
ControlStyle := [csOpaque]
else
ControlStyle := [csOpaque, csFramed];
IncludeThemeStyle(Self, [csNeedsBorderPaint]);
ParentColor := False;
TabStop := True;
FLookupSource := TDataSource.Create(Self);
FDataLink := TJvLookupDataSourceLink.Create;
FDataLink.FDBLookupControl := Self;
FListLink := TJvLookupListSourceLink.Create;
FListLink.FDBLookupControl := Self;
FListFields := TList.Create;
FKeyValue := Null;
FSearchTickCount := 0;
end;
destructor TJvDBLookupControl.Destroy;
begin
FListFields.Free;
FListLink.FDBLookupControl := nil;
FListLink.Free;
FDataLink.FDBLookupControl := nil;
FDataLink.Free;
inherited Destroy;
end;
function TJvDBLookupControl.CanModify: Boolean;
begin
Result := FListActive and not ReadOnly and ((FDataLink.DataSource = nil) or
(FMasterField <> nil) and FMasterField.CanModify);
end;
procedure TJvDBLookupControl.CheckNotCircular;
begin
if (FDataLink.Active and FDataLink.DataSet.IsLinkedTo(ListSource)) or
(FListLink.Active and FListLink.DataSet.IsLinkedTo(DataSource)) then
DatabaseError(SCircularDataLink);
end;
procedure TJvDBLookupControl.CheckNotLookup;
begin
if FLookupMode then
DatabaseError(SPropDefByLookup);
if FDataLink.DataSourceFixed then
DatabaseError(SDataSourceFixed);
end;
procedure TJvDBLookupControl.DataLinkActiveChanged;
begin
FDataField := nil;
FMasterField := nil;
if FDataLink.Active and (FDataFieldName <> '') then
begin
CheckNotCircular;
FDataField := GetFieldProperty(FDataLink.DataSet, Self, FDataFieldName);
FMasterField := FDataField;
end;
SetLookupMode((FDataField <> nil) and (FDataField.FieldKind = fkLookup));
DataLinkRecordChanged(nil);
end;
procedure TJvDBLookupControl.DataLinkRecordChanged(Field: TField);
begin
if (Field = nil) or (Field = FMasterField) then
if FMasterField <> nil then
SetKeyValue(FMasterField.Value)
else
SetKeyValue(Null);
end;
function TJvDBLookupControl.GetBorderSize: Integer;
var
Params: TCreateParams;
R: TRect;
begin
CreateParams(Params);
SetRect(R, 0, 0, 0, 0);
AdjustWindowRectEx(R, Params.Style, False, Params.ExStyle);
Result := R.Bottom - R.Top;
end;
function TJvDBLookupControl.GetDataSource: TDataSource;
begin
Result := FDataLink.DataSource;
end;
function TJvDBLookupControl.GetKeyFieldName: string;
begin
if FLookupMode then
Result := ''
else
Result := FKeyFieldName;
end;
function TJvDBLookupControl.GetListSource: TDataSource;
begin
if FLookupMode then
Result := nil
else
Result := FListLink.DataSource;
end;
function TJvDBLookupControl.GetReadOnly: Boolean;
begin
Result := FDataLink.ReadOnly;
end;
function TJvDBLookupControl.GetTextHeight: Integer;
var
DC: HDC;
SaveFont: HFont;
Metrics: TTextMetric;
begin
DC := GetDC(HWND_DESKTOP);
SaveFont := SelectObject(DC, Font.Handle);
GetTextMetrics(DC, Metrics);
SelectObject(DC, SaveFont);
ReleaseDC(HWND_DESKTOP, DC);
Result := Metrics.tmHeight;
end;
procedure TJvDBLookupControl.KeyValueChanged;
begin
end;
procedure TJvDBLookupControl.ListLinkActiveChanged;
var
DataSet: TDataSet;
ResultField: TField;
begin
FListActive := False;
FKeyField := nil;
FListField := nil;
FListFields.Clear;
if FListLink.Active and (FKeyFieldName <> '') then
begin
CheckNotCircular;
DataSet := FListLink.DataSet;
FKeyField := GetFieldProperty(DataSet, Self, FKeyFieldName);
try
DataSet.GetFieldList(FListFields, FListFieldName);
except
DatabaseErrorFmt(SFieldNotFound, [Self.Name, FListFieldName]);
end;
if FLookupMode then
begin
ResultField := GetFieldProperty(DataSet, Self, FDataField.LookupResultField);
if FListFields.IndexOf(ResultField) < 0 then
FListFields.Insert(0, ResultField);
FListField := ResultField;
end
else
begin
if FListFields.Count = 0 then
FListFields.Add(FKeyField);
if (FListFieldIndex >= 0) and (FListFieldIndex < FListFields.Count) then
FListField := FListFields[FListFieldIndex]
else
FListField := FListFields[0];
end;
FListActive := True;
end;
end;
procedure TJvDBLookupControl.ListLinkDataChanged;
begin
end;
function TJvDBLookupControl.LocateKey: Boolean;
begin
Result := False;
try
if not VarIsNull(FKeyValue) and
FListLink.DataSet.Locate(FKeyFieldName, FKeyValue, []) then
Result := True;
except
end;
end;
procedure TJvDBLookupControl.Notification(AComponent: TComponent;
Operation: TOperation);
begin
inherited Notification(AComponent, Operation);
if Operation = opRemove then
begin
if (FDataLink <> nil) and (AComponent = DataSource) then
DataSource := nil;
if (FListLink <> nil) and (AComponent = ListSource) then
ListSource := nil;
end;
end;
procedure TJvDBLookupControl.ProcessSearchKey(Key: Char);
var
TickCount: Integer;
S: string;
begin
if (FListField <> nil) and (FListField.FieldKind = fkData) and
(FListField.DataType = ftString) then
case Word(Key) of
VK_BACK, VK_ESCAPE:
FSearchText := '';
VK_SPACE..255:
if CanModify then
begin
TickCount := GetTickCount;
if TickCount - FSearchTickCount > 2000 then
FSearchText := '';
FSearchTickCount := TickCount;
if Length(FSearchText) < 32 then
begin
S := FSearchText + Key;
if FListLink.DataSet.Locate(FListField.FieldName, S,
[loCaseInsensitive, loPartialKey]) then
begin
SelectKeyValue(FKeyField.Value);
FSearchText := S;
end;
end;
end;
end;
end;
procedure TJvDBLookupControl.SelectKeyValue(const Value: Variant);
begin
if FMasterField <> nil then
begin
if FDataLink.Edit then
FMasterField.Value := Value;
end
else
SetKeyValue(Value);
Repaint;
Click;
end;
procedure TJvDBLookupControl.SetDataFieldName(const Value: string);
begin
if FDataFieldName <> Value then
begin
FDataFieldName := Value;
DataLinkActiveChanged;
end;
end;
procedure TJvDBLookupControl.SetDataSource(Value: TDataSource);
begin
FDataLink.DataSource := Value;
if Value <> nil then
Value.FreeNotification(Self);
end;
procedure TJvDBLookupControl.SetKeyFieldName(const Value: string);
begin
CheckNotLookup;
if FKeyFieldName <> Value then
begin
FKeyFieldName := Value;
ListLinkActiveChanged;
end;
end;
procedure TJvDBLookupControl.SetKeyValue(const Value: Variant);
begin
if not VarEquals(FKeyValue, Value) then
begin
FKeyValue := Value;
KeyValueChanged;
end;
end;
procedure TJvDBLookupControl.SetListFieldName(const Value: string);
begin
if FListFieldName <> Value then
begin
FListFieldName := Value;
ListLinkActiveChanged;
end;
end;
procedure TJvDBLookupControl.SetListSource(Value: TDataSource);
begin
CheckNotLookup;
FListLink.DataSource := Value;
if Value <> nil then
Value.FreeNotification(Self);
end;
procedure TJvDBLookupControl.SetLookupMode(Value: Boolean);
begin
if FLookupMode <> Value then
if Value then
begin
FMasterField := GetFieldProperty(FDataField.DataSet, Self, FDataField.KeyFields);
FLookupSource.DataSet := FDataField.LookupDataSet;
FKeyFieldName := FDataField.LookupKeyFields;
FLookupMode := True;
FListLink.DataSource := FLookupSource;
end
else
begin
FListLink.DataSource := nil;
FLookupMode := False;
FKeyFieldName := '';
FLookupSource.DataSet := nil;
FMasterField := FDataField;
end;
end;
procedure TJvDBLookupControl.SetReadOnly(Value: Boolean);
begin
FDataLink.ReadOnly := Value;
end;
procedure TJvDBLookupControl.GetDlgCode(var Code: TDlgCodes);
begin
Code := [dcWantArrows, dcWantChars];
end;
procedure TJvDBLookupControl.FocusKilled(NextWnd: HWND);
begin
FFocused := False;
inherited FocusKilled(NextWnd);
Invalidate;
end;
procedure TJvDBLookupControl.FocusSet(PrevWnd: HWND);
begin
FFocused := True;
inherited FocusSet(PrevWnd);
Invalidate;
end;
procedure TJvDBLookupControl.CMGetDataLink(var Msg: TMessage);
begin
Msg.Result := Integer(FDataLink);
end;
//=== { TJvDBLookupTreeViewCombo } ===========================================
constructor TJvDBLookupTreeViewCombo.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
ControlStyle := ControlStyle + [csReplicatable];
Width := 145;
Height := 0;
FDataList := TJvTreePopupDataList.Create(Self);
// FDataList.Visible := False;
// FDataList.Parent := Self;
FButtonWidth := GetSystemMetrics(SM_CXVSCROLL);
FDropDownHeight := 100;
FFullExpand := False;
end;
procedure TJvDBLookupTreeViewCombo.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
with Params do
if NewStyleControls and Ctl3D then
ExStyle := ExStyle or WS_EX_CLIENTEDGE
else
Style := Style or WS_BORDER;
end;
procedure TJvDBLookupTreeViewCombo.Paint;
var
W, X, Flags: Integer;
Text: string;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -