1877 lines
60 KiB
ObjectPascal
1877 lines
60 KiB
ObjectPascal
|
|
{********************************************************************}
|
|
{ }
|
|
{ Developer Express Visual Component Library }
|
|
{ ExpressEditors }
|
|
{ }
|
|
{ Copyright (c) 1998-2009 Developer Express Inc. }
|
|
{ ALL RIGHTS RESERVED }
|
|
{ }
|
|
{ The entire contents of this file is protected by U.S. and }
|
|
{ International Copyright Laws. Unauthorized reproduction, }
|
|
{ reverse-engineering, and distribution of all or any portion of }
|
|
{ the code contained in this file is strictly prohibited and may }
|
|
{ result in severe civil and criminal penalties and will be }
|
|
{ prosecuted to the maximum extent possible under the law. }
|
|
{ }
|
|
{ RESTRICTIONS }
|
|
{ }
|
|
{ THIS SOURCE CODE AND ALL RESULTING INTERMEDIATE FILES }
|
|
{ (DCU, OBJ, DLL, ETC.) ARE CONFIDENTIAL AND PROPRIETARY TRADE }
|
|
{ SECRETS OF DEVELOPER EXPRESS INC. THE REGISTERED DEVELOPER IS }
|
|
{ LICENSED TO DISTRIBUTE THE EXPRESSEDITORS AND ALL }
|
|
{ ACCOMPANYING VCL CONTROLS AS PART OF AN EXECUTABLE PROGRAM ONLY. }
|
|
{ }
|
|
{ THE SOURCE CODE CONTAINED WITHIN THIS FILE AND ALL RELATED }
|
|
{ FILES OR ANY PORTION OF ITS CONTENTS SHALL AT NO TIME BE }
|
|
{ COPIED, TRANSFERRED, SOLD, DISTRIBUTED, OR OTHERWISE MADE }
|
|
{ AVAILABLE TO OTHER INDIVIDUALS WITHOUT EXPRESS WRITTEN CONSENT }
|
|
{ AND PERMISSION FROM DEVELOPER EXPRESS INC. }
|
|
{ }
|
|
{ CONSULT THE END USER LICENSE AGREEMENT FOR INFORMATION ON }
|
|
{ ADDITIONAL RESTRICTIONS. }
|
|
{ }
|
|
{********************************************************************}
|
|
|
|
unit cxShellComboBox;
|
|
|
|
{$I cxVer.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
Windows, Messages, Classes, ComCtrls, Controls, ImgList, ShlObj, cxClasses,
|
|
cxContainer, cxDataUtils, cxDropDownEdit, cxEdit, cxGraphics, cxTextEdit,
|
|
cxShellListView, cxShellTreeView, cxShellCommon, cxShellControls;
|
|
|
|
type
|
|
TcxShellComboBoxViewOption = (scvoShowFiles, scvoShowHidden);
|
|
TcxShellComboBoxViewOptions = set of TcxShellComboBoxViewOption;
|
|
|
|
TcxPopupShellTreeViewOption = (tvoContextMenus, tvoHotTrack, tvoShowButtons,
|
|
tvoShowInfoTips, tvoShowLines, tvoShowRoot, tvoShowToolTip,
|
|
tvoRightClickSelect);
|
|
TcxPopupShellTreeViewOptions = set of TcxPopupShellTreeViewOption;
|
|
|
|
TcxShellComboBoxShowFullPath = (sfpNever, sfpAlways, sfpNotFocused);
|
|
|
|
{ TcxShellComboBoxViewInfo }
|
|
|
|
TcxShellComboBoxViewInfo = class(TcxCustomTextEditViewInfo)
|
|
public
|
|
ShellIconPosition: TPoint;
|
|
ShellSysIconIndex: Integer;
|
|
ShellSysIconOverlayIndex: Integer;
|
|
procedure Offset(DX, DY: Integer); override;
|
|
procedure Paint(ACanvas: TcxCanvas); override;
|
|
end;
|
|
|
|
{ TcxShellComboBoxViewData }
|
|
|
|
TcxCustomShellComboBoxProperties = class;
|
|
|
|
TcxShellComboBoxViewData = class(TcxCustomDropDownEditViewData)
|
|
private
|
|
function GetProperties: TcxCustomShellComboBoxProperties;
|
|
protected
|
|
function InternalEditValueToDisplayText(AEditValue: TcxEditValue): string; override;
|
|
function InternalGetEditConstantPartSize(ACanvas: TcxCanvas; AIsInplace: Boolean;
|
|
AEditSizeProperties: TcxEditSizeProperties; var MinContentSize: TSize;
|
|
AViewInfo: TcxCustomEditViewInfo): TSize; override;
|
|
public
|
|
procedure Calculate(ACanvas: TcxCanvas; const ABounds: TRect;
|
|
const P: TPoint; Button: TcxMouseButton; Shift: TShiftState;
|
|
AViewInfo: TcxCustomEditViewInfo; AIsMouseEvent: Boolean); override;
|
|
procedure EditValueToDrawValue(ACanvas: TcxCanvas;
|
|
const AEditValue: TcxEditValue; AViewInfo: TcxCustomEditViewInfo); override;
|
|
function GetClientExtent(ACanvas: TcxCanvas;
|
|
AViewInfo: TcxCustomEditViewInfo): TRect; override;
|
|
property Properties: TcxCustomShellComboBoxProperties read GetProperties;
|
|
end;
|
|
|
|
{ TcxShellComboBoxRoot }
|
|
|
|
TcxShellComboBoxRoot = class(TcxCustomShellRoot)
|
|
private
|
|
FOnChange: TNotifyEvent;
|
|
protected
|
|
procedure RootUpdated; override;
|
|
property OnChange: TNotifyEvent read FOnChange write FOnChange;
|
|
end;
|
|
|
|
{ TcxShellComboBoxLookupData }
|
|
|
|
TcxCustomShellComboBox = class;
|
|
|
|
TcxShellComboBoxLookupData = class(TcxCustomTextEditLookupData)
|
|
private
|
|
function GetEdit: TcxCustomShellComboBox;
|
|
protected
|
|
function GetItem(Index: Integer): string; override;
|
|
function GetItemCount: Integer; override;
|
|
procedure ListChanged; override;
|
|
property Edit: TcxCustomShellComboBox read GetEdit;
|
|
end;
|
|
|
|
{ TcxCustomShellComboBoxProperties }
|
|
|
|
TcxCustomShellComboBoxProperties = class(TcxCustomPopupEditProperties)
|
|
private
|
|
FFastSearch: Boolean;
|
|
FIncrementalSearch: Boolean;
|
|
FRoot: TcxShellComboBoxRoot;
|
|
FShowFullPath: TcxShellComboBoxShowFullPath;
|
|
FStoreRelativePath: Boolean;
|
|
FTreeViewOptions: TcxPopupShellTreeViewOptions;
|
|
FViewOptions: TcxShellComboBoxViewOptions;
|
|
FOnAddFolder: TcxShellAddFolderEvent;
|
|
FOnRootSettingsChanged: TNotifyEvent;
|
|
procedure DoRootSettingsChanged;
|
|
function GetDropDownSizeable: Boolean;
|
|
function GetDropDownWidth: Integer;
|
|
procedure RootChangeHandler(Sender: TObject);
|
|
procedure RootSettingsChanged(Sender: TObject);
|
|
procedure SetDropDownSizeable(Value: Boolean);
|
|
procedure SetDropDownWidth(Value: Integer);
|
|
procedure SetFastSearch(Value: Boolean);
|
|
procedure SetIncrementalSearch(Value: Boolean);
|
|
procedure SetShowFullPath(Value: TcxShellComboBoxShowFullPath);
|
|
procedure SetStoreRelativePath(Value: Boolean);
|
|
procedure SetTreeViewOptions(Value: TcxPopupShellTreeViewOptions);
|
|
procedure SetViewOptions(Value: TcxShellComboBoxViewOptions);
|
|
protected
|
|
class function GetPopupWindowClass: TcxCustomEditPopupWindowClass; override;
|
|
class function GetViewDataClass: TcxCustomEditViewDataClass; override;
|
|
procedure CheckRoot;
|
|
function EditValueToPIDL(const AEditValue: TcxEditValue): PItemIDList; virtual;
|
|
function GetShellViewOptions: TcxShellViewOptions;
|
|
procedure RootChanged; virtual;
|
|
property OnRootSettingsChanged: TNotifyEvent read FOnRootSettingsChanged
|
|
write FOnRootSettingsChanged;
|
|
public
|
|
constructor Create(AOwner: TPersistent); override;
|
|
destructor Destroy; override;
|
|
procedure Assign(Source: TPersistent); override;
|
|
function CompareDisplayValues(
|
|
const AEditValue1, AEditValue2: TcxEditValue): Boolean; override;
|
|
class function GetContainerClass: TcxContainerClass; override;
|
|
function GetDisplayText(const AEditValue: TcxEditValue;
|
|
AFullText: Boolean = False; AIsInplace: Boolean = True): WideString; override;
|
|
function GetEditValueSource(AEditFocused: Boolean): TcxDataEditValueSource; override;
|
|
class function GetLookupDataClass: TcxInterfacedPersistentClass; override;
|
|
procedure GetShellDisplayValue(const AEditValue: TcxEditValue;
|
|
AFocused: Boolean; out AText: string;
|
|
out AShellSysIconIndex, AShellSysIconOverlayIndex: Integer);
|
|
class function GetViewInfoClass: TcxContainerViewInfoClass; override;
|
|
function IsEditValueValid(var EditValue: TcxEditValue;
|
|
AEditFocused: Boolean): Boolean; override;
|
|
// !!!
|
|
property DropDownSizeable: Boolean read GetDropDownSizeable write SetDropDownSizeable default True;
|
|
property DropDownWidth: Integer read GetDropDownWidth write SetDropDownWidth
|
|
default 250;
|
|
property FastSearch: Boolean read FFastSearch write SetFastSearch default False;
|
|
property IncrementalSearch: Boolean read FIncrementalSearch
|
|
write SetIncrementalSearch default False;
|
|
property Root: TcxShellComboBoxRoot read FRoot write FRoot;
|
|
property ShowFullPath: TcxShellComboBoxShowFullPath read FShowFullPath
|
|
write SetShowFullPath default sfpNever;
|
|
property StoreRelativePath: Boolean read FStoreRelativePath write SetStoreRelativePath default True;
|
|
property TreeViewOptions: TcxPopupShellTreeViewOptions read FTreeViewOptions
|
|
write SetTreeViewOptions default [tvoContextMenus, tvoHotTrack,
|
|
tvoShowButtons, tvoShowLines, tvoShowRoot, tvoShowToolTip];
|
|
property ViewOptions: TcxShellComboBoxViewOptions read FViewOptions
|
|
write SetViewOptions default [];
|
|
property OnAddFolder: TcxShellAddFolderEvent read FOnAddFolder
|
|
write FOnAddFolder;
|
|
end;
|
|
|
|
{ TcxShellComboBoxProperties }
|
|
|
|
TcxShellComboBoxProperties = class(TcxCustomShellComboBoxProperties)
|
|
published
|
|
property Alignment;
|
|
property AssignedValues;
|
|
property AutoSelect;
|
|
property ButtonGlyph;
|
|
property ClearKey;
|
|
property DropDownSizeable;
|
|
property DropDownWidth;
|
|
property FastSearch;
|
|
property HideSelection;
|
|
property ImeMode;
|
|
property ImeName;
|
|
property IncrementalSearch;
|
|
property PopupAlignment;
|
|
property ReadOnly;
|
|
property Root;
|
|
property ShowFullPath;
|
|
property StoreRelativePath;
|
|
property TreeViewOptions;
|
|
property UseLeftAlignmentOnEditing;
|
|
property ValidateOnEnter;
|
|
property ViewOptions;
|
|
property OnAddFolder;
|
|
property OnChange;
|
|
property OnCloseUp;
|
|
property OnEditValueChanged;
|
|
property OnPopup;
|
|
end;
|
|
|
|
{ TcxPopupShellTreeView }
|
|
|
|
TcxPopupShellTreeView = class(TcxShellTreeView)
|
|
private
|
|
function GetEdit: TcxCustomShellComboBox;
|
|
protected
|
|
procedure KeyDown(var Key: Word; Shift: TShiftState); override;
|
|
procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
|
|
procedure DoSelectNode(AClosePopupReason: TcxEditCloseUpReason); virtual;
|
|
property Edit: TcxCustomShellComboBox read GetEdit;
|
|
end;
|
|
|
|
TcxPopupShellTreeViewClass = class of TcxPopupShellTreeView;
|
|
|
|
{ TcxShellComboBoxPopupWindow }
|
|
|
|
TcxShellComboBoxPopupWindow = class(TcxPopupEditPopupWindow)
|
|
private
|
|
procedure WMEnable(var Message: TMessage); message WM_ENABLE;
|
|
end;
|
|
|
|
{ TcxCustomShellComboBox }
|
|
|
|
TcxCustomShellComboBox = class(TcxCustomPopupEdit)
|
|
private
|
|
FAbsolutePIDL: PItemIDList;
|
|
FIsDependentShellControlsNotification, FNotificationFromDependentShellControls: Boolean;
|
|
FIsSelectedNodeChangeEventLocked: Boolean;
|
|
FPopupShellTreeView: TcxPopupShellTreeView;
|
|
FPopupWindowShowing: Boolean;
|
|
FShellListView: TcxCustomShellListView;
|
|
FShellTreeView: TcxCustomShellTreeView;
|
|
procedure AddFolderHandler(Sender: TObject; AFolder: TcxShellFolder;
|
|
var ACanAdd: Boolean);
|
|
function GetAbsolutePIDL: PItemIDList;
|
|
function GetActiveProperties: TcxCustomShellComboBoxProperties;
|
|
function GetPath: string;
|
|
function GetProperties: TcxCustomShellComboBoxProperties;
|
|
// function GetRelativePath: string;
|
|
function GetViewInfo: TcxShellComboBoxViewInfo;
|
|
procedure RootChangeHandler(Sender: TObject);
|
|
procedure RootSettingsChanged(Sender: TObject);
|
|
procedure SetAbsolutePIDL(Value: PItemIDList);
|
|
procedure SetPath(const Value: string);
|
|
procedure SetProperties(Value: TcxCustomShellComboBoxProperties);
|
|
procedure SetRelativePIDL(Value: PItemIDList);
|
|
// procedure SetRelativePath(const Value: string);
|
|
procedure SetShellListView(Value: TcxCustomShellListView);
|
|
procedure SetShellTreeView(Value: TcxCustomShellTreeView);
|
|
procedure DSMDoNavigate(var Message: TMessage); message DSM_DONAVIGATE;
|
|
procedure DSMSynchronizeRoot(var Message: TMessage); message DSM_SYNCHRONIZEROOT;
|
|
protected
|
|
function CanDropDown: Boolean; override;
|
|
procedure CloseUp(AReason: TcxEditCloseUpReason); override;
|
|
procedure CreatePopupWindow; override;
|
|
procedure DoInitPopup; override;
|
|
procedure DropDown; override;
|
|
procedure HandleSelectItem(Sender: TObject); override;
|
|
procedure Initialize; override;
|
|
procedure InitializePopupWindow; override;
|
|
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
|
|
procedure PopupWindowShowed(Sender: TObject); override;
|
|
procedure PopupWindowShowing(Sender: TObject); override;
|
|
procedure PropertiesChanged(Sender: TObject); override;
|
|
procedure SynchronizeDisplayValue; override;
|
|
procedure SynchronizeEditValue; override;
|
|
function CheckAbsolutePIDL(var APIDL: PItemIDList;
|
|
ACheckObjectExistence: Boolean): Boolean;
|
|
procedure CheckPopupShellTreeView;
|
|
function FindNodeAmongExpandedNodes(ANodeText: string): TTreeNode;
|
|
function GetPopupShellTreeViewClass: TcxPopupShellTreeViewClass; virtual;
|
|
procedure InternalSetAbsolutePIDL(Value: PItemIDList);
|
|
procedure InternalSynchronizeEditValue(APIDL: PItemIDList;
|
|
const ADisplayText: string = ''); virtual;
|
|
procedure InvalidateShellIconRect;
|
|
procedure SelectedNodeChangeHandler(Sender: TObject; ANode: TTreeNode); virtual;
|
|
procedure SynchronizeDependentShellControls;
|
|
procedure SynchronizePopupShellTreeView;
|
|
function TraverseAllVisibleNodes(var ANodeIndex: Integer;
|
|
ATreeNode: TTreeNode = nil): TTreeNode;
|
|
property ShellListView: TcxCustomShellListView read FShellListView write SetShellListView;
|
|
property ShellTreeView: TcxCustomShellTreeView read FShellTreeView write SetShellTreeView;
|
|
property ViewInfo: TcxShellComboBoxViewInfo read GetViewInfo;
|
|
public
|
|
destructor Destroy; override;
|
|
function CanHide: Boolean; override;
|
|
class function GetPropertiesClass: TcxCustomEditPropertiesClass; override;
|
|
property AbsolutePIDL: PItemIDList read GetAbsolutePIDL write SetAbsolutePIDL;
|
|
property AbsolutePath: string read GetPath write SetPath; // deprecated
|
|
property ActiveProperties: TcxCustomShellComboBoxProperties
|
|
read GetActiveProperties;
|
|
property Path: string read GetPath write SetPath;
|
|
property PopupShellTreeView: TcxPopupShellTreeView read FPopupShellTreeView;
|
|
property Properties: TcxCustomShellComboBoxProperties read GetProperties
|
|
write SetProperties;
|
|
property RelativePIDL: PItemIDList write SetRelativePIDL; // TODO
|
|
// property RelativePath: string read GetRelativePath write SetRelativePath;
|
|
end;
|
|
|
|
{ TcxShellComboBox }
|
|
|
|
TcxShellComboBox = class(TcxCustomShellComboBox)
|
|
private
|
|
function GetActiveProperties: TcxShellComboBoxProperties;
|
|
function GetProperties: TcxShellComboBoxProperties;
|
|
procedure SetProperties(Value: TcxShellComboBoxProperties);
|
|
public
|
|
class function GetPropertiesClass: TcxCustomEditPropertiesClass; override;
|
|
property ActiveProperties: TcxShellComboBoxProperties
|
|
read GetActiveProperties;
|
|
published
|
|
property Align;
|
|
property Anchors;
|
|
property AutoSize;
|
|
property BeepOnEnter;
|
|
property Constraints;
|
|
property DragCursor;
|
|
property DragKind;
|
|
property DragMode;
|
|
property Enabled;
|
|
property ImeMode;
|
|
property ImeName;
|
|
property ParentColor;
|
|
property ParentFont;
|
|
property ParentShowHint;
|
|
property PopupMenu;
|
|
property Properties: TcxShellComboBoxProperties read GetProperties
|
|
write SetProperties;
|
|
property ShellListView;
|
|
property ShellTreeView;
|
|
property ShowHint;
|
|
property Style;
|
|
property StyleDisabled;
|
|
property StyleFocused;
|
|
property StyleHot;
|
|
property TabOrder;
|
|
property TabStop;
|
|
property Visible;
|
|
property OnClick;
|
|
property OnContextPopup;
|
|
property OnDblClick;
|
|
property OnDragDrop;
|
|
property OnDragOver;
|
|
property OnEditing;
|
|
property OnEndDock;
|
|
property OnEndDrag;
|
|
property OnEnter;
|
|
property OnExit;
|
|
property OnKeyDown;
|
|
property OnKeyPress;
|
|
property OnKeyUp;
|
|
property OnMouseDown;
|
|
property OnMouseEnter;
|
|
property OnMouseLeave;
|
|
property OnMouseMove;
|
|
property OnMouseUp;
|
|
property OnStartDock;
|
|
property OnStartDrag;
|
|
end;
|
|
|
|
var
|
|
cxShellComboBoxImageList: TCustomImageList;
|
|
|
|
implementation
|
|
|
|
uses
|
|
{$IFDEF DELPHI6}
|
|
Variants,
|
|
{$ENDIF}
|
|
ActiveX, CommCtrl, Graphics, ShellAPI, SysUtils, cxControls, cxDBEdit,
|
|
cxEditPaintUtils, cxEditUtils, cxExtEditConsts, cxFilterControlUtils,
|
|
cxGeometry, cxVariants;
|
|
|
|
type
|
|
TcxDBTextEditDataBindingAccess = class(TcxDBTextEditDataBinding);
|
|
TcxCustomEditAccess = class(TcxCustomEdit);
|
|
TcxInnerShellListViewAccess = class(TcxInnerShellListView);
|
|
TcxInnerShellTreeViewAccess = class(TcxInnerShellTreeView);
|
|
TcxPopupEditPopupWindowAccess = class(TcxPopupEditPopupWindow);
|
|
TcxShellTreeItemProducerAccess = class(TcxShellTreeItemProducer);
|
|
|
|
const
|
|
ShellRootIDL: Word = 0;
|
|
|
|
type
|
|
{ TcxFilterShellComboBoxHelper }
|
|
|
|
TcxFilterShellComboBoxHelper = class(TcxFilterDropDownEditHelper)
|
|
public
|
|
class function GetFilterEditClass: TcxCustomEditClass; override;
|
|
end;
|
|
|
|
class function TcxFilterShellComboBoxHelper.GetFilterEditClass: TcxCustomEditClass;
|
|
begin
|
|
Result := TcxShellComboBox;
|
|
end;
|
|
|
|
procedure FreeAndNilPIDL(var APIDL: PItemIDList);
|
|
begin
|
|
if APIDL <> nil then
|
|
begin
|
|
cxMalloc.Free(APIDL);
|
|
APIDL := nil;
|
|
end;
|
|
end;
|
|
|
|
procedure GetShellSysIconIndex(APIDL: PItemIDList;
|
|
out AShellSysIconIndex, AShellSysIconOverlayIndex: Integer);
|
|
const
|
|
SHGFI_ATTR_SPECIFIED = $20000;
|
|
var
|
|
AFlags: Integer;
|
|
ASHFileInfo: TSHFileInfo;
|
|
begin
|
|
AFlags := SHGFI_PIDL or SHGFI_SYSICONINDEX or SHGFI_SMALLICON or
|
|
SHGFI_ATTR_SPECIFIED or SHGFI_ATTRIBUTES;
|
|
ASHFileInfo.dwAttributes := SFGAO_LINK or SFGAO_SHARE;
|
|
SHGetFileInfo(Pointer(APIDL), 0, ASHFileInfo, SizeOf(ASHFileInfo), AFlags);
|
|
AShellSysIconIndex := ASHFileInfo.iIcon;
|
|
if ASHFileInfo.dwAttributes and SFGAO_LINK <> 0 then
|
|
AShellSysIconOverlayIndex := cxShellShortcutItemOverlayIndex
|
|
else
|
|
if ASHFileInfo.dwAttributes and SFGAO_SHARE <> 0 then
|
|
AShellSysIconOverlayIndex := cxShellSharedItemOverlayIndex
|
|
else
|
|
AShellSysIconOverlayIndex := cxShellNormalItemOverlayIndex;
|
|
end;
|
|
|
|
procedure PrepareShellComboBoxImageList;
|
|
var
|
|
ASHFileInfo : TSHFileInfo;
|
|
begin
|
|
cxShellComboBoxImageList := TCustomImageList.Create(nil);
|
|
with cxShellComboBoxImageList do
|
|
begin
|
|
ShareImages := True;
|
|
Handle := SHGetFileInfo(@ShellRootIDL, 0, ASHFileInfo, SizeOf(ASHFileInfo),
|
|
SHGFI_PIDL or SHGFI_SYSICONINDEX or SHGFI_SMALLICON);
|
|
end;
|
|
end;
|
|
|
|
{ TcxShellComboBoxViewInfo }
|
|
|
|
procedure TcxShellComboBoxViewInfo.Offset(DX, DY: Integer);
|
|
begin
|
|
inherited Offset(DX, DY);
|
|
Inc(ShellIconPosition.X, DX);
|
|
Inc(ShellIconPosition.Y, DY);
|
|
end;
|
|
|
|
procedure TcxShellComboBoxViewInfo.Paint(ACanvas: TcxCanvas);
|
|
var
|
|
R: TRect;
|
|
begin
|
|
if (ShellSysIconIndex <> -1) and (cxShellComboBoxImageList <> nil) then
|
|
begin
|
|
R.TopLeft := ShellIconPosition;
|
|
R.Right := R.Left + cxShellComboBoxImageList.Width;
|
|
R.Bottom := R.Top + cxShellComboBoxImageList.Height;
|
|
if not Transparent then
|
|
cxEditFillRect(ACanvas.Handle, R, GetSolidBrush(BackgroundColor));
|
|
ImageList_Draw(cxShellComboBoxImageList.Handle, ShellSysIconIndex,
|
|
ACanvas.Handle, R.Left, R.Top,
|
|
ILD_TRANSPARENT or IndexToOverlayMask(ShellSysIconOverlayIndex + 1));
|
|
if not Transparent then
|
|
ACanvas.ExcludeClipRect(R);
|
|
end;
|
|
inherited Paint(ACanvas);
|
|
end;
|
|
|
|
{ TcxShellComboBoxViewData }
|
|
|
|
procedure TcxShellComboBoxViewData.Calculate(ACanvas: TcxCanvas;
|
|
const ABounds: TRect; const P: TPoint; Button: TcxMouseButton;
|
|
Shift: TShiftState; AViewInfo: TcxCustomEditViewInfo;
|
|
AIsMouseEvent: Boolean);
|
|
|
|
function GetIconPosition: TPoint;
|
|
begin
|
|
if cxShellComboBoxImageList = nil then
|
|
Result := cxNullPoint
|
|
else
|
|
with TcxShellComboBoxViewInfo(AViewInfo) do
|
|
begin
|
|
Result.X := BorderRect.Left + 1;
|
|
Result.Y := BorderRect.Top + (BorderRect.Bottom - BorderRect.Top -
|
|
cxShellComboBoxImageList.Height) div 2
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
inherited Calculate(ACanvas, ABounds, P, Button, Shift, AViewInfo, AIsMouseEvent);
|
|
TcxShellComboBoxViewInfo(AViewInfo).ShellIconPosition := GetIconPosition;
|
|
end;
|
|
|
|
procedure TcxShellComboBoxViewData.EditValueToDrawValue(ACanvas: TcxCanvas;
|
|
const AEditValue: TcxEditValue; AViewInfo: TcxCustomEditViewInfo);
|
|
begin
|
|
with TcxShellComboBoxViewInfo(AViewInfo) do
|
|
begin
|
|
Properties.GetShellDisplayValue(AEditValue, False, string(Text),
|
|
ShellSysIconIndex, ShellSysIconOverlayIndex);
|
|
DoOnGetDisplayText(string(Text));
|
|
end;
|
|
PrepareSelection(AViewInfo);
|
|
end;
|
|
|
|
function TcxShellComboBoxViewData.GetClientExtent(ACanvas: TcxCanvas;
|
|
AViewInfo: TcxCustomEditViewInfo): TRect;
|
|
begin
|
|
Result := inherited GetClientExtent(ACanvas, AViewInfo);
|
|
if not (Properties.FastSearch and (Edit = nil) or (cxShellComboBoxImageList = nil)) then
|
|
Inc(Result.Left, cxShellComboBoxImageList.Width + 4);
|
|
end;
|
|
|
|
function TcxShellComboBoxViewData.InternalGetEditConstantPartSize(ACanvas: TcxCanvas;
|
|
AIsInplace: Boolean; AEditSizeProperties: TcxEditSizeProperties;
|
|
var MinContentSize: TSize; AViewInfo: TcxCustomEditViewInfo): TSize;
|
|
begin
|
|
Result := inherited InternalGetEditConstantPartSize(ACanvas, AIsInplace,
|
|
AEditSizeProperties, MinContentSize, AViewInfo);
|
|
if IsInplace or (Edit <> nil) and TcxCustomEditAccess(Edit).AutoSize then
|
|
begin
|
|
if (cxShellComboBoxImageList <> nil) and
|
|
(MinContentSize.cy < cxShellComboBoxImageList.Height) then
|
|
MinContentSize.cy := cxShellComboBoxImageList.Height;
|
|
end;
|
|
end;
|
|
|
|
function TcxShellComboBoxViewData.InternalEditValueToDisplayText(
|
|
AEditValue: TcxEditValue): string;
|
|
var
|
|
AShellSysIconIndex, AShellSysIconOverlayIndex: Integer;
|
|
begin
|
|
Properties.GetShellDisplayValue(AEditValue, Focused, Result, AShellSysIconIndex,
|
|
AShellSysIconOverlayIndex);
|
|
end;
|
|
|
|
function TcxShellComboBoxViewData.GetProperties: TcxCustomShellComboBoxProperties;
|
|
begin
|
|
Result := TcxCustomShellComboBoxProperties(FProperties);
|
|
end;
|
|
|
|
{ TcxShellComboBoxRoot }
|
|
|
|
procedure TcxShellComboBoxRoot.RootUpdated;
|
|
begin
|
|
inherited RootUpdated;
|
|
TcxCustomShellComboBoxProperties(Owner).RootChangeHandler(Self);
|
|
if Assigned(FOnChange) then
|
|
FOnChange(Self);
|
|
end;
|
|
|
|
{ TcxShellComboBoxLookupData }
|
|
|
|
function TcxShellComboBoxLookupData.GetItem(Index: Integer): string;
|
|
begin
|
|
Result := Edit.TraverseAllVisibleNodes(Index).Text;
|
|
end;
|
|
|
|
function TcxShellComboBoxLookupData.GetItemCount: Integer;
|
|
begin
|
|
if Edit.ActiveProperties.IncrementalSearch then
|
|
begin
|
|
Result := -1;
|
|
Edit.TraverseAllVisibleNodes(Result);
|
|
end
|
|
else
|
|
Result := 0;
|
|
end;
|
|
|
|
procedure TcxShellComboBoxLookupData.ListChanged;
|
|
begin
|
|
end;
|
|
|
|
function TcxShellComboBoxLookupData.GetEdit: TcxCustomShellComboBox;
|
|
begin
|
|
Result := TcxCustomShellComboBox(GetOwner);
|
|
end;
|
|
|
|
{ TcxCustomShellComboBoxProperties }
|
|
|
|
constructor TcxCustomShellComboBoxProperties.Create(AOwner: TPersistent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FRoot := TcxShellComboBoxRoot.Create(Self, 0);
|
|
FRoot.OnSettingsChanged := RootSettingsChanged;
|
|
DropDownSizeable := True;
|
|
ImmediateDropDown := False;
|
|
PopupAutoSize := False;
|
|
TreeViewOptions := [tvoContextMenus, tvoHotTrack, tvoShowButtons,
|
|
tvoShowLines, tvoShowRoot, tvoShowToolTip];
|
|
ValidateOnEnter := True;
|
|
|
|
FStoreRelativePath := True;
|
|
end;
|
|
|
|
destructor TcxCustomShellComboBoxProperties.Destroy;
|
|
begin
|
|
FreeAndNil(FRoot);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TcxCustomShellComboBoxProperties.Assign(Source: TPersistent);
|
|
begin
|
|
if Source is TcxCustomShellComboBoxProperties then
|
|
begin
|
|
BeginUpdate;
|
|
try
|
|
inherited Assign(Source);
|
|
with Source as TcxCustomShellComboBoxProperties do
|
|
begin
|
|
Self.FastSearch := FastSearch;
|
|
Self.IncrementalSearch := IncrementalSearch;
|
|
Self.Root.Assign(Root);
|
|
Self.ShowFullPath := ShowFullPath;
|
|
Self.StoreRelativePath := StoreRelativePath;
|
|
Self.TreeViewOptions := TreeViewOptions;
|
|
Self.ViewOptions := ViewOptions;
|
|
Self.OnAddFolder := OnAddFolder;
|
|
end;
|
|
finally
|
|
EndUpdate;
|
|
end
|
|
end
|
|
else
|
|
inherited Assign(Source);
|
|
end;
|
|
|
|
function TcxCustomShellComboBoxProperties.CompareDisplayValues(
|
|
const AEditValue1, AEditValue2: TcxEditValue): Boolean;
|
|
var
|
|
AShellSysIconIndex1, AShellSysIconIndex2: Integer;
|
|
AShellSysIconOverlayIndex1, AShellSysIconOverlayIndex2: Integer;
|
|
AText1, AText2: string;
|
|
begin
|
|
GetShellDisplayValue(AEditValue1, False, AText1, AShellSysIconIndex1,
|
|
AShellSysIconOverlayIndex1);
|
|
GetShellDisplayValue(AEditValue2, False, AText2, AShellSysIconIndex2,
|
|
AShellSysIconOverlayIndex2);
|
|
Result := InternalCompareString(AText1, AText2, True) and (FastSearch or
|
|
(AShellSysIconIndex1 = AShellSysIconIndex2) and
|
|
(AShellSysIconOverlayIndex1 = AShellSysIconOverlayIndex2));
|
|
end;
|
|
|
|
class function TcxCustomShellComboBoxProperties.GetContainerClass: TcxContainerClass;
|
|
begin
|
|
Result := TcxShellComboBox;
|
|
end;
|
|
|
|
function TcxCustomShellComboBoxProperties.GetDisplayText(const AEditValue: TcxEditValue;
|
|
AFullText: Boolean = False; AIsInplace: Boolean = True): WideString;
|
|
var
|
|
AShellSysIconIndex, AShellSysIconOverlayIndex: Integer;
|
|
AText: string;
|
|
begin
|
|
GetShellDisplayValue(AEditValue, False, AText, AShellSysIconIndex,
|
|
AShellSysIconOverlayIndex);
|
|
Result := AText;
|
|
end;
|
|
|
|
function TcxCustomShellComboBoxProperties.GetEditValueSource(AEditFocused: Boolean): TcxDataEditValueSource;
|
|
begin
|
|
Result := evsValue;
|
|
end;
|
|
|
|
class function TcxCustomShellComboBoxProperties.GetLookupDataClass: TcxInterfacedPersistentClass;
|
|
begin
|
|
Result := TcxShellComboBoxLookupData;
|
|
end;
|
|
|
|
procedure TcxCustomShellComboBoxProperties.GetShellDisplayValue(
|
|
const AEditValue: TcxEditValue; AFocused: Boolean;
|
|
out AText: string; out AShellSysIconIndex, AShellSysIconOverlayIndex: Integer);
|
|
var
|
|
APath: string;
|
|
|
|
procedure GetShellObjectName;
|
|
var
|
|
APathLength: Integer;
|
|
I: Integer;
|
|
begin
|
|
APathLength := Length(APath);
|
|
for I := APathLength - 1 downto 1 do
|
|
if APath[I] = '\' then
|
|
begin
|
|
APath := Copy(APath, I + 1, APathLength - I);
|
|
Break;
|
|
end;
|
|
end;
|
|
|
|
var
|
|
AAttributes, AParsedCharCount: ULONG;
|
|
APIDL: PItemIDList;
|
|
begin
|
|
AShellSysIconIndex := -1;
|
|
if FastSearch then
|
|
begin
|
|
if VarIsNull(AEditValue) or VarIsEmpty(AEditValue) then
|
|
AText := ''
|
|
else
|
|
begin
|
|
APath := VarToStr(AEditValue);
|
|
CheckRoot;
|
|
if APath = '' then
|
|
AText := GetPIDLDisplayName(Root.Pidl)
|
|
else
|
|
case CheckShellObjectPath(APath, GetPidlName(Root.Pidl), False) of
|
|
sptVirtual:
|
|
begin
|
|
AAttributes := SFGAO_HIDDEN or SFGAO_FOLDER;
|
|
GetDesktopIShellFolder.ParseDisplayName(0, nil, StringToOleStr(APath),
|
|
AParsedCharCount, APIDL, AAttributes);
|
|
if (APIDL <> nil) and not CheckViewOptions(GetShellViewOptions, AAttributes) then
|
|
APIDL := nil;
|
|
if APIDL = nil then
|
|
AText := APath
|
|
else
|
|
begin
|
|
AText := GetPIDLDisplayName(APIDL);
|
|
DisposePidl(APIDL);
|
|
end;
|
|
end;
|
|
else
|
|
begin
|
|
GetShellObjectName;
|
|
AText := APath;
|
|
end;
|
|
end;
|
|
end;
|
|
Exit;
|
|
end;
|
|
|
|
if VarIsNull(AEditValue) or VarIsEmpty(AEditValue) then
|
|
APIDL := nil
|
|
else
|
|
APIDL := EditValueToPIDL(AEditValue);
|
|
if APIDL = nil then
|
|
AText := VarToStr(AEditValue)
|
|
else
|
|
begin
|
|
AText := GetPIDLDisplayName(APIDL, (ShowFullPath = sfpAlways) or
|
|
(ShowFullPath = sfpNotFocused) and not AFocused);
|
|
GetShellSysIconIndex(APIDL, AShellSysIconIndex, AShellSysIconOverlayIndex);
|
|
DisposePidl(APIDL);
|
|
end;
|
|
DisplayValueToDisplayText(AText);
|
|
end;
|
|
|
|
class function TcxCustomShellComboBoxProperties.GetViewInfoClass: TcxContainerViewInfoClass;
|
|
begin
|
|
Result := TcxShellComboBoxViewInfo;
|
|
end;
|
|
|
|
function TcxCustomShellComboBoxProperties.IsEditValueValid(var EditValue: TcxEditValue;
|
|
AEditFocused: Boolean): Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
class function TcxCustomShellComboBoxProperties.GetPopupWindowClass: TcxCustomEditPopupWindowClass;
|
|
begin
|
|
Result := TcxShellComboBoxPopupWindow;
|
|
end;
|
|
|
|
class function TcxCustomShellComboBoxProperties.GetViewDataClass: TcxCustomEditViewDataClass;
|
|
begin
|
|
Result := TcxShellComboBoxViewData;
|
|
end;
|
|
|
|
procedure TcxCustomShellComboBoxProperties.CheckRoot;
|
|
begin
|
|
if Root.ShellFolder = nil then
|
|
begin
|
|
BeginUpdate;
|
|
try
|
|
Root.CheckRoot;
|
|
finally
|
|
EndUpdate(False);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomShellComboBoxProperties.EditValueToPIDL(const AEditValue: TcxEditValue): PItemIDList;
|
|
begin
|
|
CheckRoot;
|
|
if VarIsNull(AEditValue) or VarIsEmpty(AEditValue) then
|
|
Result := nil
|
|
else
|
|
Result := PathToAbsolutePIDL(VarToStr(AEditValue), Root, GetShellViewOptions);
|
|
end;
|
|
|
|
function TcxCustomShellComboBoxProperties.GetShellViewOptions: TcxShellViewOptions;
|
|
begin
|
|
Result := [svoShowFolders];
|
|
if scvoShowFiles in FViewOptions then
|
|
Include(Result, svoShowFiles);
|
|
if scvoShowHidden in FViewOptions then
|
|
Include(Result, svoShowHidden);
|
|
end;
|
|
|
|
procedure TcxCustomShellComboBoxProperties.RootChanged;
|
|
begin
|
|
Changed;
|
|
end;
|
|
|
|
procedure TcxCustomShellComboBoxProperties.DoRootSettingsChanged;
|
|
begin
|
|
if Assigned(FOnRootSettingsChanged) then
|
|
FOnRootSettingsChanged(Self);
|
|
end;
|
|
|
|
function TcxCustomShellComboBoxProperties.GetDropDownSizeable: Boolean;
|
|
begin
|
|
Result := PopupSizeable;
|
|
end;
|
|
|
|
function TcxCustomShellComboBoxProperties.GetDropDownWidth: Integer;
|
|
begin
|
|
Result := PopupWidth;
|
|
end;
|
|
|
|
procedure TcxCustomShellComboBoxProperties.RootChangeHandler(Sender: TObject);
|
|
begin
|
|
RootChanged;
|
|
end;
|
|
|
|
procedure TcxCustomShellComboBoxProperties.RootSettingsChanged(Sender: TObject);
|
|
begin
|
|
DoRootSettingsChanged;
|
|
end;
|
|
|
|
procedure TcxCustomShellComboBoxProperties.SetDropDownSizeable(Value: Boolean);
|
|
begin
|
|
PopupSizeable := Value;
|
|
end;
|
|
|
|
procedure TcxCustomShellComboBoxProperties.SetDropDownWidth(Value: Integer);
|
|
begin
|
|
PopupWidth := Value;
|
|
end;
|
|
|
|
procedure TcxCustomShellComboBoxProperties.SetFastSearch(Value: Boolean);
|
|
begin
|
|
if Value <> FFastSearch then
|
|
begin
|
|
FFastSearch := Value;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomShellComboBoxProperties.SetIncrementalSearch(Value: Boolean);
|
|
begin
|
|
if Value <> FIncrementalSearch then
|
|
begin
|
|
FIncrementalSearch := Value;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomShellComboBoxProperties.SetShowFullPath(
|
|
Value: TcxShellComboBoxShowFullPath);
|
|
begin
|
|
if Value <> FShowFullPath then
|
|
begin
|
|
FShowFullPath := Value;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomShellComboBoxProperties.SetStoreRelativePath(Value: Boolean);
|
|
begin
|
|
if Value <> FStoreRelativePath then
|
|
begin
|
|
FStoreRelativePath := Value;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomShellComboBoxProperties.SetTreeViewOptions(Value: TcxPopupShellTreeViewOptions);
|
|
begin
|
|
if Value <> FTreeViewOptions then
|
|
begin
|
|
FTreeViewOptions := Value;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomShellComboBoxProperties.SetViewOptions(Value: TcxShellComboBoxViewOptions);
|
|
begin
|
|
if Value <> FViewOptions then
|
|
begin
|
|
FViewOptions := Value;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
{ TcxPopupShellTreeView }
|
|
|
|
procedure TcxPopupShellTreeView.KeyDown(var Key: Word; Shift: TShiftState);
|
|
begin
|
|
if Key = VK_TAB then
|
|
Edit.DoEditKeyDown(Key, Shift);
|
|
inherited KeyDown(Key, Shift);
|
|
case Key of
|
|
VK_ESCAPE:
|
|
begin
|
|
DoSelectNode(crCancel);
|
|
Key := 0;
|
|
end;
|
|
VK_F4:
|
|
if not (ssAlt in Shift) then
|
|
begin
|
|
DoSelectNode(crClose);
|
|
Key := 0;
|
|
end;
|
|
VK_UP, VK_DOWN:
|
|
if ssAlt in Shift then
|
|
begin
|
|
DoSelectNode(crClose);
|
|
Key := 0;
|
|
end;
|
|
VK_RETURN:
|
|
if (Shift = []) and (InnerTreeView.Selected <> nil) then
|
|
DoSelectNode(crEnter);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxPopupShellTreeView.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
|
|
var
|
|
AHitTests : THitTests;
|
|
begin
|
|
inherited MouseUp(Button, Shift, X, Y);
|
|
AHitTests := InnerTreeView.GetHitTestInfoAt(X, Y);
|
|
if ((Button = mbLeft) and not RightClickSelect) or ((Button = mbRight) and RightClickSelect) then
|
|
if ([htOnIcon, htOnItem, htOnLabel] * AHitTests <> []) and (AHitTests <> [htOnIcon, htOnItem]) then
|
|
DoSelectNode(crEnter);
|
|
end;
|
|
|
|
procedure TcxPopupShellTreeView.DoSelectNode(AClosePopupReason: TcxEditCloseUpReason);
|
|
begin
|
|
Edit.CloseUp(AClosePopupReason)
|
|
end;
|
|
|
|
function TcxPopupShellTreeView.GetEdit: TcxCustomShellComboBox;
|
|
begin
|
|
Result := TcxCustomShellComboBox(TcxPopupEditPopupWindowAccess(Parent).Edit);
|
|
end;
|
|
|
|
{ TcxShellComboBoxPopupWindow }
|
|
|
|
procedure TcxShellComboBoxPopupWindow.WMEnable(var Message: TMessage);
|
|
begin
|
|
inherited;
|
|
if not IsInternalWindowsDisabling then
|
|
if Bool(Message.WParam) then
|
|
EnableAppWindows
|
|
else
|
|
DisableAppWindows;
|
|
end;
|
|
|
|
{ TcxCustomShellComboBox }
|
|
|
|
destructor TcxCustomShellComboBox.Destroy;
|
|
begin
|
|
if FAbsolutePIDL <> nil then
|
|
begin
|
|
DisposePidl(FAbsolutePIDL);
|
|
FAbsolutePIDL := nil;
|
|
end;
|
|
|
|
if FShellListView <> nil then
|
|
with FShellListView do
|
|
if (InnerListView <> nil) and not(csDestroying in InnerListView.ComponentState) then
|
|
TcxInnerShellListViewAccess(InnerListView).ComboBoxControl := nil;
|
|
|
|
if FShellTreeView <> nil then
|
|
with FShellTreeView do
|
|
if (InnerTreeView <> nil) and not(csDestroying in InnerTreeView.ComponentState) then
|
|
TcxInnerShellTreeViewAccess(InnerTreeView).ComboBoxControl := nil;
|
|
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TcxCustomShellComboBox.CanHide: Boolean;
|
|
begin
|
|
Result := not HasPopupWindow or IsWindowEnabled(PopupWindow.Handle);
|
|
end;
|
|
|
|
class function TcxCustomShellComboBox.GetPropertiesClass: TcxCustomEditPropertiesClass;
|
|
begin
|
|
Result := TcxCustomShellComboBoxProperties;
|
|
end;
|
|
|
|
function TcxCustomShellComboBox.CanDropDown: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
procedure TcxCustomShellComboBox.CloseUp(AReason: TcxEditCloseUpReason);
|
|
begin
|
|
if not HasPopupWindow then
|
|
Exit;
|
|
if AReason in [crTab, crEnter] then
|
|
begin
|
|
ValidateEdit(True);
|
|
SelectAll;
|
|
end;
|
|
FCloseUpReason := AReason;
|
|
PopupWindow.ClosePopup;
|
|
end;
|
|
|
|
procedure TcxCustomShellComboBox.CreatePopupWindow;
|
|
begin
|
|
inherited CreatePopupWindow;
|
|
PopupWindow.ModalMode := False;
|
|
end;
|
|
|
|
procedure TcxCustomShellComboBox.DoInitPopup;
|
|
begin
|
|
inherited DoInitPopup;
|
|
ActiveProperties.PopupControl := FPopupShellTreeView;
|
|
end;
|
|
|
|
procedure TcxCustomShellComboBox.DropDown;
|
|
begin
|
|
FIsSelectedNodeChangeEventLocked := True;
|
|
inherited DropDown;
|
|
end;
|
|
|
|
procedure TcxCustomShellComboBox.HandleSelectItem(Sender: TObject);
|
|
var
|
|
ANodeIndex: Integer;
|
|
APIDL: PItemIDList;
|
|
begin
|
|
ANodeIndex := ILookupData.CurrentKey;
|
|
APIDL := FPopupShellTreeView.GetNodeAbsolutePIDL(TraverseAllVisibleNodes(ANodeIndex));
|
|
InternalSynchronizeEditValue(APIDL, '');
|
|
DisposePidl(APIDL);
|
|
SelectAll;
|
|
end;
|
|
|
|
procedure TcxCustomShellComboBox.Initialize;
|
|
begin
|
|
inherited Initialize;
|
|
ActiveProperties.Root.OnChange := RootChangeHandler;
|
|
ActiveProperties.Root.OnSettingsChanged := RootSettingsChanged;
|
|
if IsDesigning then
|
|
Exit;
|
|
FPopupShellTreeView := GetPopupShellTreeViewClass.Create(PopupWindow);
|
|
ActiveProperties.PopupControl := FPopupShellTreeView;
|
|
with FPopupShellTreeView do
|
|
begin
|
|
LookAndFeel.MasterLookAndFeel := Self.PopupControlsLookAndFeel;
|
|
ParentColor := True;
|
|
Parent := Self.PopupWindow;
|
|
Options.ShowNonFolders := False;
|
|
Style.BorderStyle := cbsNone;
|
|
Style.HotTrack := False;
|
|
Style.TransparentBorder := False;
|
|
TreeHotTrack := True;
|
|
InnerTreeView.ShowInfoTips := False;
|
|
OnAddFolder := Self.AddFolderHandler;
|
|
OnChange := Self.SelectedNodeChangeHandler;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomShellComboBox.InitializePopupWindow;
|
|
begin
|
|
inherited InitializePopupWindow;
|
|
TcxPopupEditPopupWindowAccess(PopupWindow).SysPanelStyle := ActiveProperties.PopupSizeable;
|
|
PopupShellTreeView.Color := GetBackgroundColor;
|
|
PopupWindow.Font := VisibleFont;
|
|
end;
|
|
|
|
procedure TcxCustomShellComboBox.Notification(AComponent: TComponent; Operation: TOperation);
|
|
begin
|
|
inherited Notification(AComponent, Operation);
|
|
|
|
if Operation = opRemove then
|
|
if AComponent = ShellListView then
|
|
ShellListView := nil
|
|
else
|
|
if AComponent = ShellTreeView then
|
|
ShellTreeView := nil;
|
|
end;
|
|
|
|
procedure TcxCustomShellComboBox.PopupWindowShowed(Sender: TObject);
|
|
begin
|
|
inherited PopupWindowShowed(Sender);
|
|
FPopupWindowShowing := False;
|
|
end;
|
|
|
|
procedure TcxCustomShellComboBox.PopupWindowShowing(Sender: TObject);
|
|
var
|
|
ARootNode: TTreeNode;
|
|
begin
|
|
FPopupWindowShowing := True;
|
|
try
|
|
inherited PopupWindowShowing(Sender);
|
|
SynchronizePopupShellTreeView;
|
|
ARootNode := FPopupShellTreeView.InnerTreeView.Items.GetFirstNode;
|
|
if (ARootNode <> nil) and not ARootNode.Expanded then
|
|
ARootNode.Expanded := True;
|
|
finally
|
|
FIsSelectedNodeChangeEventLocked := False;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomShellComboBox.PropertiesChanged(Sender: TObject);
|
|
begin
|
|
inherited PropertiesChanged(Sender);
|
|
ActiveProperties.PopupControl := FPopupShellTreeView;
|
|
if FPopupShellTreeView <> nil then
|
|
with FPopupShellTreeView do
|
|
begin
|
|
ImeMode := ActiveProperties.ImeMode;
|
|
ImeName := ActiveProperties.ImeName;
|
|
Options.ContextMenus := tvoContextMenus in ActiveProperties.TreeViewOptions;
|
|
Options.ShowHidden := scvoShowHidden in ActiveProperties.ViewOptions;
|
|
Options.ShowNonFolders := scvoShowFiles in ActiveProperties.ViewOptions;
|
|
Options.ShowToolTip := tvoShowToolTip in ActiveProperties.TreeViewOptions;
|
|
RightClickSelect := tvoRightClickSelect in ActiveProperties.TreeViewOptions;
|
|
ShowButtons := tvoShowButtons in ActiveProperties.TreeViewOptions;
|
|
ShowInfoTips := tvoShowInfoTips in ActiveProperties.TreeViewOptions;
|
|
ShowLines := tvoShowLines in ActiveProperties.TreeViewOptions;
|
|
ShowRoot := tvoShowRoot in ActiveProperties.TreeViewOptions;
|
|
TreeHotTrack := tvoHotTrack in ActiveProperties.TreeViewOptions
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomShellComboBox.SynchronizeDisplayValue;
|
|
var
|
|
APIDL: PItemIDList;
|
|
S: String;
|
|
begin
|
|
if DataBinding is TcxDBTextEditDataBinding then // TODO Remove cxDBEdit, IsDataSourceLive
|
|
with TcxDBTextEditDataBindingAccess(DataBinding) do
|
|
if not IsDataAvailable then
|
|
begin
|
|
ViewInfo.ShellSysIconIndex := -1;
|
|
Exit;
|
|
end;
|
|
|
|
if VarIsNull(FEditValue) or VarIsEmpty(FEditValue) then
|
|
begin
|
|
ActiveProperties.CheckRoot;
|
|
APIDL := GetPidlCopy(ActiveProperties.Root.Pidl);
|
|
end
|
|
else
|
|
APIDL := ActiveProperties.EditValueToPIDL(FEditValue);
|
|
|
|
InternalSetAbsolutePIDL(APIDL);
|
|
|
|
if APIDL = nil then
|
|
begin
|
|
S := VarToStr(FEditValue);
|
|
ViewInfo.ShellSysIconIndex := -1;
|
|
end
|
|
else
|
|
begin
|
|
S := GetPIDLDisplayName(APIDL, (ActiveProperties.ShowFullPath = sfpAlways) or
|
|
(ActiveProperties.ShowFullPath = sfpNotFocused) and not IsFocused);
|
|
GetShellSysIconIndex(APIDL, ViewInfo.ShellSysIconIndex,
|
|
ViewInfo.ShellSysIconOverlayIndex);
|
|
DisposePidl(APIDL);
|
|
end;
|
|
|
|
DataBinding.DisplayValue := S;
|
|
// SelStart := Length(S);
|
|
InvalidateShellIconRect;
|
|
end;
|
|
|
|
procedure TcxCustomShellComboBox.SynchronizeEditValue;
|
|
var
|
|
APIDL: PItemIDList;
|
|
|
|
function GetRootAbsolutePIDL: PItemIDList;
|
|
begin
|
|
Result := GetPidlCopy(ActiveProperties.Root.Pidl);
|
|
end;
|
|
|
|
function GetSelectedNodeAbsolutePIDL: PItemIDList;
|
|
begin
|
|
with PopupShellTreeView do
|
|
Result := GetNodeAbsolutePIDL(InnerTreeView.Selected);
|
|
end;
|
|
|
|
procedure InternalEditValueToPIDL;
|
|
var
|
|
ACSIDL: Integer;
|
|
ANode: TTreeNode;
|
|
AParentIFolder: IShellFolder;
|
|
AParentFolderPIDL: PItemIDList;
|
|
APath: string;
|
|
APathType: TcxShellObjectPathType;
|
|
AShellViewOptions: TcxShellViewOptions;
|
|
ATempPIDL: PItemIDList;
|
|
begin
|
|
APath := AnsiUpperCase(DisplayValue);
|
|
ActiveProperties.CheckRoot;
|
|
|
|
if APath = '' then
|
|
begin
|
|
APIDL := GetRootAbsolutePIDL;
|
|
Exit;
|
|
end;
|
|
|
|
if IsDesigning or (FPopupShellTreeView.InnerTreeView.Selected = nil) then
|
|
ATempPIDL := GetRootAbsolutePIDL
|
|
else
|
|
ATempPIDL := GetSelectedNodeAbsolutePIDL;
|
|
try
|
|
APathType := CheckShellObjectPath(APath,
|
|
AnsiUpperCase(GetPidlName(ATempPIDL)), True);
|
|
finally
|
|
DisposePidl(ATempPIDL);
|
|
end;
|
|
|
|
APIDL := nil;
|
|
AShellViewOptions := ActiveProperties.GetShellViewOptions;
|
|
repeat
|
|
case APathType of
|
|
sptAbsolutePhysical, sptUNC, sptVirtual:
|
|
APIDL := InternalParseDisplayName(GetDesktopIShellFolder, APath,
|
|
AShellViewOptions);
|
|
sptInternalAbsoluteVirtual, sptInternalRelativeVirtual:
|
|
APIDL := ShellObjectInternalVirtualPathToPIDL(APath, ActiveProperties.Root,
|
|
AShellViewOptions);
|
|
sptRelativePhysical:
|
|
begin
|
|
if IsDesigning or (FPopupShellTreeView.InnerTreeView.Selected = nil) then
|
|
begin
|
|
AParentFolderPIDL := GetRootAbsolutePIDL;
|
|
AParentIFolder := ActiveProperties.Root.ShellFolder;
|
|
end
|
|
else
|
|
begin
|
|
AParentFolderPIDL := GetSelectedNodeAbsolutePIDL;
|
|
if APath = AnsiUpperCase(FPopupShellTreeView.InnerTreeView.Selected.Text) then
|
|
begin
|
|
APIDL := AParentFolderPIDL;
|
|
Break;
|
|
end;
|
|
GetDesktopIShellFolder.BindToObject(AParentFolderPIDL, nil,
|
|
IID_IShellFolder, Pointer(AParentIFolder));
|
|
end;
|
|
if AParentIFolder <> nil then
|
|
begin
|
|
APIDL := InternalParseDisplayName(AParentIFolder, APath,
|
|
AShellViewOptions);
|
|
if APIDL <> nil then
|
|
begin
|
|
ATempPIDL := APIDL;
|
|
APIDL := ConcatenatePidls(AParentFolderPIDL, APIDL);
|
|
DisposePidl(ATempPIDL);
|
|
end;
|
|
DisposePidl(AParentFolderPIDL);
|
|
if APIDL <> nil then
|
|
Break;
|
|
end;
|
|
|
|
if not IsDesigning then
|
|
begin
|
|
ANode := FindNodeAmongExpandedNodes(APath);
|
|
if ANode <> nil then
|
|
begin
|
|
APIDL := FPopupShellTreeView.GetNodeAbsolutePIDL(ANode);
|
|
Break;
|
|
end;
|
|
end;
|
|
|
|
for ACSIDL := CSIDL_DESKTOP to CSIDL_HISTORY do
|
|
with cxShellSpecialFolderInfoTable[ACSIDL] do
|
|
if (PIDL <> nil) and (PIDLUpperCaseDisplayName = APath) and
|
|
CheckViewOptions(AShellViewOptions, Attributes) then
|
|
begin
|
|
APIDL := GetPidlCopy(PIDL);
|
|
Break;
|
|
end;
|
|
end;
|
|
end;
|
|
until True;
|
|
|
|
if (APIDL <> nil) and not IsSubPath(ActiveProperties.Root.Pidl, APIDL) then
|
|
begin
|
|
DisposePidl(APIDL);
|
|
APIDL := nil;
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
if DataBinding is TcxDBTextEditDataBinding then // TODO Remove cxDBEdit, IsDataSourceLive
|
|
with TcxDBTextEditDataBindingAccess(DataBinding) do
|
|
if not IsDataAvailable then
|
|
begin
|
|
ViewInfo.ShellSysIconIndex := -1;
|
|
Exit;
|
|
end;
|
|
InternalEditValueToPIDL;
|
|
InternalSynchronizeEditValue(APIDL, DisplayValue);
|
|
DisposePidl(APIDL);
|
|
end;
|
|
|
|
function TcxCustomShellComboBox.CheckAbsolutePIDL(var APIDL: PItemIDList;
|
|
ACheckObjectExistence: Boolean): Boolean;
|
|
begin
|
|
ActiveProperties.CheckRoot;
|
|
if APIDL = nil then
|
|
begin
|
|
Result := True;
|
|
APIDL := ActiveProperties.Root.Pidl;
|
|
end
|
|
else
|
|
begin
|
|
Result := IsSubPath(ActiveProperties.Root.Pidl, APIDL);
|
|
if Result and ACheckObjectExistence then
|
|
Result := CheckShellObjectExistence(APIDL);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomShellComboBox.CheckPopupShellTreeView;
|
|
var
|
|
ARootNode: TTreeNode;
|
|
begin
|
|
if (FPopupShellTreeView = nil) or (FPopupShellTreeView.InnerTreeView = nil) or
|
|
(FPopupShellTreeView.InnerTreeView.Items.Count = 0) then
|
|
Exit;
|
|
|
|
ARootNode := FPopupShellTreeView.InnerTreeView.Items[0];
|
|
if not ARootNode.Expanded then
|
|
ARootNode.Expanded := True;
|
|
end;
|
|
|
|
function TcxCustomShellComboBox.FindNodeAmongExpandedNodes(ANodeText: string): TTreeNode;
|
|
|
|
function InternalFindPIDLAmongExpandedNodes(ANode: TTreeNode): TTreeNode;
|
|
var
|
|
AChildNode: TTreeNode;
|
|
begin
|
|
Result := nil;
|
|
if ANode = nil then
|
|
Exit;
|
|
if ANodeText = AnsiUpperCase(ANode.Text) then
|
|
begin
|
|
Result := ANode;
|
|
Exit;
|
|
end;
|
|
if not ANode.Expanded then
|
|
Exit;
|
|
AChildNode := ANode.GetFirstChild;
|
|
while AChildNode <> nil do
|
|
begin
|
|
Result := InternalFindPIDLAmongExpandedNodes(AChildNode);
|
|
if Result <> nil then
|
|
Break;
|
|
AChildNode := ANode.GetNextChild(AChildNode);
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
ANodeText := AnsiUpperCase(ANodeText);
|
|
with FPopupShellTreeView.InnerTreeView do
|
|
if (Selected <> nil) and (ANodeText = AnsiUpperCase(Selected.Text)) then
|
|
Result := Selected
|
|
else
|
|
Result := InternalFindPIDLAmongExpandedNodes(Items.GetFirstNode);
|
|
end;
|
|
|
|
function TcxCustomShellComboBox.GetPopupShellTreeViewClass: TcxPopupShellTreeViewClass;
|
|
begin
|
|
Result := TcxPopupShellTreeView;
|
|
end;
|
|
|
|
procedure TcxCustomShellComboBox.InternalSetAbsolutePIDL(Value: PItemIDList);
|
|
begin
|
|
if not EqualPIDLs(FAbsolutePIDL, Value) then
|
|
begin
|
|
if FAbsolutePIDL <> nil then
|
|
FreeAndNilPIDL(FAbsolutePIDL);
|
|
if Value <> nil then
|
|
begin
|
|
FAbsolutePIDL := GetPidlCopy(Value);
|
|
SynchronizeDependentShellControls;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomShellComboBox.InternalSynchronizeEditValue(APIDL: PItemIDList;
|
|
const ADisplayText: string = '');
|
|
var
|
|
APIDLName: string;
|
|
|
|
function UseInternalVirtualPathFormat: Boolean;
|
|
var
|
|
AShellSysIconIndex1, AShellSysIconOverlayIndex1: Integer;
|
|
AShellSysIconIndex2, AShellSysIconOverlayIndex2: Integer;
|
|
ATempPIDL: PItemIDList;
|
|
begin
|
|
APIDLName := GetPidlName(APIDL);
|
|
Result := APIDLName = '';
|
|
if not Result then
|
|
begin
|
|
ATempPIDL := InternalParseDisplayName(GetDesktopIShellFolder, APIDLName,
|
|
ActiveProperties.GetShellViewOptions);
|
|
try
|
|
GetShellSysIconIndex(APIDL, AShellSysIconIndex1, AShellSysIconOverlayIndex1);
|
|
GetShellSysIconIndex(ATempPIDL, AShellSysIconIndex2, AShellSysIconOverlayIndex2);
|
|
Result := (AShellSysIconIndex1 <> AShellSysIconIndex2) or
|
|
(AShellSysIconOverlayIndex1 <> AShellSysIconOverlayIndex2);
|
|
finally
|
|
DisposePidl(ATempPIDL);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
var
|
|
AIsEditValueChanged: Boolean;
|
|
ANewEditValue: string;
|
|
AParentIFolder: IShellFolder;
|
|
AStrRet: TStrRet;
|
|
ATempPIDL, ATempPIDL1: PItemIDList;
|
|
I: Integer;
|
|
S1, S2: string;
|
|
begin
|
|
InternalSetAbsolutePIDL(APIDL);
|
|
|
|
if APIDL = nil then
|
|
begin
|
|
ViewInfo.ShellSysIconIndex := -1;
|
|
S1 := ADisplayText;
|
|
ANewEditValue := DisplayValue;
|
|
end
|
|
else
|
|
begin
|
|
if ActiveProperties.StoreRelativePath and EqualPIDLs(ActiveProperties.Root.Pidl, APIDL) then
|
|
begin
|
|
ANewEditValue := '';
|
|
S1 := GetPIDLDisplayName(APIDL, (ActiveProperties.ShowFullPath = sfpAlways) or
|
|
(ActiveProperties.ShowFullPath = sfpNotFocused) and not IsFocused);
|
|
end
|
|
else
|
|
if UseInternalVirtualPathFormat then
|
|
begin
|
|
ATempPIDL := APIDL;
|
|
try
|
|
if ActiveProperties.StoreRelativePath then
|
|
begin
|
|
Integer(APIDL) := Integer(APIDL) + GetPidlSize(ActiveProperties.Root.Pidl);
|
|
S2 := cxShellObjectInternalRelativeVirtualPathPrefix;
|
|
AParentIFolder := ActiveProperties.Root.ShellFolder;
|
|
end
|
|
else
|
|
begin
|
|
S2 := cxShellObjectInternalAbsoluteVirtualPathPrefix;
|
|
AParentIFolder := GetDesktopIShellFolder;
|
|
end;
|
|
for I := 1 to GetPidlItemsCount(APIDL) do
|
|
begin
|
|
ATempPIDL1 := cxMalloc.Alloc(APIDL^.mkid.cb + SizeOf(SHITEMID));
|
|
FillChar(ATempPIDL1^, APIDL^.mkid.cb + SizeOf(SHITEMID), 0);
|
|
CopyMemory(ATempPIDL1, APIDL, APIDL^.mkid.cb);
|
|
Integer(APIDL) := Integer(APIDL) + APIDL^.mkid.cb;
|
|
AParentIFolder.GetDisplayNameOf(ATempPIDL1, SHGDN_INFOLDER, AStrRet);
|
|
S1 := GetTextFromStrRet(AStrRet, ATempPIDL1);
|
|
S2 := S2 + '\' + S1;
|
|
AParentIFolder.BindToObject(ATempPIDL1, nil, IID_IShellFolder,
|
|
Pointer(AParentIFolder));
|
|
DisposePidl(ATempPIDL1);
|
|
end;
|
|
ANewEditValue := S2;
|
|
finally
|
|
APIDL := ATempPIDL;
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
if ActiveProperties.StoreRelativePath then
|
|
begin
|
|
S1 := GetPidlName(ActiveProperties.Root.Pidl);
|
|
S2 := GetPidlName(APIDL);
|
|
if Pos(S1, S2) = 1 then
|
|
begin
|
|
if S1[Length(S1)] = '\' then
|
|
S1 := Copy(S2, Length(S1) + 1, Length(S2) - Length(S1))
|
|
else
|
|
S1 := Copy(S2, Length(S1) + 2, Length(S2) - Length(S1) - 1);
|
|
if (Length(S1) >= 1) and (S1[1] = '\') then
|
|
S1 := Copy(S1, 2, Length(S1) - 1);
|
|
ANewEditValue := S1;
|
|
end
|
|
else
|
|
ANewEditValue := GetPidlName(APIDL);
|
|
end
|
|
else
|
|
ANewEditValue := APidlName;
|
|
S1 := GetPIDLDisplayName(APIDL, (ActiveProperties.ShowFullPath = sfpAlways) or
|
|
(ActiveProperties.ShowFullPath = sfpNotFocused) and not IsFocused);
|
|
end;
|
|
GetShellSysIconIndex(APIDL, ViewInfo.ShellSysIconIndex,
|
|
ViewInfo.ShellSysIconOverlayIndex);
|
|
end;
|
|
|
|
AIsEditValueChanged := (VarType(FEditValue) <> VarType(ANewEditValue)) or
|
|
not VarEqualsExact(FEditValue, ANewEditValue);
|
|
FEditValue := ANewEditValue;
|
|
|
|
DataBinding.DisplayValue := S1;
|
|
// SelStart := Length(S1);
|
|
InvalidateShellIconRect;
|
|
|
|
if AIsEditValueChanged then
|
|
DoEditValueChanged;
|
|
end;
|
|
|
|
procedure TcxCustomShellComboBox.InvalidateShellIconRect;
|
|
begin
|
|
with ViewInfo.ShellIconPosition do
|
|
InvalidateRect(Rect(X, Y, X + cxShellComboBoxImageList.Width, Y +
|
|
cxShellComboBoxImageList.Height), False);
|
|
end;
|
|
|
|
procedure TcxCustomShellComboBox.SelectedNodeChangeHandler(Sender: TObject;
|
|
ANode: TTreeNode);
|
|
var
|
|
ANodeIndex: Integer;
|
|
begin
|
|
if (not HasPopupWindow) and not FNotificationFromDependentShellControls then
|
|
Exit;
|
|
|
|
ANodeIndex := -1;
|
|
TraverseAllVisibleNodes(ANodeIndex, ANode);
|
|
TcxShellComboBoxLookupData(FLookupData).InternalSetCurrentKey(ANodeIndex);
|
|
|
|
if FIsSelectedNodeChangeEventLocked or (not FPopupWindowShowing and
|
|
not DataBinding.Modified and not DoEditing) then
|
|
Exit;
|
|
|
|
DataBinding.DisplayValue :=
|
|
GetPIDLDisplayName(FPopupShellTreeView.GetNodeAbsolutePIDL(ANode),
|
|
ActiveProperties.ShowFullPath = sfpAlways);
|
|
if FPopupWindowShowing then
|
|
ModifiedAfterEnter := False
|
|
else
|
|
if IsFocused then
|
|
ModifiedAfterEnter := True;
|
|
SelStart := Length(DataBinding.DisplayValue);
|
|
ViewInfo.ShellSysIconIndex := ANode.ImageIndex;
|
|
ViewInfo.ShellSysIconOverlayIndex := ANode.OverlayIndex;
|
|
InvalidateShellIconRect;
|
|
|
|
if ActiveProperties.ImmediatePost and CanPostEditValue and ValidateEdit(True) then
|
|
InternalPostEditValue;
|
|
end;
|
|
|
|
procedure TcxCustomShellComboBox.SynchronizeDependentShellControls;
|
|
var
|
|
ATempPIDL: PItemIDList;
|
|
begin
|
|
if FIsDependentShellControlsNotification or FNotificationFromDependentShellControls then
|
|
Exit;
|
|
FIsDependentShellControlsNotification := True;
|
|
try
|
|
if FAbsolutePIDL = nil then
|
|
Exit;
|
|
ATempPIDL := GetPidlCopy(FAbsolutePIDL);
|
|
try
|
|
if (FShellTreeView <> nil) and FShellTreeView.HandleAllocated then
|
|
SendMessage(FShellTreeView.InnerTreeView.Handle, DSM_DONAVIGATE,
|
|
Integer(ATempPIDL), 0);
|
|
|
|
if FShellListView <> nil then
|
|
FShellListView.ProcessTreeViewNavigate(ATempPIDL);
|
|
|
|
SynchronizePopupShellTreeView;
|
|
finally
|
|
DisposePidl(ATempPIDL);
|
|
end;
|
|
finally
|
|
FIsDependentShellControlsNotification := False;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomShellComboBox.SynchronizePopupShellTreeView;
|
|
begin
|
|
if FAbsolutePIDL = nil then
|
|
Exit;
|
|
|
|
if not IsDesigning and (FPopupShellTreeView <> nil) and (HasPopupWindow(* or not IsInplace*)) then
|
|
with FPopupShellTreeView do
|
|
if (Parent <> nil) and Parent.HandleAllocated and (InnerTreeView <> nil) then
|
|
begin
|
|
InnerTreeView.HandleNeeded;
|
|
SendMessage(InnerTreeView.Handle, DSM_DONAVIGATE, WPARAM(FAbsolutePIDL), 0);
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomShellComboBox.TraverseAllVisibleNodes(var ANodeIndex: Integer;
|
|
ATreeNode: TTreeNode = nil): TTreeNode;
|
|
var
|
|
ANodeCount: Integer;
|
|
|
|
function InternalTraverseAllVisibleNodes(ANode: TTreeNode): TTreeNode;
|
|
var
|
|
AChildNode: TTreeNode;
|
|
begin
|
|
Result := nil;
|
|
if ANode = nil then
|
|
Exit;
|
|
if (ANodeCount = ANodeIndex) or (ANode = ATreeNode) then
|
|
begin
|
|
Result := ANode;
|
|
Exit;
|
|
end;
|
|
Inc(ANodeCount);
|
|
if not ANode.Expanded then
|
|
Exit;
|
|
AChildNode := ANode.GetFirstChild;
|
|
while AChildNode <> nil do
|
|
begin
|
|
Result := InternalTraverseAllVisibleNodes(AChildNode);
|
|
if Result <> nil then
|
|
Break;
|
|
AChildNode := ANode.GetNextChild(AChildNode);
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
CheckPopupShellTreeView;
|
|
ANodeCount := 0;
|
|
if FPopupShellTreeView = nil then
|
|
Result := nil
|
|
else
|
|
with FPopupShellTreeView.InnerTreeView do
|
|
Result := InternalTraverseAllVisibleNodes(Items.GetFirstNode);
|
|
ANodeIndex := ANodeCount;
|
|
end;
|
|
|
|
procedure TcxCustomShellComboBox.AddFolderHandler(Sender: TObject;
|
|
AFolder: TcxShellFolder; var ACanAdd: Boolean);
|
|
|
|
procedure DoAddFolder(AProperties: TcxCustomShellComboBoxProperties);
|
|
begin
|
|
with AProperties do
|
|
if Assigned(OnAddFolder) then
|
|
OnAddFolder(Self, AFolder, ACanAdd);
|
|
end;
|
|
|
|
begin
|
|
DoAddFolder(Properties);
|
|
if ACanAdd and (RepositoryItem <> nil) then
|
|
DoAddFolder(ActiveProperties);
|
|
end;
|
|
|
|
function TcxCustomShellComboBox.GetAbsolutePIDL: PItemIDList;
|
|
begin
|
|
Result := GetPidlCopy(FAbsolutePIDL);
|
|
end;
|
|
|
|
function TcxCustomShellComboBox.GetActiveProperties: TcxCustomShellComboBoxProperties;
|
|
begin
|
|
Result := TcxCustomShellComboBoxProperties(InternalGetActiveProperties);
|
|
end;
|
|
|
|
function TcxCustomShellComboBox.GetPath: string;
|
|
begin
|
|
if FAbsolutePIDL = nil then
|
|
Result := ''
|
|
else
|
|
Result := GetPidlName(FAbsolutePIDL);
|
|
end;
|
|
|
|
function TcxCustomShellComboBox.GetProperties: TcxCustomShellComboBoxProperties;
|
|
begin
|
|
Result := TcxCustomShellComboBoxProperties(FProperties);
|
|
end;
|
|
|
|
(*function TcxCustomShellComboBox.GetRelativePath: string;
|
|
begin
|
|
end;*)
|
|
|
|
function TcxCustomShellComboBox.GetViewInfo: TcxShellComboBoxViewInfo;
|
|
begin
|
|
Result := TcxShellComboBoxViewInfo(FViewInfo);
|
|
end;
|
|
|
|
procedure TcxCustomShellComboBox.RootChangeHandler(Sender: TObject);
|
|
begin
|
|
if not IsDesigning then
|
|
FPopupShellTreeView.Root.Assign(ActiveProperties.Root);
|
|
if not ActiveProperties.ChangedLocked and not ModifiedAfterEnter then
|
|
SynchronizeDisplayValue;
|
|
end;
|
|
|
|
procedure TcxCustomShellComboBox.RootSettingsChanged(Sender: TObject);
|
|
begin
|
|
if IsLoading then
|
|
Exit;
|
|
if (ShellListView <> nil) and ShellListView.HandleAllocated then
|
|
SendMessage(ShellListView.InnerListView.Handle, DSM_SYNCHRONIZEROOT,
|
|
Integer(ActiveProperties.Root), 0);
|
|
if (ShellTreeView <> nil) and ShellTreeView.HandleAllocated then
|
|
SendMessage(ShellTreeView.InnerTreeView.Handle, DSM_SYNCHRONIZEROOT,
|
|
Integer(ActiveProperties.Root), 0);
|
|
end;
|
|
|
|
procedure TcxCustomShellComboBox.SetAbsolutePIDL(Value: PItemIDList);
|
|
begin
|
|
if not CheckAbsolutePIDL(Value, True) then
|
|
Exit;
|
|
InternalSynchronizeEditValue(Value);
|
|
end;
|
|
|
|
procedure TcxCustomShellComboBox.SetPath(const Value: string);
|
|
begin
|
|
InternalEditValue := Value;
|
|
end;
|
|
|
|
procedure TcxCustomShellComboBox.SetProperties(Value: TcxCustomShellComboBoxProperties);
|
|
begin
|
|
FProperties.Assign(Value);
|
|
end;
|
|
|
|
procedure TcxCustomShellComboBox.SetRelativePIDL(Value: PItemIDList);
|
|
var
|
|
ATempPIDL: PItemIDList;
|
|
begin
|
|
ActiveProperties.CheckRoot;
|
|
if Value = nil then
|
|
InternalSynchronizeEditValue(ActiveProperties.Root.Pidl)
|
|
else
|
|
begin
|
|
ATempPIDL := ConcatenatePidls(ActiveProperties.Root.Pidl, Value);
|
|
try
|
|
if CheckShellObjectExistence(ATempPIDL) then
|
|
InternalSynchronizeEditValue(ATempPIDL);
|
|
finally
|
|
DisposePidl(ATempPIDL);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
(*procedure TcxCustomShellComboBox.SetRelativePath(const Value: string);
|
|
begin
|
|
end;*)
|
|
|
|
procedure TcxCustomShellComboBox.SetShellListView(Value: TcxCustomShellListView);
|
|
begin
|
|
if Value = FShellListView then
|
|
Exit;
|
|
if FShellListView <> nil then
|
|
begin
|
|
if (FShellListView.InnerListView <> nil) and not(csDestroying in FShellListView.InnerListView.ComponentState) then
|
|
TcxInnerShellListViewAccess(FShellListView.InnerListView).ComboBoxControl := nil;
|
|
{$IFDEF DELPHI5}
|
|
FShellListView.RemoveFreeNotification(Self);
|
|
{$ENDIF}
|
|
end;
|
|
FShellListView := Value;
|
|
if FShellListView <> nil then
|
|
begin
|
|
FShellListView.FreeNotification(Self);
|
|
TcxInnerShellListViewAccess(FShellListView.InnerListView).ComboBoxControl := Self;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomShellComboBox.SetShellTreeView(Value: TcxCustomShellTreeView);
|
|
begin
|
|
if Value = FShellTreeView then
|
|
Exit;
|
|
if FShellTreeView <> nil then
|
|
begin
|
|
if (FShellTreeView.InnerTreeView <> nil) and not(csDestroying in FShellTreeView.InnerTreeView.ComponentState) then
|
|
TcxInnerShellTreeViewAccess(FShellTreeView.InnerTreeView).ComboBoxControl := nil;
|
|
{$IFDEF DELPHI5}
|
|
FShellTreeView.RemoveFreeNotification(Self);
|
|
{$ENDIF}
|
|
end;
|
|
FShellTreeView := Value;
|
|
if FShellTreeView <> nil then
|
|
begin
|
|
FShellTreeView.FreeNotification(Self);
|
|
TcxInnerShellTreeViewAccess(FShellTreeView.InnerTreeView).ComboBoxControl := Self;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomShellComboBox.DSMDoNavigate(var Message: TMessage);
|
|
var
|
|
APIDL: PItemIDList;
|
|
begin
|
|
if FIsDependentShellControlsNotification or FNotificationFromDependentShellControls then
|
|
Exit;
|
|
FNotificationFromDependentShellControls := True;
|
|
try
|
|
if FShellTreeView <> nil then
|
|
APIDL := FShellTreeView.AbsolutePIDL
|
|
else if FShellListView <> nil then
|
|
APIDL := FShellListView.AbsolutePIDL
|
|
else
|
|
APIDL := PItemIDList(Message.WParam);
|
|
if not CheckAbsolutePIDL(APIDL, False) then
|
|
Exit;
|
|
if not IsDesigning and (FPopupShellTreeView <> nil) then
|
|
with FPopupShellTreeView do
|
|
if (Parent <> nil) and Parent.HandleAllocated and (InnerTreeView <> nil) then
|
|
begin
|
|
InnerTreeView.HandleNeeded;
|
|
SendMessage(InnerTreeView.Handle, DSM_DONAVIGATE, WPARAM(APIDL), 0);
|
|
SynchronizeEditValue;
|
|
Exit;
|
|
end;
|
|
|
|
InternalSynchronizeEditValue(APIDL);
|
|
finally
|
|
FNotificationFromDependentShellControls := False;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomShellComboBox.DSMSynchronizeRoot(var Message: TMessage);
|
|
begin
|
|
if not IsLoading then
|
|
ActiveProperties.Root.Update(TcxCustomShellRoot(Message.WParam));
|
|
end;
|
|
|
|
{ TcxShellComboBox }
|
|
|
|
class function TcxShellComboBox.GetPropertiesClass: TcxCustomEditPropertiesClass;
|
|
begin
|
|
Result := TcxShellComboBoxProperties;
|
|
end;
|
|
|
|
function TcxShellComboBox.GetActiveProperties: TcxShellComboBoxProperties;
|
|
begin
|
|
Result := TcxShellComboBoxProperties(InternalGetActiveProperties);
|
|
end;
|
|
|
|
function TcxShellComboBox.GetProperties: TcxShellComboBoxProperties;
|
|
begin
|
|
Result := TcxShellComboBoxProperties(FProperties);
|
|
end;
|
|
|
|
procedure TcxShellComboBox.SetProperties(Value: TcxShellComboBoxProperties);
|
|
begin
|
|
FProperties.Assign(Value);
|
|
end;
|
|
|
|
initialization
|
|
GetRegisteredEditProperties.Register(TcxShellComboBoxProperties, scxSEditRepositoryShellComboBoxItem);
|
|
FilterEditsController.Register(TcxShellComboBoxProperties, TcxFilterShellComboBoxHelper);
|
|
PrepareShellComboBoxImageList;
|
|
|
|
finalization
|
|
FreeAndNil(cxShellComboBoxImageList);
|
|
FilterEditsController.Unregister(TcxShellComboBoxProperties, TcxFilterShellComboBoxHelper);
|
|
GetRegisteredEditProperties.Unregister(TcxShellComboBoxProperties);
|
|
|
|
end.
|