| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119 |
- {******************************************************************************}
- { CnPack For Delphi/C++Builder }
- { 中国人自己的开放源码第三方开发包 }
- { (C)Copyright 2001-2018 CnPack 开发组 }
- { ------------------------------------ }
- { }
- { 本开发包是开源的自由软件,您可以遵照 CnPack 的发布协议来修 }
- { 改和重新发布这一程序。 }
- { }
- { 发布这一开发包的目的是希望它有用,但没有任何担保。甚至没有 }
- { 适合特定目的而隐含的担保。更详细的情况请参阅 CnPack 发布协议。 }
- { }
- { 您应该已经和开发包一起收到一份 CnPack 发布协议的副本。如果 }
- { 还没有,可访问我们的网站: }
- { }
- { 网站地址:http://www.cnpack.org }
- { 电子邮件:master@cnpack.org }
- { }
- {******************************************************************************}
- unit CnAOTreeView;
- {* |<PRE>
- ================================================================================
- * 软件名称:不可视工具组件包
- * 单元名称:自动参数设置 TreeView 组件单元
- * 单元作者:周劲羽 (zjy@cnpack.org)
- * 开发平台:PWin2000 SP4 + Delphi 5.01
- * 兼容测试:PWin9X/2000/XP + Delphi 5/6/7
- * 本 地 化:该单元中的字符串均符合本地化处理方式
- * 单元标识:$Id$
- * 备 注:该单元定义了自动参数设置 TreeView 组件
- * 该组件用于在运行时使用树状结构根据设置信息对象显示通用的设置界面。
- ================================================================================
- |</PRE>}
- interface
- {$I CnPack.inc}
- uses
- Windows, Messages, SysUtils, Classes, Graphics, Controls, ComCtrls, TypInfo,
- {$IFDEF COMPILER6_UP} Variants, {$ENDIF COMPILER6_UP}
- StdCtrls, ImgList, CnSpin, Dialogs, Menus, Math, Forms, CnGraphConsts,
- CnAutoOption;
- type
- { TCnAOTreeView }
- EUnsupportedPropKind = class(Exception);
- TCnOptionKind = (
- okUnknown, okGroup, okCustom, okBoolFalse, okBoolTrue, okString,
- okStringCombo, okInteger, okIntegerCombo, okFloat, okDateTime,
- okDate, okTime, okEnum, okSet, okVariant, okFont, okColor, okShortCut,
- okStrings);
- TCreateInplaceEditEvent = procedure(Sender: TObject; InplaceEdit: TControl;
- AOption: TCnBaseOption) of object;
- TGetItemTextEvent = procedure(Sender: TObject; AOption: TCnOptionItem;
- var AText: string) of object;
- TCnAOTreeView = class(TCustomTreeView)
- private
- FImageList: TImageList;
- FInplaceEdit: TControl;
- FModified: Boolean;
- FOptions: TCnOptionGroup;
- FOnCreateInplaceEdit: TCreateInplaceEditEvent;
- FOnGetItemText: TGetItemTextEvent;
- procedure ApplyInplaceEdit;
- procedure ComboBoxDropDown(Sender: TObject);
- procedure CreateInplaceEdit;
- procedure FreeInplaceEdit;
- procedure OnColorClick(Sender: TObject);
- procedure OnFontClick(Sender: TObject);
- procedure OnInplaceEditEnterExit(Sender: TObject);
- procedure SetNodeImageIndex(Node: TTreeNode; Index: Integer);
- procedure UpdateInplaceEdit;
- procedure SetOptions(Value: TCnOptionGroup);
- protected
- function CanEdit(Node: TTreeNode): Boolean; override;
- procedure Change(Node: TTreeNode); override;
- procedure Click; override;
- function DoClickNode(Node: TTreeNode): Boolean;
- procedure DoCustomDrawItem(Sender: TCustomTreeView; Node: TTreeNode;
- State: TCustomDrawState; var DefaultDraw: Boolean);
- procedure DoEnter; override;
- procedure DoExit; override;
- function GetOptionKind(Option: TCnBaseOption; RaiseError: Boolean = False):
- TCnOptionKind;
- procedure GetSelectedIndex(Node: TTreeNode); override;
- procedure UpdateNode(Node: TTreeNode);
- procedure WMChar(var Message: TWMChar); message WM_CHAR;
- procedure WMHScroll(var Message: TWMHScroll); message WM_HSCROLL;
- procedure WMMouseWheel(var Message: TWMMouseWheel); message WM_MOUSEWHEEL;
- procedure WMVScroll(var Message: TWMVScroll); message WM_VSCROLL;
- property ImageList: TImageList read FImageList;
- public
- constructor Create(AOwner: TComponent); override;
- {* 类构造器 }
- destructor Destroy; override;
- {* 类析构器 }
- procedure ApplyOption;
- {* 应用当前的设置到对象属性 }
- procedure DefaultOption;
- {* 恢复设置为原对象属性的默认值 }
- procedure ResetOption;
- {* 恢复设置为原对象属性的当前值 }
- procedure UpdateTreeView;
- {* 更新设置树 }
- property Modified: Boolean read FModified;
- {* 标识是否有属性被修改 }
- property Options: TCnOptionGroup read FOptions write SetOptions;
- {* 用于设置的参数组对象 }
- published
- property Align;
- property Anchors;
- property AutoExpand;
- property BiDiMode;
- property BorderStyle;
- property BorderWidth;
- property ChangeDelay;
- property Color;
- property Constraints;
- property Ctl3D;
- property DragCursor;
- property DragKind;
- property DragMode;
- property Enabled;
- property Font;
- property HideSelection;
- property HotTrack;
- property Indent;
- property OnChange;
- property OnChanging;
- property OnClick;
- property OnCollapsed;
- property OnCollapsing;
- property OnContextPopup;
- property OnDblClick;
- property OnDeletion;
- property OnDragDrop;
- property OnDragOver;
- property OnEndDock;
- property OnEndDrag;
- property OnEnter;
- property OnExit;
- property OnExpanded;
- property OnExpanding;
- property OnGetSelectedIndex;
- property OnKeyDown;
- property OnKeyPress;
- property OnKeyUp;
- property OnMouseDown;
- property OnMouseMove;
- property OnMouseUp;
- property OnStartDock;
- property OnStartDrag;
- property ParentBiDiMode;
- property ParentColor default False;
- property ParentCtl3D;
- property ParentFont;
- property ParentShowHint;
- property PopupMenu;
- property RightClickSelect;
- property RowSelect;
- property ShowButtons default False;
- property ShowHint;
- property ShowLines default False;
- property ShowRoot;
- property TabOrder;
- property TabStop default True;
- property ToolTips;
- property Visible;
- property OnCreateInplaceEdit: TCreateInplaceEditEvent
- read FOnCreateInplaceEdit write FOnCreateInplaceEdit;
- property OnGetItemText: TGetItemTextEvent read FOnGetItemText write FOnGetItemText;
- end;
- implementation
- {$IFDEF DEBUG}
- uses
- CnDebug;
- {$ENDIF}
- {$R *.res}
- const
- csIdxGroup = 0;
- csIdxCustom = 1;
- csIdxUnChecked = 2;
- csIdxChecked = 3;
- csIdxUnSelected = 4;
- csIdxSelected = 5;
- csIdxString = 6;
- csIdxStringCombo = 7;
- csIdxInteger = 8;
- csIdxIntegerCombo = 9;
- csIdxFloat = 10;
- csIdxEnum = 11;
- csIdxSet = 12;
- csIdxVariant = 13;
- csIdxFont = 14;
- csIdxDateTime = 15;
- csIdxDate = 16;
- csIdxTime = 17;
- csIdxColor = 18;
- csIdxShortCut = 19;
- csIdxStrings = 20;
- csSepStr = ': ';
- csInplaceEditHeight = 20;
- csInplaceEditWidth = 120;
- csInplaceButtonHeight = 20;
- csInplaceButtonWidth = 60;
- csInplaceMemoHeight = 60;
- csInplaceMemoWidth = 120;
- csInplaceSpace = 4;
- csMaxStrLength = 15;
- csImageIndexs: array[TCnOptionKind] of Integer = (
- -1, csIdxGroup, csIdxCustom, csIdxUnChecked, csIdxChecked, csIdxString,
- csIdxStringCombo, csIdxInteger, csIdxIntegerCombo, csIdxFloat, csIdxDateTime,
- csIdxDate, csIdxTime, csIdxEnum, csIdxSet, csIdxVariant, csIdxFont, csIdxColor,
- csIdxShortCut, csIdxStrings);
- type
- TWinControlHack = class(TWinControl);
- constructor TCnAOTreeView.Create(AOwner: TComponent);
- var
- Bitmap: TBitmap;
- begin
- inherited;
- FImageList := TImageList.Create(Self);
- Images := FImageList;
- Bitmap := TBitmap.Create;
- try
- Bitmap.LoadFromResourceName(HInstance, 'CNAOTREEVIEW');
- FImageList.AddMasked(Bitmap, Bitmap.TransparentColor);
- finally
- Bitmap.Free;
- end;
-
- ShowLines := False;
- ShowButtons := False;
- ReadOnly := True;
- OnCustomDrawItem := DoCustomDrawItem;
- end;
- destructor TCnAOTreeView.Destroy;
- begin
- FImageList.Free;
- inherited;
- end;
- procedure TCnAOTreeView.ApplyInplaceEdit;
- var
- Node: TTreeNode;
- Item: TCnOptionItem;
- Obj: TObject;
- // 将字符串转换为匹配的格式
- function GetString(PropKind: TTypeKind; const Value: string): Variant;
- var
- C: Char;
- WC: WideChar;
- WS: WideString;
- begin
- case PropKind of
- tkChar:
- begin
- if Value <> '' then
- C := Value[1]
- else
- C := #0;
- Result := C;
- end;
- tkWChar:
- begin
- WS := Value;
- if WS <> '' then
- WC := WS[1]
- else
- WC := #0;
- Result := WC;
- end;
- tkWString {$IFDEF UNICODE_STRING}, tkUString{$ENDIF}:
- begin
- WS := Value;
- Result := WS;
- end;
- else
- Result := Value;
- end;
- end;
- begin
- if FInplaceEdit = nil then Exit;
- Node := TTreeNode(FInplaceEdit.Tag);
- Item := TCnOptionItem(Node.Data);
-
- if FInplaceEdit is TDateTimePicker then
- begin
- Item.Value := TDateTimePicker(FInplaceEdit).DateTime;
- FModified := True;
- end
- else if FInplaceEdit is TCnSpinEdit then
- begin
- with TCnSpinEdit(FInplaceEdit) do
- begin
- if (MaxValue > MinValue) and ((MaxValue <> 0) or (MinValue <> 0)) then
- begin
- if Value > MaxValue then
- Value := MaxValue;
- if Value < MinValue then
- Value := MinValue;
- end;
- Item.Value := Value;
- end;
- FModified := True;
- end
- else if FInplaceEdit is TComboBox then
- begin
- case GetOptionKind(Item) of
- okIntegerCombo:
- Item.Value := TComboBox(FInplaceEdit).ItemIndex;
- okStringCombo:
- Item.Value := GetString(Item.PropKind, TComboBox(FInplaceEdit).Text);
- else
- Assert(False);
- end;
- FModified := True;
- end
- else if FInplaceEdit is THotKey then
- begin
- Item.Value := THotKey(FInplaceEdit).HotKey;
- FModified := True;
- end
- else if FInplaceEdit is TEdit then
- begin
- try
- case GetOptionKind(Item) of
- okFloat:
- Item.Value := StrToFloat(TEdit(FInplaceEdit).Text);
- okDateTime:
- Item.Value := StrToDateTime(TEdit(FInplaceEdit).Text);
- okString:
- Item.Value := GetString(Item.PropKind, TEdit(FInplaceEdit).Text);
- okVariant:
- Item.Value := TEdit(FInplaceEdit).Text;
- else
- Assert(False);
- end;
- FModified := True;
- except
- ;
- end;
- end
- else if FInplaceEdit is TMemo then
- begin
- {$IFDEF WIN64}
- Obj := TObject(Integer(Item.Value));
- {$ELSE}
- Integer(Obj) := Item.Value;
- {$ENDIF}
- if Obj is TStrings then
- TStrings(Obj).Text := TMemo(FInplaceEdit).Lines.Text;
- FModified := True;
- end
- else if FInplaceEdit is TButton then
- begin
- // None
- end
- else
- begin
- // None
- end;
- UpdateNode(Node);
- Repaint;
- end;
- procedure TCnAOTreeView.ApplyOption;
- procedure DoApplyOption(Option: TCnBaseOption);
- var
- i: Integer;
- begin
- if Option is TCnOptionItem then
- TCnOptionItem(Option).ApplyOption
- else if Option is TCnOptionGroup then
- for i := 0 to TCnOptionGroup(Option).Count - 1 do
- DoApplyOption(TCnOptionGroup(Option)[i]);
- end;
- begin
- ApplyInplaceEdit;
- DoApplyOption(FOptions);
- end;
- function TCnAOTreeView.CanEdit(Node: TTreeNode): Boolean;
- begin
- Result := False;
- end;
- procedure TCnAOTreeView.Change(Node: TTreeNode);
- begin
- inherited;
- CreateInplaceEdit;
- end;
- procedure TCnAOTreeView.Click;
- var
- P: TPoint;
- Node: TTreeNode;
- begin
- inherited;
- GetCursorPos(P);
- P := ScreenToClient(P);
- Node := GetNodeAt(P.X, P.Y);
- if Node <> nil then
- DoClickNode(Node);
- end;
- procedure TCnAOTreeView.ComboBoxDropDown(Sender: TObject);
- var
- i: Integer;
- MaxWidth: Integer;
- Bitmap: Graphics.TBitmap;
- ComboBox: TComboBox;
- begin
- if not (Sender is TComboBox) then
- Exit;
- ComboBox := TComboBox(Sender);
- MaxWidth := ComboBox.Width;
- Bitmap := Graphics.TBitmap.Create;
- try
- Bitmap.Canvas.Font.Assign(ComboBox.Font);
- for i := 0 to ComboBox.Items.Count - 1 do
- MaxWidth := Max(MaxWidth, Bitmap.Canvas.TextWidth(ComboBox.Items[i]) + 10);
- finally;
- Bitmap.Free;
- end;
- if ComboBox.Items.Count > ComboBox.DropDownCount then
- Inc(MaxWidth, GetSystemMetrics(SM_CXVSCROLL));
- MaxWidth := Min(400, MaxWidth);
- if MaxWidth > ComboBox.Width then
- SendMessage(ComboBox.Handle, CB_SETDROPPEDWIDTH, MaxWidth, 0)
- else
- SendMessage(ComboBox.Handle, CB_SETDROPPEDWIDTH, 0, 0)
- end;
- procedure TCnAOTreeView.CreateInplaceEdit;
- var
- Option: TCnBaseOption;
- Item: TCnOptionItem;
- procedure CreateSpin(Value, MinValue, MaxValue: Integer);
- begin
- FInplaceEdit := TCnSpinEdit.Create(Self);
- FInplaceEdit.Height := csInplaceEditHeight;
- FInplaceEdit.Width := csInplaceEditWidth;
- TCnSpinEdit(FInplaceEdit).Value := Value;
- TCnSpinEdit(FInplaceEdit).MinValue := MinValue;
- TCnSpinEdit(FInplaceEdit).MaxValue := MaxValue;
- UpdateInplaceEdit;
- end;
- procedure CreateDateTimePicker(Kind: TDateTimeKind; Value: TDateTime);
- begin
- FInplaceEdit := TDateTimePicker.Create(Self);
- FInplaceEdit.Height := csInplaceEditHeight;
- FInplaceEdit.Width := csInplaceEditWidth;
- TDateTimePicker(FInplaceEdit).Kind := Kind;
- TDateTimePicker(FInplaceEdit).DateTime := Value;
- UpdateInplaceEdit;
- end;
- procedure CreateEdit(const Value: string);
- begin
- FInplaceEdit := TEdit.Create(Self);
- FInplaceEdit.Height := csInplaceEditHeight;
- FInplaceEdit.Width := csInplaceEditWidth;
- UpdateInplaceEdit;
- TEdit(FInplaceEdit).Text := Value;
- end;
- procedure CreateComboBox(const Value: string; List: TStrings; DropDownList: Boolean);
- begin
- FInplaceEdit := TComboBox.Create(Self);
- FInplaceEdit.Height := csInplaceEditHeight;
- FInplaceEdit.Width := csInplaceEditWidth;
- UpdateInplaceEdit;
- TComboBox(FInplaceEdit).Items.Assign(List);
- TComboBox(FInplaceEdit).OnDropDown := ComboBoxDropDown;
- if DropDownList then
- begin
- TComboBox(FInplaceEdit).Style := csDropDownList;
- TComboBox(FInplaceEdit).ItemIndex := List.IndexOf(Value);
- end
- else
- begin
- TComboBox(FInplaceEdit).Style := csDropDown;
- TComboBox(FInplaceEdit).Text := Value;
- end;
- end;
- procedure CreateButton(Caption: string; OnClick: TNotifyEvent);
- begin
- FInplaceEdit := TButton.Create(Self);
- FInplaceEdit.Height := csInplaceButtonHeight;
- FInplaceEdit.Width := csInplaceButtonWidth;
- UpdateInplaceEdit;
- if Caption = '' then
- Caption := SCnAOCaptionOption;
- TButton(FInplaceEdit).Caption := Caption;
- TButton(FInplaceEdit).OnClick := OnClick;
- end;
- procedure CreateHotKey(ShortCut: TShortCut);
- begin
- FInplaceEdit := THotKey.Create(Self);
- FInplaceEdit.Height := csInplaceEditHeight;
- FInplaceEdit.Width := csInplaceEditWidth;
- UpdateInplaceEdit;
- THotKey(FInplaceEdit).HotKey := ShortCut;
- end;
- procedure CreateMemo(Value: Variant);
- var
- Obj: TPersistent;
- begin
- {$IFDEF WIN64}
- Obj := TPersistent(Integer(Value));
- {$ELSE}
- Integer(Obj) := Value;
- {$ENDIF}
- Assert(Obj is TStrings);
- FInplaceEdit := TMemo.Create(Self);
- FInplaceEdit.Width := csInplaceMemoWidth;
- FInplaceEdit.Height := csInplaceMemoHeight;
- UpdateInplaceEdit;
- TMemo(FInplaceEdit).Lines.Assign(Obj);
- end;
- begin
- FreeInplaceEdit;
- if (Selected = nil) or (Selected.Data = nil) then Exit;
- Option := TCnBaseOption(Selected.Data);
- Item := TCnOptionItem(Selected.Data);
- case GetOptionKind(Option) of
- okCustom:
- CreateButton(TCnOptionCustom(Option).Caption, TCnOptionCustom(Option).OnClick);
- okString:
- CreateEdit(Item.Value);
- okStringCombo:
- CreateComboBox(Item.Value, Item.List, False);
- okInteger:
- CreateSpin(Item.Value, Item.MinValue, Item.MaxValue);
- okIntegerCombo:
- CreateComboBox(Item.List[Item.Value], Item.List, True);
- okFloat:
- CreateEdit(FloatToStr(Item.Value));
- okDateTime:
- CreateEdit(DateTimeToStr(TDateTime(Item.Value)));
- okDate:
- CreateDateTimePicker(dtkDate, TDate(Item.Value));
- okTime:
- CreateDateTimePicker(dtkTime, TTime(Item.Value));
- okVariant:
- CreateEdit(VarToStr(Item.Value));
- okFont:
- CreateButton(SCnAOCaptionFont, OnFontClick);
- okColor:
- CreateButton(SCnAOCaptionColor, OnColorClick);
- okShortCut:
- CreateHotKey(Item.Value);
- okStrings:
- CreateMemo(Item.Value);
- else
- Exit;
- end;
- if Assigned(FOnCreateInplaceEdit) then
- FOnCreateInplaceEdit(Self, FInplaceEdit, Option);
- end;
- procedure TCnAOTreeView.DefaultOption;
- procedure DoDefaultOption(Option: TCnBaseOption);
- var
- i: Integer;
- begin
- if Option is TCnOptionItem then
- TCnOptionItem(Option).DefaultOption
- else if Option is TCnOptionGroup then
- for i := 0 to TCnOptionGroup(Option).Count - 1 do
- DoDefaultOption(TCnOptionGroup(Option)[i]);
- end;
- begin
- DoDefaultOption(FOptions);
- UpdateTreeView;
- end;
- function TCnAOTreeView.DoClickNode(Node: TTreeNode): Boolean;
- var
- i, Min, Max: Integer;
- Item: TCnOptionItem;
- BoolValue: Boolean;
- EnumInfo: PTypeInfo;
- SetValue: TIntegerSet;
- begin
- Result := False;
- if Node = nil then Exit;
-
- if Node.Data = nil then // 是集合或枚举子项
- begin
- Item := TCnOptionItem(Node.Parent.Data);
- Assert(Item is TCnOptionItem);
- Assert(GetOptionKind(Item) in [okEnum, okSet]);
- case GetOptionKind(Item) of
- okEnum:
- begin
- Item.Value := Node.Index + Item.MinValue;
- for i := 0 to Node.Parent.Count - 1 do
- if i = Node.Index then
- SetNodeImageIndex(Node.Parent.Item[i], csIdxSelected)
- else
- SetNodeImageIndex(Node.Parent.Item[i], csIdxUnSelected)
- end;
- okSet:
- begin
- EnumInfo := GetTypeData(Item.PropInfo^.PropType^)^.CompType^;
- if Node.ImageIndex = csIdxChecked then
- SetNodeImageIndex(Node, csIdxUnChecked)
- else
- SetNodeImageIndex(Node, csIdxChecked);
- SetValue := [];
- Min := GetTypeData(EnumInfo).MinValue;
- Max := GetTypeData(EnumInfo).MaxValue;
- for i := Min to Max do
- if Node.Parent.Item[i].ImageIndex = csIdxChecked then
- Include(SetValue, i + Min);
- Item.Value := Integer(SetValue);
- end;
- end;
- FModified := True;
- Result := True;
- end
- else if GetOptionKind(TCnBaseOption(Node.Data)) in [okBoolFalse, okBoolTrue] then
- begin
- Item := TCnOptionItem(Node.Data);
-
- BoolValue := not Item.Value;
- Item.Value := BoolValue;
- if BoolValue then
- SetNodeImageIndex(Node, csIdxChecked)
- else
- SetNodeImageIndex(Node, csIdxUnChecked);
- FModified := True;
- Result := True;
- end;
- end;
- procedure TCnAOTreeView.DoCustomDrawItem(Sender: TCustomTreeView;
- Node: TTreeNode; State: TCustomDrawState; var DefaultDraw: Boolean);
- begin
- // Todo: 自绘制颜色属性及字体等
- DefaultDraw := True;
- end;
- procedure TCnAOTreeView.DoEnter;
- begin
- inherited;
- Change(Selected);
- end;
- procedure TCnAOTreeView.DoExit;
- begin
- inherited;
- FreeInplaceEdit;
- end;
- procedure TCnAOTreeView.FreeInplaceEdit;
- begin
- if FInplaceEdit <> nil then
- begin
- ApplyInplaceEdit;
- FreeAndNil(FInplaceEdit);
- end;
- end;
- function TCnAOTreeView.GetOptionKind(Option: TCnBaseOption; RaiseError: Boolean
- = False): TCnOptionKind;
- var
- Item: TCnOptionItem;
- BoolValue: Boolean;
- Obj: TObject;
- begin
- Result := okUnknown;
-
- if Option is TCnOptionCustom then
- Result := okCustom
- else if Option is TCnOptionGroup then
- Result := okGroup
- else if Option is TCnOptionItem then
- begin
- Item := TCnOptionItem(Option);
- case Item.PropKind of
- tkInteger, tkInt64:
- begin
- if Item.PropInfo^.PropType^ = TypeInfo(TColor) then
- Result := okColor
- else if Item.PropInfo^.PropType^ = TypeInfo(TShortCut) then
- Result := okShortCut
- else if (Item.List.Count > 0) and (Item.Value >= 0) and
- (Item.Value < Item.List.Count) then
- Result := okIntegerCombo
- else
- Result := okInteger;
- end;
- tkFloat:
- begin
- if Item.PropInfo^.PropType^ = TypeInfo(TDateTime) then
- Result := okDateTime
- else if Item.PropInfo^.PropType^ = TypeInfo(TDate) then
- Result := okDate
- else if Item.PropInfo^.PropType^ = TypeInfo(TTime) then
- Result := okTime
- else
- Result := okFloat;
- end;
- tkChar, tkString, tkWChar, tkLString, tkWString{$IFDEF UNICODE_STRING}, tkUString{$ENDIF}:
- begin
- if Item.List.Count > 0 then
- Result := okStringCombo
- else
- Result := okString
- end;
- tkEnumeration:
- begin
- if IsBooleanType(Item.PropInfo^.PropType^) or
- IsBoolType(Item.PropInfo^.PropType^) then
- begin
- BoolValue := Item.Value;
- if BoolValue then
- Result := okBoolTrue
- else
- Result := okBoolFalse;
- end
- else
- Result := okEnum;
- end;
- tkSet:
- begin
- Result := okSet;
- end;
- tkClass:
- begin
- {$IFDEF WIN64}
- Obj := TObject(Integer(Item.Value));
- {$ELSE}
- Integer(Obj) := Item.Value;
- {$ENDIF}
- if Obj is TFont then
- Result := okFont
- else if Obj is TStrings then
- Result := okStrings
- else if RaiseError then
- raise EUnsupportedPropKind.Create('Unsupported Property Kind: ' +
- Obj.ClassName);
- end;
- tkVariant:
- begin
- Result := okVariant;
- end;
- end;
- end;
- if (Result = okUnknown) and RaiseError then
- if Option is TCnOptionItem then
- raise EUnsupportedPropKind.Create('Unsupported Property Kind: ' +
- GetEnumName(TypeInfo(TTypeKind), Ord(TCnOptionItem(Option).PropKind)))
- else
- raise EUnsupportedPropKind.Create('Unsupported Property Define: ' + Option.Text);
- end;
- procedure TCnAOTreeView.GetSelectedIndex(Node: TTreeNode);
- begin
- Node.SelectedIndex := Node.ImageIndex;
- end;
- procedure TCnAOTreeView.OnColorClick(Sender: TObject);
- var
- Node: TTreeNode;
- Item: TCnOptionItem;
- begin
- if FInplaceEdit = nil then Exit;
- Node := TTreeNode(FInplaceEdit.Tag);
- Item := TCnOptionItem(Node.Data);
- with TColorDialog.Create(Self) do
- try
- Color := ColorToRGB(Item.Value);
- if Execute then
- Item.Value := Color;
- finally
- Free;
- end;
- end;
- procedure TCnAOTreeView.OnFontClick(Sender: TObject);
- var
- Node: TTreeNode;
- Item: TCnOptionItem;
- Obj: TFont;
- begin
- if FInplaceEdit = nil then Exit;
- Node := TTreeNode(FInplaceEdit.Tag);
- Item := TCnOptionItem(Node.Data);
- {$IFDEF WIN64}
- Obj := TFont(Integer(Item.Value));
- {$ELSE}
- Integer(Obj) := Item.Value;
- {$ENDIF}
- with TFontDialog.Create(Self) do
- try
- Font.Assign(Obj);
- if Execute then
- Obj.Assign(Font);
- finally
- Free;
- end;
- end;
- procedure TCnAOTreeView.OnInplaceEditEnterExit(Sender: TObject);
- var
- i: Integer;
- begin
- if FInplaceEdit <> nil then
- begin
- FInplaceEdit.Invalidate;
- if FInplaceEdit is TWinControl then
- for i := 0 to TWinControl(FInplaceEdit).ControlCount - 1 do
- TWinControl(FInplaceEdit).Controls[i].Invalidate;
- end;
- end;
- procedure TCnAOTreeView.ResetOption;
- procedure DoResetOption(Option: TCnBaseOption);
- var
- i: Integer;
- begin
- if Option is TCnOptionItem then
- TCnOptionItem(Option).ResetOption
- else if Option is TCnOptionGroup then
- for i := 0 to TCnOptionGroup(Option).Count - 1 do
- try
- DoResetOption(TCnOptionGroup(Option)[i]);
- except
- Application.HandleException(nil);
- end;
- end;
- begin
- DoResetOption(FOptions);
- UpdateTreeView;
- end;
- procedure TCnAOTreeView.SetNodeImageIndex(Node: TTreeNode; Index: Integer);
- begin
- Node.ImageIndex := Index;
- Node.SelectedIndex := Index;
- end;
- procedure TCnAOTreeView.UpdateInplaceEdit;
- var
- R1, R2: TRect;
- begin
- if (Selected <> nil) and (TopItem <> nil) and (FInplaceEdit <> nil) then
- begin
- FInplaceEdit.Tag := Integer(Selected);
- FInplaceEdit.Parent := Self;
- if FInplaceEdit is TWinControl then
- begin
- TWinControlHack(FInplaceEdit).OnEnter := OnInplaceEditEnterExit;
- TWinControlHack(FInplaceEdit).OnExit := OnInplaceEditEnterExit;
- end;
- Selected.Text := TCnBaseOption(Selected.Data).Text + csSepStr;
- R1 := Selected.DisplayRect(True);
- R2 := TopItem.DisplayRect(True);
- FInplaceEdit.Top := R1.Top - R2.Top;
- FInplaceEdit.Left := R1.Right + csInplaceSpace;
- FInplaceEdit.Invalidate;
- //Invalidate;
- // Todo: 滚动时刷新有时不正常
- end;
- end;
- procedure TCnAOTreeView.UpdateNode(Node: TTreeNode);
- var
- Idx: Integer;
- Item: TCnOptionItem;
- OptionKind: TCnOptionKind;
- OrdValue: Integer;
- EnumInfo: PTypeInfo;
- function FontToStr(Value: Variant): string;
- var
- Obj: TObject;
- begin
- {$IFDEF WIN64}
- Obj := TObject(Integer(Value));
- {$ELSE}
- Integer(Obj) := Value;
- {$ENDIF}
- if Obj is TFont then
- Result := Format('%s,%d', [TFont(Obj).Name, TFont(Obj).Size])
- else
- Result := '';
- end;
- function StringsToStr(Value: Variant): string;
- var
- Obj: TObject;
- begin
- {$IFDEF WIN64}
- Obj := TObject(Integer(Value));
- {$ELSE}
- Integer(Obj) := Value;
- {$ENDIF}
- if Obj is TStrings then
- Result := StringReplace(TStrings(Obj).Text, #13#10, ' ', [rfReplaceAll])
- else
- Result := '';
- if Length(Result) > csMaxStrLength - 3 then
- Result := Copy(Result, 1, csMaxStrLength - 3) + '...';
- end;
- procedure SetNodeText(AItem: TCnOptionItem; Text: string);
- begin
- if Assigned(FOnGetItemText) then
- FOnGetItemText(Self, AItem, Text);
- Node.Text := AItem.Text + csSepStr + Text;
- end;
- begin
- Assert(Node <> nil);
- if Node.Data = nil then // 是集合或枚举子项
- begin
- Item := TCnOptionItem(Node.Parent.Data);
- Assert(GetOptionKind(Item) in [okEnum, okSet]);
- case GetOptionKind(Item) of
- okEnum:
- begin
- OrdValue := Item.Value;
- Idx := Node.Index;
- if Idx < Item.List.Count then
- Node.Text := Item.List[Idx - Item.MinValue]
- else
- Node.Text := GetEnumName(Item.PropInfo^.PropType^, Idx);
- if Idx = OrdValue then
- SetNodeImageIndex(Node, csIdxSelected)
- else
- SetNodeImageIndex(Node, csIdxUnSelected);
- end;
- okSet:
- begin
- OrdValue := Item.Value;
- EnumInfo := GetTypeData(Item.PropInfo^.PropType^)^.CompType^;
- Idx := Node.Index;
- if Idx < Item.List.Count then
- Node.Text := Item.List[Idx - GetTypeData(EnumInfo).MinValue]
- else
- Node.Text := GetEnumName(EnumInfo, Idx);
- if Idx in TIntegerSet(OrdValue) then
- SetNodeImageIndex(Node, csIdxChecked)
- else
- SetNodeImageIndex(Node, csIdxUnChecked);
- end;
- end;
- end
- else
- begin
- Item := TCnOptionItem(Node.Data);
- OptionKind := GetOptionKind(TCnBaseOption(Node.Data));
- SetNodeImageIndex(Node, csImageIndexs[OptionKind]);
- case OptionKind of
- okString, okStringCombo:
- SetNodeText(Item, Item.Value);
- okInteger:
- SetNodeText(Item, IntToStr(Item.Value));
- okIntegerCombo:
- SetNodeText(Item, Item.List[Item.Value]);
- okFloat:
- SetNodeText(Item, FloatToStr(Item.Value));
- okDateTime:
- SetNodeText(Item, DateTimeToStr(Item.Value));
- okDate:
- SetNodeText(Item, DateToStr(Item.Value));
- okTime:
- SetNodeText(Item, TimeToStr(Item.Value));
- okVariant:
- SetNodeText(Item, VarToStr(Item.Value));
- okFont:
- SetNodeText(Item, FontToStr(Item.Value));
- okColor:
- SetNodeText(Item, IntToHex(ColorToRGB(Item.Value), 8));
- okShortCut:
- SetNodeText(Item, ShortCutToText(Item.Value));
- okStrings:
- SetNodeText(Item, StringsToStr(Item.Value));
- else
- Node.Text := TCnBaseOption(Node.Data).Text;
- end;
- end;
- end;
- procedure TCnAOTreeView.UpdateTreeView;
- function AddNode(ParentNode: TTreeNode; AOption: TCnBaseOption): TTreeNode;
- var
- i: Integer;
- EnumInfo: PTypeInfo;
- begin
- Result := Items.AddChildObject(ParentNode, AOption.Text, AOption);
- try
- UpdateNode(Result);
- case GetOptionKind(AOption, True) of
- okGroup:
- begin
- with TCnOptionGroup(AOption) do
- for i := 0 to Count - 1 do
- AddNode(Result, Items[i]);
- end;
- okEnum:
- with TCnOptionItem(AOption) do
- begin
- for i := MinValue to MaxValue do
- begin
- UpdateNode(Items.AddChildObject(Result, '', nil));
- end;
- end;
- okSet:
- with TCnOptionItem(AOption) do
- begin
- EnumInfo := GetTypeData(PropInfo^.PropType^)^.CompType^;
- for i := GetTypeData(EnumInfo).MinValue to GetTypeData(EnumInfo).MaxValue do
- UpdateNode(Items.AddChildObject(Result, '', nil));
- end;
- end;
- except
- Result.Free;
- Application.HandleException(Self);
- end;
- end;
- begin
- Items.BeginUpdate;
- try
- Items.Clear;
- AddNode(nil, Options);
- Selected := Items.GetFirstNode;
- FullExpand;
- TopItem := Selected;
- FModified := False;
- finally
- Items.EndUpdate;
- end;
- end;
- procedure TCnAOTreeView.SetOptions(Value: TCnOptionGroup);
- begin
- if FOptions <> Value then
- begin
- FOptions := Value;
- ResetOption;
- end;
- end;
- procedure TCnAOTreeView.WMChar(var Message: TWMChar);
- begin
- if (Char(Message.CharCode) <> ' ') or not DoClickNode(Selected) then
- inherited;
- end;
- procedure TCnAOTreeView.WMHScroll(var Message: TWMHScroll);
- begin
- inherited;
- UpdateInplaceEdit;
- end;
- procedure TCnAOTreeView.WMMouseWheel(var Message: TWMMouseWheel);
- begin
- inherited;
- UpdateInplaceEdit;
- end;
- procedure TCnAOTreeView.WMVScroll(var Message: TWMVScroll);
- begin
- inherited;
- UpdateInplaceEdit;
- end;
- end.
|