www.pudn.com > JsDbTree7.rar > JsDbTree.pas
unit JsDbTree;
{$OBJEXPORTALL On}
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, extctrls, buttons, ComCtrls,
DBCtrls, Menus, DB, ImgList;
type
TTitlePosition = (tpTop, tpLeft, tpRight, tpBottom);
{$EXTERNALSYM TTitlePosition}
TJsDbTitle = class(TPersistent)
private
FPosition: TTitlePosition;
FOnChange: TNotifyEvent;
FCaption: TCaption;
FFont: TFont;
FAlignment: TAlignment;
FGlyph: TBitmap;
FHeight: Integer;
FColor: TColor;
procedure SetPosition(const Value: TTitlePosition);
procedure SetCaption(const Value: TCaption);
procedure SetFont(const Value: TFont);
procedure SetAlignment(const Value: TAlignment);
procedure SetGlyph(const Value: TBitmap);
procedure SetHeight(const Value: integer);
procedure SetColor(const Value: TColor);
protected
property OnChange: TNotifyEvent read FOnChange write FOnChange;
procedure FontChanged(Sender: TObject);
public
constructor Create;
published
property Alignment: TAlignment read FAlignment write SetAlignment default taCenter;
property Caption: TCaption read FCaption write SetCaption;
property Font: TFont read FFont write SetFont;
property Position: TTitlePosition read FPosition write SetPosition default tpTop;
property Glyph: TBitmap read FGlyph write SetGlyph;
property Color: TColor read FColor write SetColor default clBtnFace;
property Height: Integer read FHeight write SetHeight default 20;
end;
TJsDbTree = class(TWinControl)
private
FOnTreeChange: TTVChangedEvent;
FTitle: TJsDbTitle;
FOnHide: TNotifyEvent;
FPanel: TPanel;
FPanel1: TPanel;
FButtonMenu: TSpeedButton;
FButtonClose: TSpeedButton;
FButtonRefresh: TSpeedButton;
FButtonMenuVisible: Boolean;
FButtonCloseVisible: Boolean;
FButtonRefreshVisible: Boolean;
FTree: TTreeView;
FReadOnly: Boolean;
FMcData: string;
FDataLink: TFieldDataLink;
FMenu: TPopupMenu;
FTreeCodeFormat: string;
FTreeCodeSeperate: string;
FTreeName: string;
FImages: TCustomImageList;
function GetDataField: string;
procedure SetDataField(const Value: string);
function GetDataSource: TDataSource;
procedure SetDataSource(Value: TDataSource);
function GetReadOnly: Boolean;
procedure SetReadOnly(Value: Boolean);
procedure SetButtonMenuVisible(Value: Boolean);
procedure SetButtonCloseVisible(Value: Boolean);
procedure SetButtonRefreshVisible(Value: Boolean);
function GetNodeLevel(sFormat, sCode: string): integer;
procedure SetImages(Value: TCustomImageList);
function GetGetNodeString: string;
function GetGetCurID: string;
function GetTreeCodeFormat: string;
function GetTreeCodeSeperate: string;
procedure SetTreeCodeFormat(const Value: string);
procedure SetTreeCodeSeperate(const Value: string);
function StrSubCount(const Source, Sub: string): integer;
protected
procedure FTreeChange(Sender: TObject; Node: TTreeNode);
procedure TitleChanged(Sender: TObject);
procedure ButtonClick(Sender: TObject); virtual;
public
Fn1: TMenuItem;
Fn2: TMenuItem;
Fn3: TMenuItem;
Fn4: TMenuItem;
Fn5: TMenuItem;
Fn6: TMenuItem;
Fn7: TMenuItem;
Fn8: TMenuItem;
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure TreeRefresh;
procedure RefreshButtonClick(Sender: TObject); virtual;
procedure AddwButtonClick(Sender: TObject); virtual;
procedure DelButtonClick(Sender: TObject); virtual;
procedure AddButtonClick(Sender: TObject); virtual;
procedure EditButtonClick(Sender: TObject); virtual;
procedure BmButtonClick(Sender: TObject); virtual;
procedure McButtonClick(Sender: TObject); virtual;
procedure DropDownPopup(Sender: TObject); virtual;
function GetNodeString: string;
function GetCurID: string;
published
property Align;
property BorderWidth;
property Anchors;
property Visible;
property Constraints;
property Width;
property Height;
property ClientWidth;
property ClientHeight;
property Color;
property Hint;
property Ctl3D;
property ShowHint;
property Title: TJsDbTitle read FTitle write FTitle;
property OnHide: TNotifyEvent read FOnHide write FOnHide;
property DataField: string read GetDataField write SetDataField;
property McData: string read FMcData write FMcData;
property DataSource: TDataSource read GetDataSource write SetDataSource;
property ButtonMenuVisible: Boolean read FButtonMenuVisible write SetButtonMenuVisible default True;
property ButtonCloseVisible: Boolean read FButtonCloseVisible write SetButtonCloseVisible default True;
property ButtonRefreshVisible: Boolean read FButtonRefreshVisible write SetButtonRefreshVisible default True;
property ReadOnly: Boolean read GetReadOnly write SetReadOnly default False;
property Menu: TPopupMenu read FMenu write FMenu;
property Images: TCustomImageList read FImages write SetImages;
property TreeCodeFormat: string read GetTreeCodeFormat write SetTreeCodeFormat;
property TreeCodeSeperate: string read GetTreeCodeSeperate write SetTreeCodeSeperate;
property TreeName: string read FTreeName write FTreeName;
property OnTreeChange: TTVChangedEvent read FOnTreeChange write FOnTreeChange;
end;
procedure Register;
implementation
{$R RES_JsDbTree.res}
{***************************************************}
function TJsDbTree.GetTreeCodeFormat: string;
begin
Result := FTreeCodeFormat;
end;
{***************************************************}
function TJsDbTree.GetTreeCodeSeperate: string;
begin
Result := FTreeCodeSeperate;
end;
{***************************************************}
procedure TJsDbTree.SetTreeCodeFormat(const Value: string);
begin
if Value <> '' then
begin
FTreeCodeFormat := Value;
FTreeCodeSeperate := '';
end;
end;
{***************************************************}
procedure TJsDbTree.SetTreeCodeSeperate(const Value: string);
begin
if Value <> '' then
begin
FTreeCodeFormat := '';
FTreeCodeSeperate := Value;
end;
end;
{***************************************************}
procedure TJsDbTree.SetImages(Value: TCustomImageList);
begin
FTree.Images := Value;
FImages := Value;
end;
{***************************************************}
procedure TJsDbTree.SetButtonMenuVisible(Value: Boolean);
begin
FButtonMenu.Visible := Value;
FButtonMenuVisible := Value;
end;
{***************************************************}
procedure TJsDbTree.SetButtonCloseVisible(Value: Boolean);
begin
FButtonClose.Visible := Value;
FButtonCloseVisible := Value;
end;
{***************************************************}
procedure TJsDbTree.SetButtonRefreshVisible(Value: Boolean);
begin
FButtonRefresh.Visible := Value;
FButtonRefreshVisible := Value;
end;
{***************************************************}
procedure TJsDbTree.ButtonClick(Sender: TObject);
begin
Visible := false;
if Assigned(FOnHide) then
FOnHide(self);
end;
{***************************************************}
procedure TJsDbTree.RefreshButtonClick(Sender: TObject);
begin
// FTree.Selected := FTree.Items[0];
TreeRefresh;
end;
{***************************************************}
procedure TJsDbTree.AddwButtonClick(Sender: TObject);
begin
end;
{***************************************************}
procedure TJsDbTree.AddButtonClick(Sender: TObject);
begin
end;
{***************************************************}
procedure TJsDbTree.DelButtonClick(Sender: TObject);
begin
end;
{***************************************************}
procedure TJsDbTree.EditButtonClick(Sender: TObject);
begin
end;
{***************************************************}
procedure TJsDbTree.BmButtonClick(Sender: TObject);
begin
Fn4.Enabled := true;
Fn4.Checked := false;
Fn3.Enabled := false;
Fn3.Checked := true;
// FTree.Selected := FTree.Items[0];
TreeRefresh;
end;
{***************************************************}
procedure TJsDbTree.McButtonClick(Sender: TObject);
begin
Fn4.Enabled := false;
Fn4.Checked := true;
Fn3.Enabled := true;
Fn3.Checked := false;
// FTree.Selected := FTree.Items[0];
TreeRefresh;
end;
{***************************************************}
procedure TJsDbTree.DropDownPopup(Sender: TObject);
begin
FMenu.Popup(GetClientOrigin.x, GetClientOrigin.y + 20);
Perform(CM_MOUSELEAVE, 0, 0);
end;
{***************************************************}
constructor TJsDbTree.Create(AOwner: TComponent);
begin
inherited;
FTitle := TJsDbTitle.Create;
FTitle.OnChange := TitleChanged;
Width := 150;
Height := 200;
FTitle.FCaption := '编码树';
FButtonMenuVisible := true;
FButtonCloseVisible := true;
FButtonRefreshVisible := true;
FDataLink := TFieldDataLink.Create;
FDataLink.Control := Self;
Fn1 := TMenuItem.Create(Self);
with FN1 do
begin
Caption := '重建编码(&R)';
Name := 'N1';
OnClick := RefreshButtonClick;
end;
Fn2 := TMenuItem.Create(Self);
with FN2 do
begin
Caption := '编码增位(&W)';
Name := 'N2';
OnClick := AddwButtonClick;
Visible := False;
end;
Fn3 := TMenuItem.Create(Self);
with FN3 do
begin
Caption := '显示编码(&B)';
Name := 'N3';
OnClick := BmButtonClick;
end;
Fn4 := TMenuItem.Create(Self);
with FN4 do
begin
Caption := '显示名称(&M)';
Name := 'N4';
OnClick := McButtonClick;
Checked := true;
Enabled := false;
end;
Fn5 := TMenuItem.Create(Self);
with FN5 do
begin
Caption := '-';
Name := 'N5';
Visible := False;
end;
Fn6 := TMenuItem.Create(Self);
with FN6 do
begin
Caption := '新增编码(&A)';
Name := 'N6';
OnClick := AddButtonClick;
Visible := False;
end;
Fn7 := TMenuItem.Create(Self);
with FN7 do
begin
Caption := '修改编码(&E)';
Name := 'N7';
OnClick := EditButtonClick;
Visible := False;
end;
Fn8 := TMenuItem.Create(Self);
with FN8 do
begin
Caption := '删除编码(&D)';
Name := 'N8';
OnClick := DelButtonClick;
Visible := False;
end;
FMenu := TPopupMenu.Create(Self);
with FMenu do
begin
Name := 'Menu';
Items.Add(Fn1);
Items.Add(Fn2);
Items.Add(Fn3);
Items.Add(Fn4);
Items.Add(Fn5);
Items.Add(Fn6);
Items.Add(Fn7);
Items.Add(Fn8);
end;
FPanel := TPanel.Create(Self);
with FPanel do
begin
Align := alTop;
Alignment := taCenter;
AutoSize := false;
Caption := FTitle.Caption;
BevelOuter := bvRaised;
Parent := self;
Height := 20;
Font.Style := [fsBold];
ControlStyle := ControlStyle - [csAcceptsControls];
end;
FPanel1 := TPanel.Create(self);
with FPanel1 do
begin
Align := alClient;
Alignment := taCenter;
AutoSize := true;
Parent := self;
end;
FButtonRefresh := TSpeedButton.Create(self);
with FButtonRefresh do
begin
Parent := FPanel;
Align := alRight;
Flat := true;
Caption := '';
Width := 20;
Glyph.LoadFromResourceName(hInstance, 'JSTREESX');
OnClick := RefreshButtonClick;
end;
FButtonClose := TSpeedButton.Create(self);
with FButtonClose do
begin
Parent := FPanel;
Align := alRight;
Flat := true;
Caption := '';
Width := 20;
Glyph.LoadFromResourceName(hInstance, 'JSTREECLOSE');
OnClick := ButtonClick;
end;
FButtonMenu := TSpeedButton.Create(self);
with FButtonMenu do
begin
Parent := FPanel;
Align := alLeft;
Flat := true;
Caption := '';
Width := 20;
Glyph.LoadFromResourceName(hInstance, 'JSTREEMenu');
PopupMenu := FMenu;
OnClick := DropDownPopup;
end;
FTree := TTreeView.Create(self);
with FTree do
begin
FTree.HideSelection := False;
OnChange := FTreeChange; /////
ReadOnly := True;
Parent := FPanel1;
Align := alClient;
Ctl3D := false;
PopupMenu := FMenu;
end;
ControlStyle := ControlStyle - [csFixedWidth, csFixedHeight];
ControlStyle := ControlStyle + [csAcceptsControls];
end;
{***************************************************}
destructor TJsDbTree.Destroy;
begin
FTree.Free;
FButtonMenu.Free;
FButtonClose.Free;
FButtonRefresh.Free;
FPanel1.Free;
FPanel.Free;
Fn8.Free;
Fn7.Free;
Fn6.Free;
Fn5.Free;
Fn4.Free;
Fn3.Free;
Fn2.Free;
Fn1.Free;
FMenu.Free;
FDataLink.Free;
FDataLink := nil;
FTitle.Free;
inherited;
end;
{***************************************************}
procedure TJsDbTree.TitleChanged(Sender: TObject);
begin
case Title.Position of
tpTop:
begin
FPanel.Align := alTop;
FButtonClose.Align := alRight;
FPanel.Caption := Title.Caption;
end;
tpLeft:
begin
FPanel.Align := alLeft;
FButtonClose.Align := alTop;
FPanel.Caption := '';
end;
tpRight:
begin
FPanel.Align := alRight;
FButtonClose.Align := alBottom;
FPanel.Caption := '';
end;
tpBottom:
begin
FPanel.Align := alBottom;
FButtonClose.Align := alRight;
FPanel.Caption := Title.Caption;
end;
end;
FPanel.Font.Assign(Title.Font);
FPanel.Alignment := Title.Alignment;
FPanel.Color := Title.Color;
if Title.Glyph.Width > 0 then
FButtonClose.Glyph.Assign(Title.Glyph)
else
FButtonClose.Glyph.LoadFromResourceName(hInstance, 'JSTREECLOSE');
FPanel.Height := Title.Height;
end;
{***************************************************}
function TJsDbTree.GetDataField: string;
begin
Result := FDataLink.FieldName;
end;
{***************************************************}
procedure TJsDbTree.SetDataField(const Value: string);
begin
FDataLink.FieldName := Value;
end;
{***************************************************}
function TJsDbTree.GetDataSource: TDataSource;
begin
Result := FDataLink.DataSource;
end;
{***************************************************}
procedure TJsDbTree.SetDataSource(Value: TDataSource);
begin
if not (FDataLink.DataSourceFixed and (csLoading in ComponentState)) then
FDataLink.DataSource := Value;
if Value <> nil then Value.FreeNotification(Self);
end;
{***************************************************}
function TJsDbTree.GetReadOnly: Boolean;
begin
Result := FReadOnly;
end;
{***************************************************}
procedure TJsDbTree.SetReadOnly(Value: Boolean);
begin
FReadOnly := Value;
end;
{***************************************************}
{ TJsDbTitle }
{***************************************************}
constructor TJsDbTitle.Create;
begin
FPosition := tpTop;
FAlignment := taCenter;
FGlyph := TBitmap.Create;
FFont := TFont.Create;
FFont.OnChange := FontChanged;
FHeight := 20;
FColor := clBtnFace;
end;
{***************************************************}
procedure TJsDbTitle.FontChanged(Sender: TObject);
begin
if Assigned(FOnChange) then
FOnChange(self);
end;
{***************************************************}
procedure TJsDbTitle.SetAlignment(const Value: TAlignment);
begin
FAlignment := Value;
if Assigned(FOnChange) then
FOnChange(self);
end;
{***************************************************}
procedure TJsDbTitle.SetCaption(const Value: TCaption);
begin
FCaption := Value;
if Assigned(FOnChange) then
FOnChange(self);
end;
{***************************************************}
procedure TJsDbTitle.SetColor(const Value: TColor);
begin
FColor := Value;
if Assigned(FOnChange) then
FOnChange(self);
end;
{***************************************************}
procedure TJsDbTitle.SetFont(const Value: TFont);
begin
FFont := Value;
if Assigned(FOnChange) then
FOnChange(self);
end;
{***************************************************}
procedure TJsDbTitle.SetGlyph(const Value: TBitmap);
begin
FGlyph.Assign(Value);
if Assigned(FOnChange) then
FOnChange(self);
end;
{***************************************************}
procedure TJsDbTitle.SetHeight(const Value: integer);
begin
FHeight := Value;
if Assigned(FOnChange) then
FOnChange(self);
end;
{***************************************************}
procedure TJsDbTitle.SetPosition(const Value: TTitlePosition);
begin
FPosition := Value;
if Assigned(FOnChange) then
FOnChange(self);
end;
{***************************************************}
function TJsDbTree.GetGetCurID: string;
begin
Result := FTree.Selected.Text;
end;
{***************************************************}
function TJsDbTree.GetGetNodeString: string;
var
p: PString;
begin
p := FTree.Selected.Data;
Result := p^;
end;
{***************************************************}
function TJsDbTree.GetNodeString: string;
begin
if Fn4.Checked then
Result := GetGetCurID
else
Result := GetGetNodeString;
end;
{***************************************************}
function TJsDbTree.GetCurID: string;
begin
if Fn4.Checked then
Result := GetGetNodeString
else
Result := GetGetCurID;
end;
{***************************************************}
function TJsDbTree.GetNodeLevel(sFormat, sCode: string): integer;
var i, level, iLen: integer;
begin
level := -1;
iLen := 0;
if (sFormat <> '') and (sCode <> '') then
for i := 1 to Length(sFormat) do
begin
iLen := iLen + StrToInt(sFormat[i]);
if Length(sCode) = iLen then
begin
level := i;
break;
end;
end;
result := level;
end;
{***************************************************}
function TJsDbTree.StrSubCount(const Source, Sub: string): integer;
var
Buf: string;
i: integer;
Len: integer;
begin
Result := 0;
Buf := Source;
i := Pos(Sub, Buf);
Len := Length(Sub);
while i <> 0 do
begin
Inc(Result);
Delete(Buf, 1, i + Len - 1);
i := Pos(Sub, Buf);
end;
end;
{***************************************************}
procedure TJsDbTree.TreeRefresh;
var curID, nodeTxt: string;
level: integer;
mynode: array[0..8] of TTreenode;
P: PString;
Ind: integer;
flm: string;
begin
flm := FDataLink.DataSet.FieldByName(DataField).AsString;
Ftree.OnChange := nil;
if FTree.Selected = nil then
Ind:= 0
else
Ind:= FTree.Selected.AbsoluteIndex;
level := 0;
Ftree.Items.Clear;
new(p);
p^ := FTreeName;
mynode[level] := Ftree.items.AddChildObject(nil, FTreeName, p);
mynode[level].ImageIndex := 1;
with FDataLink.DataSet do
begin
try
FDataLink.DataSet.DisableControls;
FDataLink.DataSource.Enabled := false;
FDataLink.DataSet.Close;////
FDataLink.DataSet.Open;////
FDataLink.DataSet.Filtered := false;
FDataLink.DataSet.First;
while not FDataLink.DataSet.Eof do
begin
new(p);
if Fn4.Checked then
begin
curID := trim(FDataLink.DataSet.FieldByName(DataField).AsString);
p^ := curID;
nodeTxt := trim(FDataLink.DataSet.FieldByName(FMcData).AsString);
if FTreeCodeFormat <> '' then
level := GetNodeLevel(FTreeCodeFormat, curID)
else
if FTreeCodeSeperate <> '' then
level := StrSubCount(curID, FTreeCodeSeperate{'-'}) + 1
else
level := 0;
end
else begin
curID := trim(FDataLink.DataSet.FieldByName(McData).AsString);
p^ := curID;
nodeTxt := trim(FDataLink.DataSet.FieldByName(DataField).AsString);
if FTreeCodeFormat <> '' then
level := GetNodeLevel(FTreeCodeFormat, nodeTxt)
else
if FTreeCodeSeperate <> '' then
level := StrSubCount(nodeTxt, FTreeCodeSeperate{'-'}) + 1
else
level := 0;
end;
if (level > 0) and (level < 9) then
begin
mynode[level] := FTree.items.AddChildObject(mynode[level - 1], nodeTxt, p);
mynode[level].ImageIndex := 2;
end;
Next;
end;
Locate(DataField, flm, []);
FDataLink.DataSource.Enabled := True;
EnableControls;
Ftree.OnChange := FTreeChange;
FTree.Selected := FTree.Items[Ind];
except;
//Close;
end;
end;
end;
{***************************************************}
procedure TJsDbTree.FTreeChange(Sender: TObject; Node: TTreeNode);
var flm, SqlText: string;
begin
with DataSource.DataSet do
begin
DisableControls;
SqlText := FieldByName(DataField).AsString;
flm := GetCurID;
Filter := DataField + ' like '''+ trim(flm) +'*''';
Filtered := Locate(DataField, flm, []);
Locate(DataField, SqlText, []);
EnableControls;
end;
if Assigned(FOnTreeChange) then
FOnTreeChange(Sender,Node); //继续加载form本身的onshow
end;
{***************************************************}
procedure Register;
begin
RegisterComponents('jszc', [TJsDbTree]);
end;
{***************************************************}
end.