git-svn-id: https://svn.code.sf.net/p/kolmck/code@119 91bb2d04-0c0c-4d2d-88a5-bbb6f4c1fa07
2650 lines
76 KiB
ObjectPascal
2650 lines
76 KiB
ObjectPascal
{This version is compatible with KOL 3.00+ -- VK}
|
|
|
|
unit ActiveKOL;
|
|
|
|
interface
|
|
|
|
uses
|
|
Windows, Messages, KOL, ActiveX, KOLComObj, err;
|
|
|
|
{$I KOLDEF.INC}
|
|
{$IFDEF _D6orHigher}
|
|
//{$WARN SYMBOL_DEPRECATED OFF}
|
|
{$WARN SYMBOL_PLATFORM OFF}
|
|
{$IFDEF _D7orHigher}
|
|
{$WARN UNSAFE_TYPE OFF}
|
|
{$WARN UNSAFE_CAST OFF}
|
|
{$WARN UNSAFE_CODE OFF}
|
|
{$ENDIF}
|
|
{$ENDIF}
|
|
|
|
{$IFNDEF _D5orHigher}
|
|
const
|
|
sNoRunningObject = 'Unable to retrieve a pointer to a running object registered with OLE for %s/%s';
|
|
{$ENDIF}
|
|
|
|
type
|
|
POleCtl = ^TOleCtl;
|
|
|
|
TEventDispatch = class(TObject, IUnknown, IDispatch)
|
|
private
|
|
FControl: POleCtl;
|
|
protected
|
|
{ IUnknown }
|
|
function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
|
|
function _AddRef: Integer; stdcall;
|
|
function _Release: Integer; stdcall;
|
|
{ IDispatch }
|
|
function GetTypeInfoCount(out Count: Integer): HResult; stdcall;
|
|
function GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult; stdcall;
|
|
function GetIDsOfNames(const IID: TGUID; Names: Pointer;
|
|
NameCount, LocaleID: Integer; DispIDs: Pointer): HResult; stdcall;
|
|
function Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer;
|
|
Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult; stdcall;
|
|
property Control: POleCtl read FControl;
|
|
public
|
|
constructor Create(Control: POleCtl);
|
|
end;
|
|
|
|
{$IFNDEF _D5orHigher}
|
|
TOleEnum = type Integer;
|
|
//{$NODEFINE TOleEnum}
|
|
{$ENDIF}
|
|
|
|
TGetStrProc = procedure(const S: string) of object;
|
|
|
|
TEnumValue = record
|
|
Value: Longint;
|
|
Ident: string;
|
|
end;
|
|
|
|
PEnumValueList = ^TEnumValueList;
|
|
TEnumValueList = array[0..32767] of TEnumValue;
|
|
|
|
PEnumPropDesc = ^TEnumPropDesc;
|
|
TEnumPropDesc = object(TObj)
|
|
private
|
|
FDispID: Integer;
|
|
FValueCount: Integer;
|
|
FValues: PEnumValueList;
|
|
public
|
|
constructor Create(DispID, ValueCount: Integer;
|
|
const TypeInfo: ITypeInfo);
|
|
destructor Destroy; virtual;
|
|
procedure GetStrings(Proc: TGetStrProc);
|
|
function StringToValue(const S: string): Integer;
|
|
function ValueToString(V: Integer): string;
|
|
end;
|
|
|
|
PControlData = ^TControlData;
|
|
TControlData = record
|
|
ClassID: TGUID;
|
|
EventIID: TGUID;
|
|
EventCount: Longint;
|
|
EventDispIDs: Pointer;
|
|
LicenseKey: Pointer;
|
|
Flags: DWORD;
|
|
Version: Integer;
|
|
FontCount: Integer;
|
|
FontIDs: PDispIDList;
|
|
PictureCount: Integer;
|
|
PictureIDs: PDispIDList;
|
|
Reserved: Integer;
|
|
InstanceCount: Integer;
|
|
EnumPropDescs: PList;
|
|
end;
|
|
|
|
PControlData2 = ^TControlData2;
|
|
TControlData2 = record
|
|
ClassID: TGUID;
|
|
EventIID: TGUID;
|
|
EventCount: Longint;
|
|
EventDispIDs: Pointer;
|
|
LicenseKey: Pointer;
|
|
Flags: DWORD;
|
|
Version: Integer;
|
|
FontCount: Integer;
|
|
FontIDs: PDispIDList;
|
|
PictureCount: Integer;
|
|
PictureIDs: PDispIDList;
|
|
Reserved: Integer;
|
|
InstanceCount: Integer;
|
|
EnumPropDescs: PList;
|
|
FirstEventOfs: Cardinal;
|
|
end;
|
|
|
|
TOleCtlIntfClass = class of TOleCtlIntf;
|
|
TOleCtlIntf = class( TObject, IUnknown, IOleClientSite,
|
|
IOleControlSite, IOleInPlaceSite, IOleInPlaceFrame, IDispatch,
|
|
IPropertyNotifySink, ISimpleFrameSite)
|
|
private
|
|
FRefCount: Integer;
|
|
fOleCtl: POleCtl;
|
|
procedure GetEventMethod(DispID: TDispID; var Method: TMethod);
|
|
protected
|
|
{ IUnknown }
|
|
function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall; //override;
|
|
function _AddRef: Integer; stdcall;
|
|
function _Release: Integer; stdcall;
|
|
{ IOleClientSite }
|
|
function SaveObject: HResult; stdcall;
|
|
function GetMoniker(dwAssign: Longint; dwWhichMoniker: Longint;
|
|
out mk: IMoniker): HResult; stdcall;
|
|
function GetContainer(out container: IOleContainer): HResult; stdcall;
|
|
function ShowObject: HResult; stdcall;
|
|
function OnShowWindow(fShow: BOOL): HResult; stdcall;
|
|
function RequestNewObjectLayout: HResult; stdcall;
|
|
{ IOleControlSite }
|
|
function OnControlInfoChanged: HResult; stdcall;
|
|
function LockInPlaceActive(fLock: BOOL): HResult; stdcall;
|
|
function GetExtendedControl(out disp: IDispatch): HResult; stdcall;
|
|
function TransformCoords(var ptlHimetric: TPoint; var ptfContainer: TPointF;
|
|
flags: Longint): HResult; stdcall;
|
|
function IOleControlSite.TranslateAccelerator = OleControlSite_TranslateAccelerator;
|
|
function OleControlSite_TranslateAccelerator(msg: PMsg;
|
|
grfModifiers: Longint): HResult; stdcall;
|
|
function OnFocus(fGotFocus: BOOL): HResult; stdcall;
|
|
function ShowPropertyFrame: HResult; stdcall;
|
|
{ IOleWindow }
|
|
function ContextSensitiveHelp(fEnterMode: BOOL): HResult; stdcall;
|
|
{ IOleInPlaceSite }
|
|
function IOleInPlaceSite.GetWindow = OleInPlaceSite_GetWindow;
|
|
function OleInPlaceSite_GetWindow(out wnd: HWnd): HResult; stdcall;
|
|
function CanInPlaceActivate: HResult; stdcall;
|
|
function OnInPlaceActivate: HResult; stdcall;
|
|
function OnUIActivate: HResult; stdcall;
|
|
function GetWindowContext(out frame: IOleInPlaceFrame;
|
|
out doc: IOleInPlaceUIWindow; out rcPosRect: TRect;
|
|
out rcClipRect: TRect; out frameInfo: TOleInPlaceFrameInfo): HResult;
|
|
stdcall;
|
|
function Scroll(scrollExtent: TPoint): HResult; stdcall;
|
|
function OnUIDeactivate(fUndoable: BOOL): HResult; stdcall;
|
|
function OnInPlaceDeactivate: HResult; stdcall;
|
|
function DiscardUndoState: HResult; stdcall;
|
|
function DeactivateAndUndo: HResult; stdcall;
|
|
function OnPosRectChange(const rcPosRect: TRect): HResult; stdcall;
|
|
{ IOleInPlaceUIWindow }
|
|
function GetBorder(out rectBorder: TRect): HResult; stdcall;
|
|
function RequestBorderSpace(const borderwidths: TRect): HResult; stdcall;
|
|
function SetBorderSpace(pborderwidths: PRect): HResult; stdcall;
|
|
function SetActiveObject(const activeObject: IOleInPlaceActiveObject;
|
|
pszObjName: POleStr): HResult; stdcall;
|
|
{ IOleInPlaceFrame }
|
|
function IOleInPlaceFrame.GetWindow = OleInPlaceFrame_GetWindow;
|
|
function OleInPlaceFrame_GetWindow(out wnd: HWnd): HResult; stdcall;
|
|
function InsertMenus(hmenuShared: HMenu;
|
|
var menuWidths: TOleMenuGroupWidths): HResult; stdcall;
|
|
function SetMenu(hmenuShared: HMenu; holemenu: HMenu;
|
|
hwndActiveObject: HWnd): HResult; stdcall;
|
|
function RemoveMenus(hmenuShared: HMenu): HResult; stdcall;
|
|
function SetStatusText(pszStatusText: POleStr): HResult; stdcall;
|
|
function EnableModeless(fEnable: BOOL): HResult; stdcall;
|
|
function IOleInPlaceFrame.TranslateAccelerator = OleInPlaceFrame_TranslateAccelerator;
|
|
function OleInPlaceFrame_TranslateAccelerator(var msg: Windows.TMsg;
|
|
wID: Word): HResult; stdcall;
|
|
{ IDispatch }
|
|
function GetTypeInfoCount(out Count: Integer): HResult; stdcall;
|
|
function GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult; stdcall;
|
|
function GetIDsOfNames(const IID: TGUID; Names: Pointer;
|
|
NameCount, LocaleID: Integer; DispIDs: Pointer): HResult; stdcall;
|
|
function Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer;
|
|
Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult; stdcall;
|
|
{ ISimpleFrameSite }
|
|
function PreMessageFilter(wnd: HWnd; msg, wp, lp: Integer;
|
|
out res: Integer; out Cookie: Longint): HResult; stdcall;
|
|
function PostMessageFilter(wnd: HWnd; msg, wp, lp: Integer;
|
|
out res: Integer; Cookie: Longint): HResult; stdcall;
|
|
{ IPropertyNotifySink }
|
|
function OnChanged(dispid: TDispID): HResult; virtual; stdcall;
|
|
function OnRequestEdit(dispid: TDispID): HResult; virtual; stdcall;
|
|
public
|
|
property OleCtl: POleCtl read fOleCtl;
|
|
constructor Create; virtual;
|
|
end;
|
|
|
|
|
|
TOnGetIntfClass = function(): TOleCtlIntfClass of object;
|
|
|
|
|
|
TOleCtl = object( TControl )
|
|
private
|
|
FOnGetIntfClass: TOnGetIntfClass;
|
|
function GetOleObject: Variant;
|
|
procedure CreateInstance;
|
|
function GetOnLeave: TOnEvent;
|
|
procedure SetOnLeave(const Value: TOnEvent);
|
|
procedure HookControlWndProc;
|
|
procedure SetUIActive(Active: Boolean);
|
|
procedure CreateControl;
|
|
procedure DestroyStorage;
|
|
procedure DestroyControl;
|
|
procedure StandardEvent(DispID: TDispID; var Params: TDispParams);
|
|
//procedure SetMouseDblClk(const Value: TOnMouse);
|
|
procedure SetOnChar(const Value: TOnChar);
|
|
protected
|
|
//{$IFDEF DELPHI_CODECOMPLETION_BUG}
|
|
fNotAvailable: Boolean;
|
|
//{$ENDIF}
|
|
{$IFNDEF USE_NAMES}
|
|
fName: String;
|
|
{$ENDIF}
|
|
FControlData: PControlData;
|
|
FOleObject: IOleObject;
|
|
FMiscStatus: Longint;
|
|
FFonts: PList;
|
|
FPictures: PList;
|
|
FEventDispatch: TEventDispatch;
|
|
fOleCtlIntf: TOleCtlIntf;
|
|
FPersistStream: IPersistStreamInit;
|
|
FOleInPlaceObject: IOleInPlaceObject;
|
|
FOleInPlaceActiveObject: IOleInPlaceActiveObject;
|
|
FOleControl: IOleControl;
|
|
FUpdatingColor: Boolean;
|
|
FUpdatingFont: Boolean;
|
|
FUpdatingEnabled: Boolean;
|
|
FObjectData: HGlobal;
|
|
FControlDispatch: IDispatch;
|
|
FPropBrowsing: IPerPropertyBrowsing;
|
|
FPropConnection: Longint;
|
|
FEventsConnection: Longint;
|
|
fCreatingWnd: Boolean;
|
|
procedure Init; virtual;
|
|
procedure InitControlData; virtual;
|
|
procedure InitControlInterface(const Obj: IUnknown); virtual;
|
|
property ControlData: PControlData read FControlData write FControlData;
|
|
function GetMainMenu: HMenu;
|
|
procedure InvokeEvent(DispID: TDispID; var Params: TDispParams);
|
|
procedure D2InvokeEvent(DispID: TDispID; var Params: TDispParams);
|
|
procedure DoHandleException;
|
|
procedure CreateEnumPropDescs;
|
|
procedure DestroyEnumPropDescs;
|
|
|
|
property OnGetIntfClass: TOnGetIntfClass read FOnGetIntfClass write FOnGetIntfClass;
|
|
public
|
|
function GetByteProp(Index: Integer): Byte;
|
|
function GetColorProp(Index: Integer): TColor;
|
|
function GetTColorProp(Index: Integer): TColor;
|
|
function GetCompProp(Index: Integer): Comp;
|
|
function GetCurrencyProp(Index: Integer): Currency;
|
|
function GetDoubleProp(Index: Integer): Double;
|
|
function GetIDispatchProp(Index: Integer): IDispatch;
|
|
function GetIntegerProp(Index: Integer): Integer;
|
|
function GetIUnknownProp(Index: Integer): IUnknown;
|
|
function GetWordBoolProp(Index: Integer): WordBool;
|
|
function GetTDateTimeProp(Index: Integer): TDateTime;
|
|
function GetTFontProp(Index: Integer): PGraphicTool;
|
|
function GetOleBoolProp(Index: Integer): TOleBool;
|
|
function GetOleDateProp(Index: Integer): TOleDate;
|
|
function GetOleEnumProp(Index: Integer): TOleEnum;
|
|
function GetTOleEnumProp(Index: Integer): TOleEnum;
|
|
function GetOleVariantProp(Index: Integer): OleVariant;
|
|
//function GetTPictureProp(Index: Integer): TPicture;
|
|
procedure GetProperty(Index: Integer; var Value: TVarData);
|
|
function GetShortIntProp(Index: Integer): ShortInt;
|
|
function GetSingleProp(Index: Integer): Single;
|
|
function GetSmallintProp(Index: Integer): Smallint;
|
|
function GetStringProp(Index: Integer): string;
|
|
function GetVariantProp(Index: Integer): Variant;
|
|
function GetWideStringProp(Index: Integer): WideString;
|
|
function GetWordProp(Index: Integer): Word;
|
|
procedure SetByteProp(Index: Integer; Value: Byte);
|
|
procedure SetColorProp(Index: Integer; Value: TColor);
|
|
procedure SetTColorProp(Index: Integer; Value: TColor);
|
|
procedure SetCompProp(Index: Integer; const Value: Comp);
|
|
procedure SetCurrencyProp(Index: Integer; const Value: Currency);
|
|
procedure SetDoubleProp(Index: Integer; const Value: Double);
|
|
procedure SetIDispatchProp(Index: Integer; const Value: IDispatch);
|
|
procedure SetIntegerProp(Index: Integer; Value: Integer);
|
|
procedure SetIUnknownProp(Index: Integer; const Value: IUnknown);
|
|
procedure SetName(const Value: String); virtual;
|
|
procedure SetWordBoolProp(Index: Integer; Value: WordBool);
|
|
procedure SetTDateTimeProp(Index: Integer; const Value: TDateTime);
|
|
procedure SetTFontProp(Index: Integer; Value:PGraphicTool);
|
|
procedure SetOleBoolProp(Index: Integer; Value: TOleBool);
|
|
procedure SetOleDateProp(Index: Integer; const Value: TOleDate);
|
|
procedure SetOleEnumProp(Index: Integer; Value: TOleEnum);
|
|
procedure SetTOleEnumProp(Index: Integer; Value: TOleEnum);
|
|
procedure SetOleVariantProp(Index: Integer; const Value: OleVariant);
|
|
procedure SetParent(AParent: PControl); virtual;
|
|
//procedure SetTPictureProp(Index: Integer; Value: TPicture);
|
|
procedure SetProperty(Index: Integer; const Value: TVarData);
|
|
procedure SetShortIntProp(Index: Integer; Value: Shortint);
|
|
procedure SetSingleProp(Index: Integer; const Value: Single);
|
|
procedure SetSmallintProp(Index: Integer; Value: Smallint);
|
|
procedure SetStringProp(Index: Integer; const Value: string);
|
|
procedure SetVariantProp(Index: Integer; const Value: Variant);
|
|
procedure SetWideStringProp(Index: Integer; const Value: WideString);
|
|
procedure SetWordProp(Index: Integer; Value: Word);
|
|
|
|
function GetEnumPropDesc(DispID: Integer): PEnumPropDesc;
|
|
|
|
property DragCursor: Boolean read fNotAvailable;
|
|
property DragMode : Boolean read fNotAvailable;
|
|
property ParentShowHint: Boolean read fNotAvailable;
|
|
property PopupMenu: Boolean read fNotAvailable;
|
|
property ShowHint: Boolean read fNotAvailable;
|
|
property OnDragDrop: Boolean read fNotAvailable;
|
|
property OnDragOver: Boolean read fNotAvailable;
|
|
property OnEndDrag: Boolean read fNotAvailable;
|
|
property OnStartDrag: Boolean read fNotAvailable;
|
|
|
|
property OnExit: TOnEvent read GetOnLeave write SetOnLeave;
|
|
property OleObject: Variant read GetOleObject;
|
|
|
|
property Name: String read fName write fName;
|
|
function CreateWindow: Boolean; virtual;
|
|
procedure DblClk;
|
|
procedure KeyDown(var Key: Longint; AShift: DWORD);
|
|
procedure KeyUp(var Key: Longint; AShift: DWORD);
|
|
procedure KeyPress(var Key: KOLChar);
|
|
procedure MouseDown(Button: TMouseButton; AShift: DWORD;
|
|
X, Y: Integer);
|
|
procedure MouseMove(AShift: DWORD; X, Y: Integer);
|
|
procedure MouseUp(Button: TMouseButton; AShift: DWORD;
|
|
X, Y: Integer);
|
|
|
|
property OnKeyPress: TOnChar
|
|
read {$IFDEF EVENTS_DYNAMIC} Get_OnChar {$ELSE} EV.fOnChar {$ENDIF}
|
|
write SetOnChar;
|
|
property OnDblClick: TOnMouse index idx_fOnMouseDblClk
|
|
read {$IFDEF EVENTS_DYNAMIC} Get_OnMouseEvent {$ELSE} EV.fOnMouseDblClk {$ENDIF}
|
|
write SetOnMouseEvent; // SetMouseDblClk;
|
|
|
|
destructor Destroy; virtual;
|
|
|
|
end;
|
|
|
|
{$IFNDEF _D2orD3}
|
|
type
|
|
TVariantArray = Array of OleVariant;
|
|
TOleServer = class;
|
|
TConnectKind = (ckRunningOrNew, // Attach to a running or create a new instance of the server
|
|
ckNewInstance, // Create a new instance of the server
|
|
ckRunningInstance, // Attach to a running instance of the server
|
|
ckRemote, // Bind to a remote instance of the server
|
|
ckAttachToInterface); // Don't bind to server, user will provide interface via 'CpnnectTo'
|
|
|
|
TServerEventDispatch = class(TObject, IUnknown, IDispatch)
|
|
private
|
|
FServer: TOleServer;
|
|
InternalRefCount : Integer;
|
|
protected
|
|
{ IUnknown }
|
|
function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
|
|
function _AddRef: Integer; stdcall;
|
|
function _Release: Integer; stdcall;
|
|
{ IDispatch }
|
|
function GetTypeInfoCount(out Count: Integer): HResult; stdcall;
|
|
function GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult; stdcall;
|
|
function GetIDsOfNames(const IID: TGUID; Names: Pointer;
|
|
NameCount, LocaleID: Integer; DispIDs: Pointer): HResult; stdcall;
|
|
function Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer;
|
|
Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult; stdcall;
|
|
property Server: TOleServer read FServer;
|
|
function ServerDisconnect :Boolean;
|
|
public
|
|
constructor Create(Server: TOleServer);
|
|
end;
|
|
|
|
PServerData = ^TServerData;
|
|
TServerData = record
|
|
ClassID: TGUID; // CLSID of CoClass
|
|
IntfIID: TGUID; // IID of default interface
|
|
EventIID: TGUID; // IID of default source interface
|
|
LicenseKey: Pointer; // Pointer to license string (not implemented)
|
|
Version: Integer; // Version of this structure
|
|
InstanceCount: Integer; // Instance of the Server running
|
|
end;
|
|
|
|
TOleServer = class(TObject, IUnknown)
|
|
private
|
|
FServerData: PServerData;
|
|
FRefCount: Longint;
|
|
FEventDispatch: TServerEventDispatch;
|
|
FEventsConnection: Longint;
|
|
FAutoConnect: Boolean;
|
|
FRemoteMachineName: string;
|
|
FConnectKind: TConnectKind;
|
|
|
|
protected
|
|
{ IUnknown }
|
|
function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall; //override;
|
|
function _AddRef: Integer; stdcall;
|
|
function _Release: Integer; stdcall;
|
|
|
|
procedure Loaded; //override;
|
|
procedure InitServerData; virtual; abstract;
|
|
|
|
function GetServer: IUnknown; virtual;
|
|
|
|
procedure ConnectEvents(const Obj: IUnknown);
|
|
procedure DisconnectEvents(const Obj: Iunknown);
|
|
procedure InvokeEvent(DispID: TDispID; var Params: TVariantArray); virtual;
|
|
|
|
function GetConnectKind: TConnectKind;
|
|
procedure SetConnectKind(ck: TConnectKind);
|
|
|
|
function GetAutoConnect: Boolean;
|
|
procedure SetAutoConnect(flag: Boolean);
|
|
|
|
property ServerData: PServerData read FServerData write FServerData;
|
|
property EventDispatch: TServerEventDispatch read FEventDispatch write FEventDispatch;
|
|
|
|
public
|
|
constructor Create; //(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
|
|
// NOTE: If derived class is generated by TLIBIMP or ImportTypeLibraryCodeGenerator,
|
|
// the derived class will also expose a 'ConnectTo(interface)' function.
|
|
// You must invoke that method if you're using 'ckAttachToInterface' connection
|
|
// kind.
|
|
procedure Connect; virtual; abstract;
|
|
procedure Disconnect; virtual; abstract;
|
|
|
|
published
|
|
property AutoConnect: Boolean read GetAutoConnect write SetAutoConnect;
|
|
property ConnectKind: TConnectKind read GetConnectKind write SetConnectKind;
|
|
property RemoteMachineName: string read FRemoteMachineName write FRemoteMachineName;
|
|
end;
|
|
{$ENDIF}
|
|
|
|
var
|
|
EmptyParam: OleVariant; { "Empty parameter" standard constant which can be
|
|
passed as an optional parameter on a dual interface. }
|
|
|
|
|
|
implementation
|
|
|
|
uses
|
|
OleConst;
|
|
|
|
const
|
|
// The following flags may be or'd into the TControlData.Reserved field to override
|
|
// default behaviors.
|
|
|
|
// cdForceSetClientSite:
|
|
// Call SetClientSite early (in constructor) regardless of misc status flags
|
|
cdForceSetClientSite = 1;
|
|
|
|
// cdDeferSetClientSite:
|
|
// Don't call SetClientSite early. Takes precedence over cdForceSetClientSite and misc status flags
|
|
cdDeferSetClientSite = 2;
|
|
|
|
const
|
|
cfBackColor = $00000001;
|
|
cfForeColor = $00000002;
|
|
cfFont = $00000004;
|
|
cfEnabled = $00000008;
|
|
cfCaption = $00000010;
|
|
cfText = $00000020;
|
|
|
|
const
|
|
MaxDispArgs = 32;
|
|
|
|
type
|
|
|
|
PDispInfo = ^TDispInfo;
|
|
TDispInfo = packed record
|
|
DispID: TDispID;
|
|
ResType: Byte;
|
|
CallDesc: TCallDesc;
|
|
end;
|
|
|
|
TArgKind = (akDWord, akSingle, akDouble);
|
|
|
|
PEventArg = ^TEventArg;
|
|
TEventArg = record
|
|
Kind: TArgKind;
|
|
Data: array[0..1] of Integer;
|
|
end;
|
|
|
|
TEventInfo = record
|
|
Method: TMethod;
|
|
Sender: TObject;
|
|
ArgCount: Integer;
|
|
Args: array[0..MaxDispArgs - 1] of TEventArg;
|
|
end;
|
|
|
|
function StringToVarOleStr(const S: string): Variant;
|
|
begin
|
|
VarClear(Result);
|
|
TVarData(Result).VOleStr := StringToOleStr(S);
|
|
TVarData(Result).VType := varOleStr;
|
|
end;
|
|
|
|
{ TEnumPropDesc }
|
|
|
|
constructor TEnumPropDesc.Create(DispID, ValueCount: Integer;
|
|
const TypeInfo: ITypeInfo);
|
|
var
|
|
I: Integer;
|
|
VarDesc: PVarDesc;
|
|
XName: WideString;
|
|
begin
|
|
FDispID := DispID;
|
|
FValueCount := ValueCount;
|
|
FValues := AllocMem(ValueCount * SizeOf(TEnumValue));
|
|
for I := 0 to ValueCount - 1 do
|
|
begin
|
|
OleCheck(TypeInfo.GetVarDesc(I, VarDesc));
|
|
try
|
|
OleCheck(TypeInfo.GetDocumentation(VarDesc^.memid, @XName,
|
|
nil, nil, nil));
|
|
with FValues^[I] do
|
|
begin
|
|
Value := TVarData(VarDesc^.lpVarValue^).VInteger;
|
|
Ident := XName;
|
|
while (Length(Ident) > 1) and (Ident[1] = '_') do
|
|
Delete(Ident, 1, 1);
|
|
end;
|
|
finally
|
|
TypeInfo.ReleaseVarDesc(VarDesc);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
destructor TEnumPropDesc.Destroy;
|
|
begin
|
|
if FValues <> nil then
|
|
begin
|
|
Finalize(FValues^[0], FValueCount);
|
|
FreeMem(FValues, FValueCount * SizeOf(TEnumValue));
|
|
end;
|
|
inherited;
|
|
end;
|
|
|
|
procedure TEnumPropDesc.GetStrings(Proc: TGetStrProc);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to FValueCount - 1 do
|
|
with FValues^[I] do Proc(Format('%d - %s', [Value, Ident]));
|
|
end;
|
|
|
|
function TEnumPropDesc.StringToValue(const S: string): Integer;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
I := 1;
|
|
while (I <= Length(S)) and (S[I] in ['0'..'9', '-']) do Inc(I);
|
|
if I > 1 then
|
|
begin
|
|
Result := Str2Int(Copy(S, 1, I - 1));
|
|
for I := 0 to FValueCount - 1 do
|
|
if Result = FValues^[I].Value then Exit;
|
|
end else
|
|
for I := 0 to FValueCount - 1 do
|
|
with FValues^[I] do
|
|
if AnsiCompareText(S, Ident) = 0 then
|
|
begin
|
|
Result := Value;
|
|
Exit;
|
|
end;
|
|
raise EOleError.CreateResFmt(e_Ole, Integer( @SBadPropValue ), [S]);
|
|
end;
|
|
|
|
function TEnumPropDesc.ValueToString(V: Integer): string;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to FValueCount - 1 do
|
|
with FValues^[I] do
|
|
if V = Value then
|
|
begin
|
|
Result := Format('%d - %s', [Value, Ident]);
|
|
Exit;
|
|
end;
|
|
Result := Int2Str(V);
|
|
end;
|
|
|
|
{ TOleCtl }
|
|
|
|
procedure TOleCtl.CreateControl;
|
|
var
|
|
Stream: IStream;
|
|
CS: IOleClientSite;
|
|
X: Integer;
|
|
begin
|
|
if FOleControl = nil then
|
|
try
|
|
try // work around ATL bug
|
|
X := FOleObject.GetClientSite(CS);
|
|
except
|
|
X := -1;
|
|
end;
|
|
if (X <> 0) or (CS = nil) then
|
|
OleCheck(FOleObject.SetClientSite(fOleCtlIntf));
|
|
if FObjectData = 0 then OleCheck(FPersistStream.InitNew) else
|
|
begin
|
|
OleCheck(CreateStreamOnHGlobal(FObjectData, False, Stream));
|
|
OleCheck(FPersistStream.Load(Stream));
|
|
DestroyStorage;
|
|
end;
|
|
OleCheck(FOleObject.QueryInterface(IOleControl, FOleControl));
|
|
OleCheck(FOleObject.QueryInterface(IDispatch, FControlDispatch));
|
|
FOleObject.QueryInterface(IPerPropertyBrowsing, FPropBrowsing);
|
|
InterfaceConnect(FOleObject, IPropertyNotifySink,
|
|
fOleCtlIntf, FPropConnection);
|
|
InterfaceConnect(FOleObject, FControlData^.EventIID,
|
|
FEventDispatch, FEventsConnection);
|
|
if FControlData^.Flags and cfBackColor <> 0 then
|
|
fOleCtlIntf.OnChanged(DISPID_BACKCOLOR);
|
|
if FControlData^.Flags and cfEnabled <> 0 then
|
|
fOleCtlIntf.OnChanged(DISPID_ENABLED);
|
|
if FControlData^.Flags and cfFont <> 0 then
|
|
fOleCtlIntf.OnChanged(DISPID_FONT);
|
|
if FControlData^.Flags and cfForeColor <> 0 then
|
|
fOleCtlIntf.OnChanged(DISPID_FORECOLOR);
|
|
FOleControl.OnAmbientPropertyChange(DISPID_UNKNOWN);
|
|
fOleCtlIntf.RequestNewObjectLayout;
|
|
except
|
|
DestroyControl;
|
|
raise;
|
|
end;
|
|
end;
|
|
|
|
procedure TOleCtl.CreateEnumPropDescs;
|
|
|
|
function FindMember(DispId: Integer): Boolean;
|
|
begin
|
|
Result := GetEnumPropDesc(DispId) <> nil;
|
|
end;
|
|
{var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to FControlData^.EnumPropDescs.Count - 1 do
|
|
if TEnumPropDesc(FControlData^.EnumPropDescs).FDispID = DispID then
|
|
begin
|
|
Result := True;
|
|
Exit;
|
|
end;
|
|
Result := False;
|
|
end;}
|
|
|
|
procedure CreateEnum(TypeDesc: TTypeDesc; const TypeInfo: ITypeInfo;
|
|
DispId: Integer);
|
|
var
|
|
RefInfo: ITypeInfo;
|
|
RefAttr: PTypeAttr;
|
|
epd: PEnumPropDesc;
|
|
begin
|
|
if TypeDesc.vt <> VT_USERDEFINED then Exit;
|
|
OleCheck(TypeInfo.GetRefTypeInfo(TypeDesc.hreftype, RefInfo));
|
|
OleCheck(RefInfo.GetTypeAttr(RefAttr));
|
|
try
|
|
if RefAttr^.typekind = TKIND_ENUM then
|
|
begin
|
|
new( epd, Create(Dispid, RefAttr^.cVars, RefInfo) );
|
|
FControlData^.EnumPropDescs.Add( epd );
|
|
end;
|
|
finally
|
|
RefInfo.ReleaseTypeAttr(RefAttr);
|
|
end;
|
|
end;
|
|
|
|
procedure ProcessTypeInfo(const TypeInfo: ITypeInfo);
|
|
var
|
|
I: Integer;
|
|
RefInfo: ITypeInfo;
|
|
TypeAttr: PTypeAttr;
|
|
VarDesc: PVarDesc;
|
|
FuncDesc: PFuncDesc;
|
|
RefType: HRefType;
|
|
begin
|
|
OleCheck(TypeInfo.GetTypeAttr(TypeAttr));
|
|
try
|
|
if IsEqualGUID(TypeAttr^.guid, IDispatch) then Exit;
|
|
if ((TypeAttr.typekind = TKIND_INTERFACE) or
|
|
(TypeAttr.wTypeFlags and TYPEFLAG_FDUAL <> 0)) and
|
|
(TypeAttr.wTypeFlags and TYPEFLAG_FNONEXTENSIBLE <> 0) then
|
|
begin
|
|
OleCheck(TypeInfo.GetRefTypeOfImplType(0, RefType));
|
|
OleCheck(TypeInfo.GetRefTypeInfo(RefType, RefInfo));
|
|
ProcessTypeInfo(RefInfo);
|
|
end;
|
|
for I := 0 to TypeAttr^.cVars - 1 do
|
|
begin
|
|
OleCheck(TypeInfo.GetVarDesc(I, VarDesc));
|
|
try
|
|
CreateEnum(VarDesc^.elemdescVar.tdesc, TypeInfo, VarDesc^.memid);
|
|
finally
|
|
TypeInfo.ReleaseVarDesc(VarDesc);
|
|
end;
|
|
end;
|
|
for I := 0 to TypeAttr^.cFuncs - 1 do
|
|
begin
|
|
OleCheck(TypeInfo.GetFuncDesc(I, FuncDesc));
|
|
try
|
|
if not FindMember(FuncDesc^.memid) then
|
|
case FuncDesc^.invkind of
|
|
INVOKE_PROPERTYGET:
|
|
CreateEnum(FuncDesc^.elemdescFunc.tdesc, TypeInfo, FuncDesc^.memid);
|
|
INVOKE_PROPERTYPUT:
|
|
CreateEnum(FuncDesc^.lprgelemdescParam[FuncDesc.cParams - 1].tdesc,
|
|
TypeInfo, FuncDesc^.memid);
|
|
INVOKE_PROPERTYPUTREF:
|
|
if FuncDesc^.lprgelemdescParam[FuncDesc.cParams - 1].tdesc.vt = VT_PTR then
|
|
CreateEnum(FuncDesc^.lprgelemdescParam[FuncDesc.cParams - 1].tdesc.ptdesc^,
|
|
TypeInfo, FuncDesc^.memid);
|
|
end;
|
|
finally
|
|
TypeInfo.ReleaseFuncDesc(FuncDesc);
|
|
end;
|
|
end;
|
|
finally
|
|
TypeInfo.ReleaseTypeAttr(TypeAttr);
|
|
end;
|
|
end;
|
|
|
|
var
|
|
TypeInfo: ITypeInfo;
|
|
begin
|
|
CreateControl;
|
|
FControlData^.EnumPropDescs := NewList;
|
|
try
|
|
OleCheck(FControlDispatch.GetTypeInfo(0, 0, TypeInfo));
|
|
ProcessTypeInfo(TypeInfo);
|
|
except
|
|
DestroyEnumPropDescs;
|
|
raise;
|
|
end;
|
|
end;
|
|
|
|
procedure TOleCtl.CreateInstance;
|
|
var
|
|
ClassFactory2: IClassFactory2;
|
|
LicKeyStr: WideString;
|
|
|
|
procedure LicenseCheck(Status: HResult; const Ident: string);
|
|
begin
|
|
if Status = CLASS_E_NOTLICENSED then
|
|
raise EOleError.CreateFmt(e_Ole, Ident, [SubClassName]);
|
|
OleCheck(Status);
|
|
end;
|
|
|
|
begin
|
|
if (FControlData^.LicenseKey <> nil) then
|
|
begin
|
|
OleCheck(CoGetClassObject(FControlData^.ClassID, CLSCTX_INPROC_SERVER or
|
|
CLSCTX_LOCAL_SERVER, nil, IClassFactory2, ClassFactory2));
|
|
LicKeyStr := PWideChar(FControlData^.LicenseKey);
|
|
LicenseCheck(ClassFactory2.CreateInstanceLic(nil, nil, IOleObject,
|
|
LicKeyStr, FOleObject), SInvalidLicense);
|
|
end else
|
|
LicenseCheck(CoCreateInstance(FControlData^.ClassID, nil,
|
|
CLSCTX_INPROC_SERVER or CLSCTX_LOCAL_SERVER, IOleObject,
|
|
FOleObject), SNotLicensed);
|
|
end;
|
|
|
|
procedure CallEventMethod(const EventInfo: TEventInfo);
|
|
asm
|
|
PUSH EBX
|
|
PUSH ESI
|
|
PUSH EBP
|
|
MOV EBP,ESP
|
|
MOV EBX,EAX
|
|
MOV EDX,[EBX].TEventInfo.ArgCount
|
|
TEST EDX,EDX
|
|
JE @@5
|
|
XOR EAX,EAX
|
|
LEA ESI,[EBX].TEventInfo.Args
|
|
@@1: MOV AL,[ESI].TEventArg.Kind
|
|
CMP AL,1
|
|
JA @@2
|
|
JE @@3
|
|
TEST AH,AH
|
|
JNE @@3
|
|
MOV ECX,[ESI].Integer[4]
|
|
MOV AH,1
|
|
JMP @@4
|
|
@@2: PUSH [ESI].Integer[8]
|
|
@@3: PUSH [ESI].Integer[4]
|
|
@@4: ADD ESI,12
|
|
DEC EDX
|
|
JNE @@1
|
|
@@5: MOV EDX,[EBX].TEventInfo.Sender
|
|
MOV EAX,[EBX].TEventInfo.Method.Data
|
|
CALL [EBX].TEventInfo.Method.Code
|
|
MOV ESP,EBP
|
|
POP EBP
|
|
POP ESI
|
|
POP EBX
|
|
end;
|
|
|
|
type
|
|
PVarArg = ^TVarArg;
|
|
TVarArg = array[0..3] of DWORD;
|
|
|
|
function TOleCtl.CreateWindow: Boolean;
|
|
begin
|
|
Result := FALSE;
|
|
if fHandle <> 0 then
|
|
begin
|
|
Result := TRUE;
|
|
Exit;
|
|
end;
|
|
if fCreatingWnd then
|
|
Exit;
|
|
fCreatingWnd := TRUE;
|
|
try
|
|
CreateControl;
|
|
if FMiscStatus and OLEMISC_INVISIBLEATRUNTIME = 0 then
|
|
begin
|
|
FOleObject.DoVerb(OLEIVERB_INPLACEACTIVATE, nil, fOleCtlIntf, 0,
|
|
ParentWindow, BoundsRect);
|
|
if FOleInPlaceObject = nil then
|
|
raise EOleError.CreateResFmt(e_Ole, Integer( @SCannotActivate ), [nil]);
|
|
HookControlWndProc;
|
|
if {$IFDEF USE_FLAGS} not(F3_Visible in fStyle.f3_Style)
|
|
{$ELSE} not fVisible {$ENDIF}
|
|
and IsWindowVisible(fHandle) then
|
|
ShowWindow(fHandle, SW_HIDE);
|
|
Result := TRUE;
|
|
end
|
|
else
|
|
Result := inherited CreateWindow;
|
|
finally
|
|
fCreatingWnd := FALSE;
|
|
end;
|
|
end;
|
|
|
|
procedure TOleCtl.D2InvokeEvent(DispID: TDispID; var Params: TDispParams);
|
|
type
|
|
TStringDesc = record
|
|
PStr: Pointer;
|
|
BStr: PBStr;
|
|
end;
|
|
var
|
|
I, J, K, ArgType, ArgCount, StrCount: Integer;
|
|
ArgPtr: PEventArg;
|
|
ParamPtr: PVarArg;
|
|
Strings: array[0..MaxDispArgs - 1] of TStringDesc;
|
|
EventInfo: TEventInfo;
|
|
begin
|
|
fOleCtlIntf.GetEventMethod(DispID, EventInfo.Method);
|
|
if Integer(EventInfo.Method.Code) >= $10000 then
|
|
begin
|
|
StrCount := 0;
|
|
try
|
|
ArgCount := Params.cArgs;
|
|
EventInfo.Sender := fOleCtlIntf;
|
|
EventInfo.ArgCount := ArgCount;
|
|
if ArgCount <> 0 then
|
|
begin
|
|
ParamPtr := @Params.rgvarg^[EventInfo.ArgCount];
|
|
ArgPtr := @EventInfo.Args;
|
|
I := 0;
|
|
repeat
|
|
Dec(Integer(ParamPtr), SizeOf(TVarArg));
|
|
ArgType := ParamPtr^[0] and $0000FFFF;
|
|
if ArgType and varTypeMask = varOleStr then
|
|
begin
|
|
ArgPtr^.Kind := akDWord;
|
|
with Strings[StrCount] do
|
|
begin
|
|
PStr := nil;
|
|
if ArgType and varByRef <> 0 then
|
|
begin
|
|
OleStrToStrVar(PBStr(ParamPtr^[2])^, string(PStr));
|
|
BStr := PBStr(ParamPtr^[2]);
|
|
ArgPtr^.Data[0] := Integer(@PStr);
|
|
end else
|
|
begin
|
|
OleStrToStrVar(TBStr(ParamPtr^[2]), string(PStr));
|
|
BStr := nil;
|
|
ArgPtr^.Data[0] := Integer(PStr);
|
|
end;
|
|
end;
|
|
Inc(StrCount);
|
|
end else
|
|
begin
|
|
case ArgType of
|
|
varSingle:
|
|
begin
|
|
ArgPtr^.Kind := akSingle;
|
|
ArgPtr^.Data[0] := ParamPtr^[2];
|
|
end;
|
|
varDouble..varDate:
|
|
begin
|
|
ArgPtr^.Kind := akDouble;
|
|
ArgPtr^.Data[0] := ParamPtr^[2];
|
|
ArgPtr^.Data[1] := ParamPtr^[3];
|
|
end;
|
|
varDispatch:
|
|
begin
|
|
ArgPtr^.Kind := akDWord;
|
|
ArgPtr^.Data[0] := Integer(ParamPtr)
|
|
end;
|
|
else
|
|
ArgPtr^.Kind := akDWord;
|
|
if (ArgType and varArray) <> 0 then
|
|
ArgPtr^.Data[0] := Integer(ParamPtr)
|
|
else
|
|
ArgPtr^.Data[0] := ParamPtr^[2];
|
|
end;
|
|
end;
|
|
Inc(Integer(ArgPtr), SizeOf(TEventArg));
|
|
Inc(I);
|
|
until I = EventInfo.ArgCount;
|
|
end;
|
|
CallEventMethod(EventInfo);
|
|
J := StrCount;
|
|
while J <> 0 do
|
|
begin
|
|
Dec(J);
|
|
with Strings[J] do
|
|
if BStr <> nil then BStr^ := StringToOleStr(string(PStr));
|
|
end;
|
|
except
|
|
DoHandleException;
|
|
end;
|
|
K := StrCount;
|
|
while K <> 0 do
|
|
begin
|
|
Dec(K);
|
|
string(Strings[K].PStr) := '';
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TOleCtl.DblClk;
|
|
var MouseData: TMouseEventData;
|
|
P: TPoint;
|
|
begin
|
|
{$IFDEF NIL_EVENTS}
|
|
if Assigned(EV.fOnMouseDblClk) then
|
|
{$ENDIF}
|
|
begin
|
|
MouseData.Button := mbLeft;
|
|
MouseData.Shift := 0;
|
|
GetCursorPos( P );
|
|
P := Screen2Client( P );
|
|
MouseData.X := P.x;
|
|
MouseData.Y := P.y;
|
|
EV.fOnMouseDblClk(@Self, MouseData);
|
|
end;
|
|
end;
|
|
|
|
destructor TOleCtl.Destroy;
|
|
|
|
procedure FreeList(var L: PList);
|
|
begin
|
|
if L = nil then Exit;
|
|
L.Release;
|
|
L := nil;
|
|
end;
|
|
|
|
begin
|
|
SetUIActive(False);
|
|
if FOleObject <> nil then FOleObject.Close(OLECLOSE_NOSAVE);
|
|
DestroyControl;
|
|
DestroyStorage;
|
|
FPersistStream := nil;
|
|
if FOleObject <> nil then FOleObject.SetClientSite(nil);
|
|
FOleObject := nil;
|
|
FEventDispatch.Free;
|
|
FreeList(FFonts);
|
|
FreeList(FPictures);
|
|
Dec(FControlData^.InstanceCount);
|
|
if FControlData^.InstanceCount = 0 then
|
|
DestroyEnumPropDescs;
|
|
fOleCtlIntf.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TOleCtl.DestroyControl;
|
|
begin
|
|
InterfaceDisconnect(FOleObject, FControlData^.EventIID, FEventsConnection);
|
|
InterfaceDisconnect(FOleObject, IPropertyNotifySink, FPropConnection);
|
|
FPropBrowsing := nil;
|
|
FControlDispatch := nil;
|
|
FOleControl := nil;
|
|
end;
|
|
|
|
procedure TOleCtl.DestroyEnumPropDescs;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
with FControlData^ do
|
|
if EnumPropDescs <> nil then
|
|
begin
|
|
for I := 0 to EnumPropDescs.Count - 1 do
|
|
PEnumPropDesc(EnumPropDescs.Items[I]).Free;
|
|
EnumPropDescs.Free;
|
|
EnumPropDescs := nil;
|
|
end;
|
|
end;
|
|
|
|
procedure TOleCtl.DestroyStorage;
|
|
begin
|
|
if FObjectData <> 0 then
|
|
begin
|
|
GlobalFree(FObjectData);
|
|
FObjectData := 0;
|
|
end;
|
|
end;
|
|
|
|
procedure TOleCtl.DoHandleException;
|
|
begin
|
|
//Application.HandleException(Self);
|
|
//TODO: replace Application.HandleException with something
|
|
end;
|
|
|
|
function TOleCtl.GetByteProp(Index: Integer): Byte;
|
|
begin
|
|
Result := GetIntegerProp(Index);
|
|
end;
|
|
|
|
function TOleCtl.GetColorProp(Index: Integer): TColor;
|
|
begin
|
|
Result := GetIntegerProp(Index);
|
|
end;
|
|
|
|
function TOleCtl.GetCompProp(Index: Integer): Comp;
|
|
begin
|
|
Result := GetDoubleProp(Index);
|
|
end;
|
|
|
|
function TOleCtl.GetCurrencyProp(Index: Integer): Currency;
|
|
var
|
|
Temp: TVarData;
|
|
begin
|
|
GetProperty(Index, Temp);
|
|
Result := Temp.VCurrency;
|
|
end;
|
|
|
|
function TOleCtl.GetDoubleProp(Index: Integer): Double;
|
|
var
|
|
Temp: TVarData;
|
|
begin
|
|
GetProperty(Index, Temp);
|
|
Result := Temp.VDouble;
|
|
end;
|
|
|
|
procedure TOleCtlIntf.GetEventMethod(DispID: TDispID; var Method: TMethod);
|
|
{begin // test for D4 - it works...
|
|
Method.Code := nil;
|
|
Method.Data := nil;
|
|
end;}
|
|
const
|
|
szOleCtl = sizeof( TOleCtl );
|
|
asm
|
|
PUSH EBX
|
|
PUSH ESI
|
|
PUSH EDI
|
|
PUSH ECX
|
|
MOV EBX,EAX
|
|
MOV ECX,[EBX].fOleCtl
|
|
///////////////////////// fix of events handling
|
|
MOV EBX, ECX // by Alexey Izyumov
|
|
///////////////////////// Octouber, 2001
|
|
MOV ECX,[ECX].TOleCtl.FControlData
|
|
MOV EDI,[ECX].TControlData.EventCount
|
|
MOV ESI,[ECX].TControlData.EventDispIDs
|
|
XOR EAX,EAX
|
|
JMP @@1
|
|
@@0: CMP EDX,[ESI].Integer[EAX*4]
|
|
JE @@2
|
|
INC EAX
|
|
@@1: CMP EAX,EDI
|
|
JNE @@0
|
|
XOR EAX,EAX
|
|
XOR EDX,EDX
|
|
JMP @@3
|
|
@@2: PUSH EAX
|
|
CMP [ECX].TControlData.Version, 401
|
|
JB @@2a
|
|
MOV EAX, [ECX].TControlData2.FirstEventOfs
|
|
TEST EAX, EAX
|
|
JNE @@2b
|
|
@@2a: {MOV EAX, [EBX]
|
|
CALL TObject.ClassParent
|
|
CALL TObject.InstanceSize}
|
|
MOV EAX, szOleCtl
|
|
ADD EAX, 7
|
|
AND EAX, not 7 // 8 byte alignment
|
|
@@2b: ADD EBX, EAX
|
|
POP EAX
|
|
MOV EDX,[EBX][EAX*8].TMethod.Data
|
|
MOV EAX,[EBX][EAX*8].TMethod.Code
|
|
@@3: POP ECX
|
|
MOV [ECX].TMethod.Code,EAX
|
|
MOV [ECX].TMethod.Data,EDX
|
|
POP EDI
|
|
POP ESI
|
|
POP EBX
|
|
end;
|
|
|
|
function TOleCtl.GetEnumPropDesc(DispID: Integer): PEnumPropDesc;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
with FControlData^ do
|
|
begin
|
|
if EnumPropDescs = nil then CreateEnumPropDescs;
|
|
for I := 0 to EnumPropDescs.Count - 1 do
|
|
begin
|
|
Result := EnumPropDescs.Items[I];
|
|
if Result.FDispID = DispID then Exit;
|
|
end;
|
|
Result := nil;
|
|
end;
|
|
end;
|
|
|
|
function TOleCtl.GetIDispatchProp(Index: Integer): IDispatch;
|
|
var
|
|
Temp: TVarData;
|
|
begin
|
|
GetProperty(Index, Temp);
|
|
Result := IDispatch(Temp.VDispatch);
|
|
end;
|
|
|
|
function TOleCtl.GetIntegerProp(Index: Integer): Integer;
|
|
var
|
|
Temp: TVarData;
|
|
begin
|
|
GetProperty(Index, Temp);
|
|
Result := Temp.VInteger;
|
|
end;
|
|
|
|
function TOleCtl.GetIUnknownProp(Index: Integer): IUnknown;
|
|
var
|
|
Temp: TVarData;
|
|
begin
|
|
GetProperty(Index, Temp);
|
|
Result := IUnknown(Temp.VUnknown);
|
|
end;
|
|
|
|
function TOleCtl.GetMainMenu: HMenu;
|
|
var
|
|
Form: PControl;
|
|
begin
|
|
Result := 0;
|
|
Form := ParentForm;
|
|
if Form <> nil then
|
|
//if Form.FormStyle <> fsMDIChild then
|
|
Result := Form.Menu
|
|
{else
|
|
if Application.MainForm <> nil then
|
|
Result := Application.MainForm.Menu};
|
|
end;
|
|
|
|
function TOleCtl.GetOleBoolProp(Index: Integer): TOleBool;
|
|
var
|
|
Temp: TVarData;
|
|
begin
|
|
GetProperty(Index, Temp);
|
|
Result := Temp.VBoolean;
|
|
end;
|
|
|
|
function TOleCtl.GetOleDateProp(Index: Integer): TOleDate;
|
|
var
|
|
Temp: TVarData;
|
|
begin
|
|
GetProperty(Index, Temp);
|
|
Result := Temp.VDate;
|
|
end;
|
|
|
|
function TOleCtl.GetOleEnumProp(Index: Integer): TOleEnum;
|
|
begin
|
|
Result := GetIntegerProp(Index);
|
|
end;
|
|
|
|
function TOleCtl.GetOleObject: Variant;
|
|
begin
|
|
CreateControl;
|
|
Result := Variant(FOleObject as IDispatch);
|
|
end;
|
|
|
|
function TOleCtl.GetOleVariantProp(Index: Integer): OleVariant;
|
|
begin
|
|
VarClear(Result);
|
|
GetProperty(Index, TVarData(Result));
|
|
end;
|
|
|
|
function TOleCtl.GetOnLeave: TOnEvent;
|
|
begin
|
|
Result := OnExit;
|
|
end;
|
|
|
|
var // init to zero, never written to
|
|
DispParams: TDispParams = ();
|
|
|
|
procedure TOleCtl.GetProperty(Index: Integer; var Value: TVarData);
|
|
var
|
|
Status: HResult;
|
|
ExcepInfo: TExcepInfo;
|
|
begin
|
|
CreateControl;
|
|
Value.VType := varEmpty;
|
|
Status := FControlDispatch.Invoke(Index, GUID_NULL, 0,
|
|
DISPATCH_PROPERTYGET, DispParams, @Value, @ExcepInfo, nil);
|
|
if Status <> 0 then DispatchInvokeError(Status, ExcepInfo);
|
|
end;
|
|
|
|
function TOleCtl.GetShortIntProp(Index: Integer): ShortInt;
|
|
begin
|
|
Result := GetIntegerProp(Index);
|
|
end;
|
|
|
|
function TOleCtl.GetSingleProp(Index: Integer): Single;
|
|
var
|
|
Temp: TVarData;
|
|
begin
|
|
GetProperty(Index, Temp);
|
|
Result := Temp.VSingle;
|
|
end;
|
|
|
|
function TOleCtl.GetSmallintProp(Index: Integer): Smallint;
|
|
var
|
|
Temp: TVarData;
|
|
begin
|
|
GetProperty(Index, Temp);
|
|
Result := Temp.VSmallint;
|
|
end;
|
|
|
|
function TOleCtl.GetStringProp(Index: Integer): string;
|
|
begin
|
|
Result := GetVariantProp(Index);
|
|
end;
|
|
|
|
function TOleCtl.GetTColorProp(Index: Integer): TColor;
|
|
begin
|
|
Result := GetIntegerProp(Index);
|
|
end;
|
|
|
|
function TOleCtl.GetTDateTimeProp(Index: Integer): TDateTime;
|
|
var
|
|
Temp: TVarData;
|
|
begin
|
|
GetProperty(Index, Temp);
|
|
Result := Temp.VDate;
|
|
end;
|
|
|
|
function TOleCtl.GetTFontProp(Index: Integer): PGraphicTool;
|
|
{var
|
|
I: Integer;}
|
|
begin
|
|
Result := nil;
|
|
{for I := 0 to FFonts.Count-1 do
|
|
if FControlData^.FontIDs^[I] = Index then
|
|
begin
|
|
Result := TFont(FFonts[I]);
|
|
if Result.FontAdapter = nil then
|
|
SetOleFont(Result, GetIDispatchProp(Index) as IFontDisp);
|
|
end;}
|
|
//TODO: implement TFont later
|
|
end;
|
|
|
|
function TOleCtl.GetTOleEnumProp(Index: Integer): TOleEnum;
|
|
begin
|
|
Result := GetIntegerProp(Index);
|
|
end;
|
|
|
|
function TOleCtl.GetVariantProp(Index: Integer): Variant;
|
|
begin
|
|
Result := GetOleVariantProp(Index);
|
|
end;
|
|
|
|
function TOleCtl.GetWideStringProp(Index: Integer): WideString;
|
|
var
|
|
Temp: TVarData;
|
|
begin
|
|
Result := '';
|
|
GetProperty(Index, Temp);
|
|
Pointer(Result) := Temp.VOleStr;
|
|
end;
|
|
|
|
function TOleCtl.GetWordBoolProp(Index: Integer): WordBool;
|
|
var
|
|
Temp: TVarData;
|
|
begin
|
|
GetProperty(Index, Temp);
|
|
Result := Temp.VBoolean;
|
|
end;
|
|
|
|
function TOleCtl.GetWordProp(Index: Integer): Word;
|
|
begin
|
|
Result := GetIntegerProp(Index);
|
|
end;
|
|
|
|
procedure TOleCtl.HookControlWndProc;
|
|
var
|
|
WndHandle: HWnd;
|
|
begin
|
|
if (FOleInPlaceObject <> nil) and (fHandle = 0) then
|
|
begin
|
|
WndHandle := 0;
|
|
FOleInPlaceObject.GetWindow(WndHandle);
|
|
if WndHandle = 0 then
|
|
raise EOleError.CreateResFmt(e_Ole, Integer(@SNoWindowHandle), [nil]);
|
|
fHandle := WndHandle;
|
|
fDefWndProc := Pointer(GetWindowLong(fHandle, GWL_WNDPROC));
|
|
CreatingWindow := @Self;
|
|
SetWindowLong(fHandle, GWL_WNDPROC, Longint(@WndFunc));
|
|
SendMessage(fHandle, WM_NULL, 0, 0);
|
|
end;
|
|
end;
|
|
|
|
procedure TOleCtl.Init;
|
|
var
|
|
I: Integer;
|
|
intfClass: TOleCtlIntfClass;
|
|
begin
|
|
OleInit;
|
|
inherited;
|
|
// overriding this method, we allow for constructor to initialize
|
|
// the object.
|
|
fControlClassName := 'OleCtl'; // ClassName
|
|
{$IFDEF USE_FLAGS} include( fFlagsG3, G3_IsControl );
|
|
{$ELSE} fIsControl := TRUE; {$ENDIF}
|
|
fStyle.Value := WS_VISIBLE or WS_CLIPCHILDREN or WS_CLIPSIBLINGS or
|
|
WS_CHILD; // or WS_BORDER or WS_THICKFRAME;
|
|
|
|
//AttachProc( WndProcCtrl ); for test only
|
|
|
|
// The rest of initialization -- moved from OleCtrls
|
|
InitControlData;
|
|
Inc(FControlData^.InstanceCount);
|
|
if FControlData^.FontCount > 0 then
|
|
begin
|
|
FFonts := NewList;
|
|
//FFonts.Count := FControlData^.FontCount;
|
|
for I := 0 to FControlData^.FontCount-1 do
|
|
FFonts.Add( NewFont );
|
|
end;
|
|
{if FControlData^.PictureCount > 0 then
|
|
begin
|
|
FPictures := NewList;
|
|
//FPictures.Count := FControlData^.PictureCount;
|
|
for I := 0 to FControlData^.PictureCount-1 do
|
|
begin
|
|
FPictures.Add( NewPicture );
|
|
TPicture(FPictures[I]).OnChange := PictureChanged;
|
|
end;
|
|
end;}
|
|
FEventDispatch := TEventDispatch.Create(@Self);
|
|
CreateInstance;
|
|
InitControlInterface(FOleObject);
|
|
OleCheck(FOleObject.GetMiscStatus(DVASPECT_CONTENT, FMiscStatus));
|
|
|
|
if (Assigned(OnGetIntfClass)) then
|
|
intfClass := OnGetIntfClass()
|
|
else
|
|
intfClass := TOleCtlIntf;
|
|
fOleCtlIntf := intfClass.Create;
|
|
fOleCtlIntf.fOleCtl := @Self;
|
|
|
|
if (FControlData^.Reserved and cdDeferSetClientSite) = 0 then
|
|
if ((FMiscStatus and OLEMISC_SETCLIENTSITEFIRST) <> 0) or
|
|
((FControlData^.Reserved and cdForceSetClientSite) <> 0) then
|
|
OleCheck(FOleObject.SetClientSite(fOleCtlIntf));
|
|
OleCheck(FOleObject.QueryInterface(IPersistStreamInit, FPersistStream));
|
|
if FMiscStatus and OLEMISC_INVISIBLEATRUNTIME <> 0 then
|
|
{$IFDEF USE_FLAGS} exclude( fStyle.f3_Style, F3_Visible );
|
|
{$ELSE} fVisible := False; {$ENDIF}
|
|
{if FMiscStatus and OLEMISC_SIMPLEFRAME <> 0 then
|
|
ControlStyle := [csAcceptsControls, csDoubleClicks, csNoStdEvents] else
|
|
ControlStyle := [csDoubleClicks, csNoStdEvents];}
|
|
if FMiscStatus and OLEMISC_SIMPLEFRAME = 0 then
|
|
fExStyle := 0; // clear WS_EX_CONTROLPARENT
|
|
TabStop := FMiscStatus and (OLEMISC_ACTSLIKELABEL or
|
|
OLEMISC_NOUIACTIVATE) = 0;
|
|
OleCheck(fOleCtlIntf.RequestNewObjectLayout);
|
|
end;
|
|
|
|
procedure TOleCtl.InitControlData;
|
|
begin
|
|
// nothing here. Originally, this method was abstract.
|
|
// Since TOleControl class became TOleCtl object, abstract methods
|
|
// are not available. So, make this method empty to override it
|
|
// in descendant objects, which represent Active-X controls.
|
|
end;
|
|
|
|
procedure TOleCtl.InitControlInterface(const Obj: IUnknown);
|
|
begin
|
|
// This method is to override it in derived Active-X control holder.
|
|
end;
|
|
|
|
procedure TOleCtl.InvokeEvent(DispID: TDispID; var Params: TDispParams);
|
|
var
|
|
EventMethod: TMethod;
|
|
begin
|
|
if ControlData.Version < 300 then
|
|
D2InvokeEvent(DispID, Params)
|
|
else
|
|
begin
|
|
fOleCtlIntf.GetEventMethod(DispID, EventMethod);
|
|
if Integer(EventMethod.Code) < $10000 then Exit;
|
|
|
|
try
|
|
asm
|
|
PUSH EBX
|
|
PUSH ESI
|
|
MOV ESI, Params
|
|
MOV EBX, [ESI].TDispParams.cArgs
|
|
TEST EBX, EBX
|
|
JZ @@7
|
|
MOV ESI, [ESI].TDispParams.rgvarg
|
|
MOV EAX, EBX
|
|
SHL EAX, 4 // count * sizeof(TVarArg)
|
|
XOR EDX, EDX
|
|
ADD ESI, EAX // EDI = Params.rgvarg^[ArgCount]
|
|
@@1: SUB ESI, 16 // Sizeof(TVarArg)
|
|
MOV EAX, dword ptr [ESI]
|
|
CMP AX, varSingle
|
|
JA @@3
|
|
JE @@4
|
|
@@2: TEST DL,DL
|
|
JNE @@2a
|
|
MOV ECX, ESI
|
|
INC DL
|
|
TEST EAX, varArray
|
|
JNZ @@6
|
|
MOV ECX, dword ptr [ESI+8]
|
|
JMP @@6
|
|
@@2a: TEST EAX, varArray
|
|
JZ @@5
|
|
PUSH ESI
|
|
JMP @@6
|
|
@@3: CMP AX, varDate
|
|
JA @@2
|
|
@@4: PUSH dword ptr [ESI+12]
|
|
@@5: PUSH dword ptr [ESI+8]
|
|
@@6: DEC EBX
|
|
JNE @@1
|
|
@@7: MOV EDX, Self
|
|
MOV EAX, EventMethod.Data
|
|
CALL EventMethod.Code
|
|
POP ESI
|
|
POP EBX
|
|
end;
|
|
except
|
|
DoHandleException;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TOleCtl.KeyDown(var Key: Longint; AShift: DWORD);
|
|
begin
|
|
if Assigned(EV.fOnKeyDown) then EV.fOnKeyDown(@Self, Key, AShift);
|
|
end;
|
|
|
|
procedure TOleCtl.KeyPress(var Key: KOLChar);
|
|
begin
|
|
if Assigned(EV.fOnChar) then EV.fOnChar(@Self, Key, 0);
|
|
end;
|
|
|
|
procedure TOleCtl.KeyUp(var Key: Longint; AShift: DWORD);
|
|
begin
|
|
if Assigned(EV.fOnKeyUp) then EV.fOnKeyUp(@Self, Key, AShift);
|
|
end;
|
|
|
|
procedure TOleCtl.MouseDown(Button: TMouseButton; AShift: DWORD; X,
|
|
Y: Integer);
|
|
begin
|
|
//TODO: mouse
|
|
end;
|
|
|
|
procedure TOleCtl.MouseMove(AShift: DWORD; X, Y: Integer);
|
|
begin
|
|
//TODO: mouse
|
|
end;
|
|
|
|
procedure TOleCtl.MouseUp(Button: TMouseButton; AShift: DWORD; X,
|
|
Y: Integer);
|
|
begin
|
|
//TODO: mouse
|
|
end;
|
|
|
|
procedure TOleCtl.SetByteProp(Index: Integer; Value: Byte);
|
|
begin
|
|
SetIntegerProp(Index, Value);
|
|
end;
|
|
|
|
procedure TOleCtl.SetColorProp(Index: Integer; Value: TColor);
|
|
begin
|
|
SetIntegerProp(Index, Value);
|
|
end;
|
|
|
|
procedure TOleCtl.SetCompProp(Index: Integer; const Value: Comp);
|
|
var
|
|
Temp: TVarData;
|
|
begin
|
|
Temp.VType := VT_I8;
|
|
Temp.VDouble := Value;
|
|
SetProperty(Index, Temp);
|
|
end;
|
|
|
|
procedure TOleCtl.SetCurrencyProp(Index: Integer; const Value: Currency);
|
|
var
|
|
Temp: TVarData;
|
|
begin
|
|
Temp.VType := varCurrency;
|
|
Temp.VCurrency := Value;
|
|
SetProperty(Index, Temp);
|
|
end;
|
|
|
|
procedure TOleCtl.SetDoubleProp(Index: Integer; const Value: Double);
|
|
var
|
|
Temp: TVarData;
|
|
begin
|
|
Temp.VType := varDouble;
|
|
Temp.VDouble := Value;
|
|
SetProperty(Index, Temp);
|
|
end;
|
|
|
|
procedure TOleCtl.SetIDispatchProp(Index: Integer; const Value: IDispatch);
|
|
var
|
|
Temp: TVarData;
|
|
begin
|
|
Temp.VType := varDispatch;
|
|
Temp.VDispatch := Pointer(Value);
|
|
SetProperty(Index, Temp);
|
|
end;
|
|
|
|
procedure TOleCtl.SetIntegerProp(Index, Value: Integer);
|
|
var
|
|
Temp: TVarData;
|
|
begin
|
|
Temp.VType := varInteger;
|
|
Temp.VInteger := Value;
|
|
SetProperty(Index, Temp);
|
|
end;
|
|
|
|
procedure TOleCtl.SetIUnknownProp(Index: Integer; const Value: IUnknown);
|
|
var
|
|
Temp: TVarData;
|
|
begin
|
|
Temp.VType := VT_UNKNOWN;
|
|
Temp.VUnknown := Pointer(Value);
|
|
SetProperty(Index, Temp);
|
|
end;
|
|
|
|
(*procedure TOleCtl.SetMouseDblClk(const Value: TOnMouse);
|
|
begin
|
|
{$IFDEF EVENTS_DYNAMIC} ProvideUniqueEvents {$ELSE} EV {$ENDIF}
|
|
.fOnMouseDblClk := Value;
|
|
end;*)
|
|
|
|
procedure TOleCtl.SetName(const Value: String);
|
|
var
|
|
OldName: string;
|
|
DispID: Integer;
|
|
begin
|
|
OldName := Name;
|
|
Name := Value; //inherited SetName(Value);
|
|
if FOleControl <> nil then
|
|
begin
|
|
FOleControl.OnAmbientPropertyChange(DISPID_AMBIENT_DISPLAYNAME);
|
|
if FControlData^.Flags and (cfCaption or cfText) <> 0 then
|
|
begin
|
|
if FControlData^.Flags and cfCaption <> 0 then
|
|
DispID := DISPID_CAPTION else
|
|
DispID := DISPID_TEXT;
|
|
if OldName = GetStringProp(DispID) then SetStringProp(DispID, Value);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TOleCtl.SetOleBoolProp(Index: Integer; Value: TOleBool);
|
|
var
|
|
Temp: TVarData;
|
|
begin
|
|
Temp.VType := varBoolean;
|
|
if Value then
|
|
Temp.VBoolean := WordBool(-1) else
|
|
Temp.VBoolean := WordBool(0);
|
|
SetProperty(Index, Temp);
|
|
end;
|
|
|
|
procedure TOleCtl.SetOleDateProp(Index: Integer; const Value: TOleDate);
|
|
var
|
|
Temp: TVarData;
|
|
begin
|
|
Temp.VType := varDate;
|
|
Temp.VDate := Value;
|
|
SetProperty(Index, Temp);
|
|
end;
|
|
|
|
procedure TOleCtl.SetOleEnumProp(Index: Integer; Value: TOleEnum);
|
|
begin
|
|
SetIntegerProp(Index, Value);
|
|
end;
|
|
|
|
procedure TOleCtl.SetOleVariantProp(Index: Integer;
|
|
const Value: OleVariant);
|
|
begin
|
|
SetProperty(Index, TVarData(Value));
|
|
end;
|
|
|
|
procedure TOleCtl.SetOnChar(const Value: TOnChar);
|
|
begin
|
|
{$IFDEF EVENTS_DYNAMIC} ProvideUniqueEvents {$ELSE} EV {$ENDIF}
|
|
.fOnChar := Value;
|
|
end;
|
|
|
|
procedure TOleCtl.SetOnLeave(const Value: TOnEvent);
|
|
begin
|
|
OnExit := Value;
|
|
end;
|
|
|
|
procedure TOleCtl.SetParent(AParent: PControl);
|
|
var
|
|
CS: IOleClientSite;
|
|
X: Integer;
|
|
begin
|
|
inherited Parent := AParent;
|
|
if (AParent <> nil) then
|
|
begin
|
|
try // work around ATL bug
|
|
X := FOleObject.GetClientSite(CS);
|
|
except
|
|
X := -1;
|
|
end;
|
|
if (X <> 0) or (CS = nil) then
|
|
OleCheck(FOleObject.SetClientSite(fOleCtlIntf));
|
|
if FOleControl <> nil then
|
|
FOleControl.OnAmbientPropertyChange(DISPID_UNKNOWN);
|
|
end;
|
|
end;
|
|
|
|
procedure TOleCtl.SetProperty(Index: Integer; const Value: TVarData);
|
|
const
|
|
DispIDArgs: Longint = DISPID_PROPERTYPUT;
|
|
var
|
|
Status, InvKind: Integer;
|
|
DispParams: TDispParams;
|
|
ExcepInfo: TExcepInfo;
|
|
begin
|
|
CreateControl;
|
|
DispParams.rgvarg := @Value;
|
|
DispParams.rgdispidNamedArgs := @DispIDArgs;
|
|
DispParams.cArgs := 1;
|
|
DispParams.cNamedArgs := 1;
|
|
if Value.VType <> varDispatch then
|
|
InvKind := DISPATCH_PROPERTYPUT else
|
|
InvKind := DISPATCH_PROPERTYPUTREF;
|
|
Status := FControlDispatch.Invoke(Index, GUID_NULL, 0,
|
|
InvKind, DispParams, nil, @ExcepInfo, nil);
|
|
if Status <> 0 then DispatchInvokeError(Status, ExcepInfo);
|
|
end;
|
|
|
|
procedure TOleCtl.SetShortIntProp(Index: Integer; Value: Shortint);
|
|
begin
|
|
SetIntegerProp(Index, Value);
|
|
end;
|
|
|
|
procedure TOleCtl.SetSingleProp(Index: Integer; const Value: Single);
|
|
var
|
|
Temp: TVarData;
|
|
begin
|
|
Temp.VType := varSingle;
|
|
Temp.VSingle := Value;
|
|
SetProperty(Index, Temp);
|
|
end;
|
|
|
|
procedure TOleCtl.SetSmallintProp(Index: Integer; Value: Smallint);
|
|
var
|
|
Temp: TVarData;
|
|
begin
|
|
Temp.VType := varSmallint;
|
|
Temp.VSmallint := Value;
|
|
SetProperty(Index, Temp);
|
|
end;
|
|
|
|
procedure TOleCtl.SetStringProp(Index: Integer; const Value: string);
|
|
var
|
|
Temp: TVarData;
|
|
begin
|
|
Temp.VType := varOleStr;
|
|
Temp.VOleStr := StringToOleStr(Value);
|
|
try
|
|
SetProperty(Index, Temp);
|
|
finally
|
|
SysFreeString(Temp.VOleStr);
|
|
end;
|
|
end;
|
|
|
|
procedure TOleCtl.SetTColorProp(Index: Integer; Value: TColor);
|
|
begin
|
|
SetIntegerProp(Index, Value);
|
|
end;
|
|
|
|
procedure TOleCtl.SetTDateTimeProp(Index: Integer; const Value: TDateTime);
|
|
var
|
|
Temp: TVarData;
|
|
begin
|
|
Temp.VType := varDate;
|
|
Temp.VDate := Value;
|
|
SetProperty(Index, Temp);
|
|
end;
|
|
|
|
procedure TOleCtl.SetTFontProp(Index: Integer; Value: PGraphicTool);
|
|
{var
|
|
I: Integer;
|
|
F: TFont;
|
|
Temp: IFontDisp;}
|
|
begin
|
|
{for I := 0 to FFonts.Count-1 do
|
|
if FControlData^.FontIDs^[I] = Index then
|
|
begin
|
|
F := TFont(FFonts[I]);
|
|
F.Assign(Value);
|
|
if F.FontAdapter = nil then
|
|
begin
|
|
GetOleFont(F, Temp);
|
|
SetIDispatchProp(Index, Temp);
|
|
end;
|
|
end;}
|
|
//TODO: implement TFont property later
|
|
end;
|
|
|
|
procedure TOleCtl.SetTOleEnumProp(Index: Integer; Value: TOleEnum);
|
|
begin
|
|
SetIntegerProp(Index, Value);
|
|
end;
|
|
|
|
procedure TOleCtl.SetUIActive(Active: Boolean);
|
|
var
|
|
Form: POleCtl; // declare it as POleCtl, though it is only PControl
|
|
// - to access its protected fields
|
|
begin
|
|
Form := POleCtl( ParentForm );
|
|
if Form <> nil then
|
|
if Active then
|
|
begin
|
|
{if (Form.ActiveOleControl <> nil) and
|
|
(Form.ActiveOleControl <> Self) then
|
|
Form.ActiveOleControl.Perform(CM_UIDEACTIVATE, 0, 0);
|
|
Form.ActiveOleControl := Self;}
|
|
if (Form.DF.fCurrentControl <> nil) and
|
|
(Form.DF.fCurrentControl <> @Self) then
|
|
Form.DF.fCurrentControl.Perform(CM_UIDEACTIVATE, 0, 0);
|
|
Form.DF.fCurrentControl := @Self;
|
|
end else
|
|
if Form.DF.fCurrentControl = @Self then
|
|
Form.DF.fCurrentControl := nil;
|
|
end;
|
|
|
|
procedure TOleCtl.SetVariantProp(Index: Integer; const Value: Variant);
|
|
begin
|
|
SetOleVariantProp(Index, Value);
|
|
end;
|
|
|
|
procedure TOleCtl.SetWideStringProp(Index: Integer;
|
|
const Value: WideString);
|
|
var
|
|
Temp: TVarData;
|
|
begin
|
|
Temp.VType := varOleStr;
|
|
if Value <> '' then
|
|
Temp.VOleStr := PWideChar(Value)
|
|
else
|
|
Temp.VOleStr := nil;
|
|
SetProperty(Index, Temp);
|
|
end;
|
|
|
|
procedure TOleCtl.SetWordBoolProp(Index: Integer; Value: WordBool);
|
|
var
|
|
Temp: TVarData;
|
|
begin
|
|
Temp.VType := varBoolean;
|
|
if Value then
|
|
Temp.VBoolean := WordBool(-1) else
|
|
Temp.VBoolean := WordBool(0);
|
|
SetProperty(Index, Temp);
|
|
end;
|
|
|
|
procedure TOleCtl.SetWordProp(Index: Integer; Value: Word);
|
|
begin
|
|
SetIntegerProp(Index, Value);
|
|
end;
|
|
|
|
procedure TOleCtl.StandardEvent(DispID: TDispID; var Params: TDispParams);
|
|
type
|
|
PVarDataList = ^TVarDataList;
|
|
TVarDataList = array[0..3] of TVarData;
|
|
const
|
|
{ShiftMap: array[0..7] of TShiftState = (
|
|
[],
|
|
[ssShift],
|
|
[ssCtrl],
|
|
[ssShift, ssCtrl],
|
|
[ssAlt],
|
|
[ssShift, ssAlt],
|
|
[ssCtrl, ssAlt],
|
|
[ssShift, ssCtrl, ssAlt]);
|
|
MouseMap: array[0..7] of TShiftState = (
|
|
[],
|
|
[ssLeft],
|
|
[ssRight],
|
|
[ssLeft, ssRight],
|
|
[ssMiddle],
|
|
[ssLeft, ssMiddle],
|
|
[ssRight, ssMiddle],
|
|
[ssLeft, ssRight, ssMiddle]);}
|
|
ShiftMap: array[0..7] of DWord = (
|
|
0,
|
|
MK_SHIFT,
|
|
MK_CONTROL,
|
|
MK_SHIFT or MK_CONTROL,
|
|
MK_ALT,
|
|
MK_SHIFT or MK_ALT,
|
|
MK_CONTROL or MK_ALT,
|
|
MK_SHIFT or MK_CONTROL or MK_ALT);
|
|
MouseMap: array[0..7] of DWORD = (
|
|
0,
|
|
MK_LBUTTON,
|
|
MK_RBUTTON,
|
|
MK_LBUTTON or MK_RBUTTON,
|
|
MK_MBUTTON,
|
|
MK_LBUTTON or MK_MBUTTON,
|
|
MK_RBUTTON or MK_MBUTTON,
|
|
MK_LBUTTON or MK_RBUTTON or MK_MBUTTON);
|
|
ButtonMap: array[0..7] of TMouseButton = (
|
|
mbLeft, mbLeft, mbRight, mbLeft, mbMiddle, mbLeft, mbRight, mbLeft);
|
|
var
|
|
Args: PVarDataList;
|
|
AShift: DWORD;
|
|
Button: TMouseButton;
|
|
X, Y: Integer;
|
|
Key: Longint;
|
|
Ch: KOLChar;
|
|
begin
|
|
Args := PVarDataList(Params.rgvarg);
|
|
try
|
|
case DispID of
|
|
DISPID_CLICK:
|
|
Click;
|
|
DISPID_DBLCLICK:
|
|
DblClk;
|
|
DISPID_KEYDOWN, DISPID_KEYUP:
|
|
if Params.cArgs >= 2 then
|
|
begin
|
|
Key := Variant(Args^[1]);
|
|
X := Variant(Args^[0]);
|
|
case DispID of
|
|
DISPID_KEYDOWN: KeyDown(Key, X);
|
|
DISPID_KEYUP: KeyUp(Key, X);
|
|
end;
|
|
if ((Args^[1].vType and varByRef) <> 0) then
|
|
Word(Args^[1].VPointer^) := Key;
|
|
end;
|
|
DISPID_KEYPRESS:
|
|
if Params.cArgs > 0 then
|
|
begin
|
|
Ch := KOLChar(Integer(Variant(Args^[0])));
|
|
KeyPress(Ch);
|
|
if ((Args^[0].vType and varByRef) <> 0) then
|
|
KOLChar(Args^[0].VPointer^) := Ch;
|
|
end;
|
|
{DISPID_KEYPRESS:
|
|
if Params.cArgs > 0 then
|
|
begin
|
|
Ch := KOLChar(Integer(Variant(Args^[0])));
|
|
KeyPress(Ch);
|
|
if ((Args^[0].vType and varByRef) <> 0) then
|
|
KOLChar(Args^[0].VPointer^) := Ch;
|
|
end;}
|
|
DISPID_MOUSEDOWN, DISPID_MOUSEMOVE, DISPID_MOUSEUP:
|
|
if Params.cArgs >= 4 then
|
|
begin
|
|
X := Integer(Variant(Args^[3])) and 7;
|
|
Y := Integer(Variant(Args^[2])) and 7;
|
|
Button := ButtonMap[X];
|
|
AShift := ShiftMap[Y] + MouseMap[X];
|
|
X := Variant(Args^[1]);
|
|
Y := Variant(Args^[0]);
|
|
case DispID of
|
|
DISPID_MOUSEDOWN:
|
|
MouseDown(Button, AShift, X, Y);
|
|
DISPID_MOUSEMOVE:
|
|
MouseMove(AShift, X, Y);
|
|
DISPID_MOUSEUP:
|
|
MouseUp(Button, AShift, X, Y);
|
|
end;
|
|
end;
|
|
end;
|
|
except
|
|
DoHandleException;
|
|
end;
|
|
end;
|
|
|
|
{$IFNDEF _D2orD3}
|
|
{ TServerEventDispatch }
|
|
constructor TServerEventDispatch.Create(Server: TOleServer);
|
|
begin
|
|
FServer := Server;
|
|
InternalRefCount := 1;
|
|
end;
|
|
|
|
{ TServerEventDispatch.IUnknown }
|
|
function TServerEventDispatch.QueryInterface(const IID: TGUID; out Obj): HResult;
|
|
begin
|
|
if GetInterface(IID, Obj) then
|
|
begin
|
|
Result := S_OK;
|
|
Exit;
|
|
end;
|
|
if IsEqualIID(IID, FServer.FServerData^.EventIID) then
|
|
begin
|
|
GetInterface(IDispatch, Obj);
|
|
Result := S_OK;
|
|
Exit;
|
|
end;
|
|
Result := E_NOINTERFACE;
|
|
end;
|
|
|
|
function TServerEventDispatch._AddRef: Integer;
|
|
begin
|
|
if FServer <> nil then FServer._AddRef;
|
|
InternalRefCount := InternalRefCount + 1;
|
|
Result := InternalRefCount;
|
|
end;
|
|
|
|
function TServerEventDispatch._Release: Integer;
|
|
begin
|
|
if FServer <> nil then FServer._Release;
|
|
InternalRefCount := InternalRefCount -1;
|
|
Result := InternalRefCount;
|
|
end;
|
|
|
|
{ TServerEventDispatch.IDispatch }
|
|
function TServerEventDispatch.GetTypeInfoCount(out Count: Integer): HResult;
|
|
begin
|
|
Count := 0;
|
|
Result:= S_OK;
|
|
end;
|
|
|
|
function TServerEventDispatch.GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult;
|
|
begin
|
|
Pointer(TypeInfo) := nil;
|
|
Result := E_NOTIMPL;
|
|
end;
|
|
|
|
function TServerEventDispatch.GetIDsOfNames(const IID: TGUID; Names: Pointer;
|
|
NameCount, LocaleID: Integer; DispIDs: Pointer): HResult;
|
|
begin
|
|
Result := E_NOTIMPL;
|
|
end;
|
|
|
|
function TServerEventDispatch.Invoke(DispID: Integer; const IID: TGUID;
|
|
LocaleID: Integer; Flags: Word; var Params;
|
|
VarResult, ExcepInfo, ArgErr: Pointer): HResult;
|
|
var
|
|
ParamCount, I: integer;
|
|
VarArray : TVariantArray;
|
|
begin
|
|
// Get parameter count
|
|
ParamCount := TDispParams(Params).cArgs;
|
|
// Set our array to appropriate length
|
|
SetLength(VarArray, ParamCount);
|
|
// Copy over data
|
|
for I := Low(VarArray) to High(VarArray) do
|
|
VarArray[High(VarArray)-I] := OleVariant(TDispParams(Params).rgvarg^[I]);
|
|
// Invoke Server proxy class
|
|
if FServer <> nil then FServer.InvokeEvent(DispID, VarArray);
|
|
// Clean array
|
|
SetLength(VarArray, 0);
|
|
// Pascal Events return 'void' - so assume success!
|
|
Result := S_OK;
|
|
end;
|
|
|
|
function TServerEventDispatch.ServerDisconnect : Boolean;
|
|
begin
|
|
FServer := nil;
|
|
if FServer <> nil then
|
|
Result := false
|
|
else Result := true;
|
|
end;
|
|
|
|
{TOleServer}
|
|
constructor TOleServer.Create; //(AOwner: TComponent);
|
|
begin
|
|
inherited; // Create(AOwner);
|
|
// Allow derived class to initialize ServerData structure pointer
|
|
InitServerData;
|
|
// Make sure derived class set ServerData pointer to some valid structure
|
|
Assert(FServerData <> nil);
|
|
// Increment instance count (not used currently)
|
|
Inc(FServerData^.InstanceCount);
|
|
// Create Event Dispatch Handler
|
|
FEventDispatch := TServerEventDispatch.Create(Self);
|
|
end;
|
|
|
|
destructor TOleServer.Destroy;
|
|
begin
|
|
// Disconnect from the Server (NOTE: Disconnect must handle case when we're no longer connected)
|
|
Disconnect;
|
|
// Free Events dispatcher
|
|
FEventDispatch.ServerDisconnect;
|
|
if (FEventDispatch._Release = 0) then FEventDispatch.Free;
|
|
// Decrement refcount
|
|
Dec(FServerData^.InstanceCount);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TOleServer.Loaded;
|
|
begin
|
|
{inherited Loaded;}
|
|
|
|
// Load Server if user requested 'AutoConnect' and we're not in Design mode
|
|
{if not (csDesigning in ComponentState) then}
|
|
if AutoConnect then
|
|
Connect;
|
|
end;
|
|
|
|
procedure TOleServer.InvokeEvent(DispID: TDispID; var Params: TVariantArray);
|
|
begin
|
|
// To be overriden in derived classes to do dispatching
|
|
end;
|
|
|
|
function TOleServer.GetServer: IUnknown;
|
|
var
|
|
HR: HResult;
|
|
ErrorStr: string;
|
|
begin
|
|
case ConnectKind of
|
|
ckNewInstance:
|
|
Result := CreateComObject(FServerData^.ClassId);
|
|
|
|
ckRunningInstance:
|
|
begin
|
|
HR := GetActiveObject(FServerData^.ClassId, nil, Result);
|
|
if not Succeeded(HR) then
|
|
begin
|
|
ErrorStr := Format(sNoRunningObject, [ClassIDToProgID(FServerData^.ClassId),
|
|
GuidToString(FServerData^.ClassId)]);
|
|
raise EOleSysError.Create( e_Ole, ErrorStr {, HR, 0} );
|
|
end;
|
|
end;
|
|
|
|
ckRunningOrNew:
|
|
if not Succeeded(GetActiveObject(FServerData^.ClassId, nil, Result)) then
|
|
Result := CreateComObject(FServerData^.ClassId);
|
|
|
|
ckRemote:
|
|
{Highly inefficient: requires at least two round trips - GetClassObject + QI}
|
|
Result := CreateRemoteComObject(RemoteMachineName, FServerData^.ClassID);
|
|
end;
|
|
end;
|
|
|
|
procedure TOleServer.ConnectEvents(const Obj: IUnknown);
|
|
begin
|
|
KOLComObj.InterfaceConnect(Obj, FServerData^.EventIID, FEventDispatch, FEventsConnection);
|
|
end;
|
|
|
|
procedure TOleServer.DisconnectEvents(const Obj: Iunknown);
|
|
begin
|
|
KOLComObj.InterfaceDisconnect(Obj, FServerData^.EventIID, FEventsConnection);
|
|
end;
|
|
|
|
function TOleServer.GetConnectKind: TConnectKind;
|
|
begin
|
|
// Should the setting of a RemoteMachine name override the Connection Kind ??
|
|
if RemoteMachineName <> '' then
|
|
Result := ckRemote
|
|
else
|
|
Result := FConnectKind;
|
|
end;
|
|
|
|
procedure TOleServer.SetConnectKind(cK: TConnectKind);
|
|
begin
|
|
// Should we validate that we have a RemoteMachineName for ckRemote ??
|
|
FConnectKind := cK;
|
|
end;
|
|
|
|
function TOleServer.GetAutoConnect: Boolean;
|
|
begin
|
|
// If user wants to provide the interface to connect to, then we won't
|
|
// 'automatically' connect to a server.
|
|
if ConnectKind = ckAttachToInterface then
|
|
Result := False
|
|
else
|
|
Result := FAutoConnect;
|
|
end;
|
|
|
|
procedure TOleServer.SetAutoConnect(flag: Boolean);
|
|
begin
|
|
FAutoConnect := flag;
|
|
end;
|
|
|
|
{ TOleServer.IUnknown }
|
|
function TOleServer.QueryInterface(const IID: TGUID; out Obj): HResult;
|
|
begin
|
|
if GetInterface(IID, Obj) then
|
|
Result := S_OK
|
|
else
|
|
Result := E_NOINTERFACE;
|
|
end;
|
|
|
|
function TOleServer._AddRef: Integer;
|
|
begin
|
|
Inc(FRefCount);
|
|
Result := FRefCount;
|
|
end;
|
|
|
|
function TOleServer._Release: Integer;
|
|
begin
|
|
Dec(FRefCount);
|
|
Result := FRefCount;
|
|
end;
|
|
{$ENDIF _D2orD3}
|
|
|
|
{ TEventDispatch }
|
|
|
|
constructor TEventDispatch.Create(Control: POleCtl);
|
|
begin
|
|
FControl := Control;
|
|
end;
|
|
|
|
{ TEventDispatch.IUnknown }
|
|
|
|
function TEventDispatch.QueryInterface(const IID: TGUID; out Obj): HResult;
|
|
begin
|
|
if GetInterface(IID, Obj) then
|
|
begin
|
|
Result := S_OK;
|
|
Exit;
|
|
end;
|
|
if IsEqualIID(IID, FControl.FControlData^.EventIID) then
|
|
begin
|
|
GetInterface(IDispatch, Obj);
|
|
Result := S_OK;
|
|
Exit;
|
|
end;
|
|
Result := E_NOINTERFACE;
|
|
end;
|
|
|
|
function TEventDispatch._AddRef: Integer;
|
|
begin
|
|
Result := FControl.fOleCtlIntf._AddRef;
|
|
end;
|
|
|
|
function TEventDispatch._Release: Integer;
|
|
begin
|
|
Result := FControl.fOleCtlIntf._Release;
|
|
end;
|
|
|
|
{ TEventDispatch.IDispatch }
|
|
|
|
function TEventDispatch.GetTypeInfoCount(out Count: Integer): HResult;
|
|
begin
|
|
Count := 0;
|
|
Result := S_OK;
|
|
end;
|
|
|
|
function TEventDispatch.GetTypeInfo(Index, LocaleID: Integer;
|
|
out TypeInfo): HResult;
|
|
begin
|
|
Pointer(TypeInfo) := nil;
|
|
Result := E_NOTIMPL;
|
|
end;
|
|
|
|
function TEventDispatch.GetIDsOfNames(const IID: TGUID; Names: Pointer;
|
|
NameCount, LocaleID: Integer; DispIDs: Pointer): HResult;
|
|
begin
|
|
Result := E_NOTIMPL;
|
|
end;
|
|
|
|
function TEventDispatch.Invoke(DispID: Integer; const IID: TGUID;
|
|
LocaleID: Integer; Flags: Word; var Params;
|
|
VarResult, ExcepInfo, ArgErr: Pointer): HResult;
|
|
begin
|
|
if (DispID >= DISPID_MOUSEUP) and (DispID <= DISPID_CLICK) then
|
|
FControl.StandardEvent(DispID, TDispParams(Params)) else
|
|
FControl.InvokeEvent(DispID, TDispParams(Params));
|
|
Result := S_OK;
|
|
end;
|
|
|
|
{ TOleCtlIntf }
|
|
|
|
function TOleCtlIntf._AddRef: Integer;
|
|
begin
|
|
//{$IFDEF _D2orD3}
|
|
//Result := inherited _AddRef;
|
|
//{$ELSE}
|
|
Inc(FRefCount);
|
|
Result := FRefCount;
|
|
//{$ENDIF}
|
|
end;
|
|
|
|
function TOleCtlIntf._Release: Integer;
|
|
begin
|
|
//{$IFDEF _D2orD3}
|
|
//Result := inherited _Release;
|
|
//{$ELSE}
|
|
Dec(FRefCount);
|
|
Result := FRefCount;
|
|
//{$ENDIF}
|
|
end;
|
|
|
|
function TOleCtlIntf.CanInPlaceActivate: HResult;
|
|
begin
|
|
Result := S_OK;
|
|
end;
|
|
|
|
function TOleCtlIntf.ContextSensitiveHelp(fEnterMode: BOOL): HResult;
|
|
begin
|
|
Result := S_OK;
|
|
end;
|
|
|
|
function TOleCtlIntf.DeactivateAndUndo: HResult;
|
|
begin
|
|
fOleCtl.FOleInPlaceObject.UIDeactivate;
|
|
Result := S_OK;
|
|
end;
|
|
|
|
function TOleCtlIntf.DiscardUndoState: HResult;
|
|
begin
|
|
Result := E_NOTIMPL;
|
|
end;
|
|
|
|
function TOleCtlIntf.EnableModeless(fEnable: BOOL): HResult;
|
|
begin
|
|
Result := S_OK;
|
|
end;
|
|
|
|
function TOleCtlIntf.GetBorder(out rectBorder: TRect): HResult;
|
|
begin
|
|
Result := INPLACE_E_NOTOOLSPACE;
|
|
end;
|
|
|
|
function TOleCtlIntf.GetContainer(out container: IOleContainer): HResult;
|
|
begin
|
|
Result := E_NOINTERFACE;
|
|
end;
|
|
|
|
function TOleCtlIntf.GetExtendedControl(out disp: IDispatch): HResult;
|
|
begin
|
|
Result := E_NOTIMPL;
|
|
end;
|
|
|
|
function TOleCtlIntf.GetIDsOfNames(const IID: TGUID; Names: Pointer;
|
|
NameCount, LocaleID: Integer; DispIDs: Pointer): HResult;
|
|
begin
|
|
Result := E_NOTIMPL;
|
|
end;
|
|
|
|
function TOleCtlIntf.GetMoniker(dwAssign, dwWhichMoniker: Integer;
|
|
out mk: IMoniker): HResult;
|
|
begin
|
|
Result := E_NOTIMPL;
|
|
end;
|
|
|
|
function TOleCtlIntf.GetTypeInfo(Index, LocaleID: Integer;
|
|
out TypeInfo): HResult;
|
|
begin
|
|
Pointer(TypeInfo) := nil;
|
|
Result := E_NOTIMPL;
|
|
end;
|
|
|
|
function TOleCtlIntf.GetTypeInfoCount(out Count: Integer): HResult;
|
|
begin
|
|
Count := 0;
|
|
Result := S_OK;
|
|
end;
|
|
|
|
function TOleCtlIntf.GetWindowContext(out frame: IOleInPlaceFrame;
|
|
out doc: IOleInPlaceUIWindow; out rcPosRect, rcClipRect: TRect;
|
|
out frameInfo: TOleInPlaceFrameInfo): HResult;
|
|
begin
|
|
frame := Self;
|
|
doc := nil;
|
|
rcPosRect := fOleCtl.BoundsRect;
|
|
rcClipRect := MakeRect( 0, 0, 32767, 32767 );
|
|
with frameInfo do
|
|
begin
|
|
fMDIApp := False;
|
|
hWndFrame := fOleCtl.ParentForm.GetWindowHandle;
|
|
//GetTopParentHandle;
|
|
// now it is not possible to make alien window to be parent for KOL window
|
|
hAccel := 0;
|
|
cAccelEntries := 0;
|
|
end;
|
|
Result := S_OK;
|
|
end;
|
|
|
|
function TOleCtlIntf.InsertMenus(hmenuShared: HMenu;
|
|
var menuWidths: TOleMenuGroupWidths): HResult;
|
|
{var
|
|
Menu: TMainMenu;}
|
|
begin
|
|
{Menu := GetMainMenu;
|
|
if Menu <> nil then
|
|
Menu.PopulateOle2Menu(hmenuShared, [0, 2, 4], menuWidths.width);}
|
|
//TODO: implement menu populate
|
|
Result := S_OK;
|
|
end;
|
|
|
|
function TOleCtlIntf.Invoke(DispID: Integer; const IID: TGUID;
|
|
LocaleID: Integer; Flags: Word; var Params; VarResult, ExcepInfo,
|
|
ArgErr: Pointer): HResult;
|
|
{var
|
|
F: PGraphicTool;}
|
|
begin
|
|
if (Flags and DISPATCH_PROPERTYGET <> 0) and (VarResult <> nil) then
|
|
begin
|
|
Result := S_OK;
|
|
case DispID of
|
|
DISPID_AMBIENT_BACKCOLOR:
|
|
PVariant(VarResult)^ := fOleCtl.Color;
|
|
DISPID_AMBIENT_DISPLAYNAME:
|
|
PVariant(VarResult)^ := StringToVarOleStr( fOleCtl.Name );
|
|
DISPID_AMBIENT_FONT:
|
|
begin
|
|
{if (fOleCtl.Parent <> nil) and fOleCtl.ParentFont then
|
|
F := Parent.Font // TOleControl(Parent).Font
|
|
else
|
|
F := Font;
|
|
PVariant(VarResult)^ := FontToOleFont(F);}
|
|
//TODO: implement Font later
|
|
end;
|
|
DISPID_AMBIENT_FORECOLOR:
|
|
PVariant(VarResult)^ := fOleCtl.fTextColor; // Font.Color;
|
|
DISPID_AMBIENT_LOCALEID:
|
|
PVariant(VarResult)^ := Integer(GetUserDefaultLCID);
|
|
DISPID_AMBIENT_MESSAGEREFLECT:
|
|
PVariant(VarResult)^ := True;
|
|
DISPID_AMBIENT_USERMODE:
|
|
PVariant(VarResult)^ := TRUE; // not (csDesigning in ComponentState);
|
|
DISPID_AMBIENT_UIDEAD:
|
|
PVariant(VarResult)^ := FALSE; // csDesigning in ComponentState;
|
|
DISPID_AMBIENT_SHOWGRABHANDLES:
|
|
PVariant(VarResult)^ := False;
|
|
DISPID_AMBIENT_SHOWHATCHING:
|
|
PVariant(VarResult)^ := False;
|
|
DISPID_AMBIENT_SUPPORTSMNEMONICS:
|
|
PVariant(VarResult)^ := True;
|
|
DISPID_AMBIENT_AUTOCLIP:
|
|
PVariant(VarResult)^ := True;
|
|
else
|
|
Result := DISP_E_MEMBERNOTFOUND;
|
|
end;
|
|
end else
|
|
Result := DISP_E_MEMBERNOTFOUND;
|
|
end;
|
|
|
|
function TOleCtlIntf.LockInPlaceActive(fLock: BOOL): HResult;
|
|
begin
|
|
Result := E_NOTIMPL;
|
|
end;
|
|
|
|
function TOleCtlIntf.OleControlSite_TranslateAccelerator(msg: PMsg;
|
|
grfModifiers: Integer): HResult;
|
|
begin
|
|
Result := E_NOTIMPL;
|
|
end;
|
|
|
|
function TOleCtlIntf.OleInPlaceFrame_GetWindow(out wnd: HWnd): HResult;
|
|
begin
|
|
wnd := fOleCtl.ParentForm.GetWindowHandle; // GetTopParentHandle;
|
|
Result := S_OK;
|
|
end;
|
|
|
|
function TOleCtlIntf.OleInPlaceFrame_TranslateAccelerator(var msg: Windows.TMsg;
|
|
wID: Word): HResult;
|
|
begin
|
|
Result := S_FALSE;
|
|
end;
|
|
|
|
function TOleCtlIntf.OleInPlaceSite_GetWindow(out wnd: HWnd): HResult;
|
|
begin
|
|
Result := S_OK;
|
|
wnd := fOleCtl.ParentWindow;
|
|
if wnd = 0 then Result := E_FAIL;
|
|
end;
|
|
|
|
function TOleCtlIntf.OnChanged(dispid: TDispID): HResult;
|
|
begin
|
|
try
|
|
case dispid of
|
|
DISPID_BACKCOLOR:
|
|
if not fOleCtl.FUpdatingColor then
|
|
begin
|
|
fOleCtl.FUpdatingColor := True;
|
|
try
|
|
fOleCtl.fColor := fOleCtl.GetIntegerProp(DISPID_BACKCOLOR);
|
|
finally
|
|
fOleCtl.FUpdatingColor := False;
|
|
end;
|
|
end;
|
|
DISPID_ENABLED:
|
|
if not fOleCtl.FUpdatingEnabled then
|
|
begin
|
|
fOleCtl.FUpdatingEnabled := True;
|
|
try
|
|
fOleCtl.Enabled := fOleCtl.GetWordBoolProp(DISPID_ENABLED);
|
|
finally
|
|
fOleCtl.FUpdatingEnabled := False;
|
|
end;
|
|
end;
|
|
DISPID_FONT:
|
|
if not fOleCtl.FUpdatingFont then
|
|
begin
|
|
fOleCtl.FUpdatingFont := True;
|
|
try
|
|
//OleFontToFont(GetVariantProp(DISPID_FONT), Font);
|
|
// font - implement later
|
|
finally
|
|
fOleCtl.FUpdatingFont := False;
|
|
end;
|
|
end;
|
|
DISPID_FORECOLOR:
|
|
if not fOleCtl.FUpdatingFont then
|
|
begin
|
|
fOleCtl.FUpdatingFont := True;
|
|
try
|
|
fOleCtl.fTextColor := fOleCtl.GetIntegerProp(DISPID_FORECOLOR);
|
|
//Font.Color := GetIntegerProp(DISPID_FORECOLOR);
|
|
finally
|
|
fOleCtl.FUpdatingFont := False;
|
|
end;
|
|
end;
|
|
end;
|
|
except // control sent us a notification for a dispid it doesn't have.
|
|
//on EOleError do ;
|
|
end;
|
|
Result := S_OK;
|
|
end;
|
|
|
|
function TOleCtlIntf.OnControlInfoChanged: HResult;
|
|
begin
|
|
Result := E_NOTIMPL;
|
|
end;
|
|
|
|
function TOleCtlIntf.OnFocus(fGotFocus: BOOL): HResult;
|
|
begin
|
|
Result := E_NOTIMPL;
|
|
end;
|
|
|
|
function TOleCtlIntf.OnInPlaceActivate: HResult;
|
|
begin
|
|
fOleCtl.FOleObject.QueryInterface( IOleInPlaceObject,
|
|
fOleCtl.FOleInPlaceObject);
|
|
fOleCtl.FOleObject.QueryInterface( IOleInPlaceActiveObject,
|
|
fOleCtl.FOleInPlaceActiveObject);
|
|
Result := S_OK;
|
|
end;
|
|
|
|
function TOleCtlIntf.OnInPlaceDeactivate: HResult;
|
|
begin
|
|
fOleCtl.FOleInPlaceActiveObject := nil;
|
|
fOleCtl.FOleInPlaceObject := nil;
|
|
Result := S_OK;
|
|
end;
|
|
|
|
function TOleCtlIntf.OnPosRectChange(const rcPosRect: TRect): HResult;
|
|
begin
|
|
fOleCtl.FOleInPlaceObject.SetObjectRects(rcPosRect, MakeRect(0, 0, 32767, 32767));
|
|
Result := S_OK;
|
|
end;
|
|
|
|
function TOleCtlIntf.OnRequestEdit(dispid: TDispID): HResult;
|
|
begin
|
|
Result := S_OK;
|
|
end;
|
|
|
|
function TOleCtlIntf.OnShowWindow(fShow: BOOL): HResult;
|
|
begin
|
|
Result := S_OK;
|
|
end;
|
|
|
|
function TOleCtlIntf.OnUIActivate: HResult;
|
|
begin
|
|
fOleCtl.SetUIActive(True);
|
|
Result := S_OK;
|
|
end;
|
|
|
|
function TOleCtlIntf.OnUIDeactivate(fUndoable: BOOL): HResult;
|
|
begin
|
|
SetMenu(0, 0, 0);
|
|
fOleCtl.SetUIActive(False);
|
|
Result := S_OK;
|
|
end;
|
|
|
|
function TOleCtlIntf.PostMessageFilter(wnd: HWnd; msg, wp, lp: Integer;
|
|
out res: Integer; Cookie: Integer): HResult;
|
|
begin
|
|
Result := S_OK;
|
|
end;
|
|
|
|
function TOleCtlIntf.PreMessageFilter(wnd: HWnd; msg, wp, lp: Integer;
|
|
out res, Cookie: Integer): HResult;
|
|
begin
|
|
Result := S_OK;
|
|
end;
|
|
|
|
function TOleCtlIntf.QueryInterface(const IID: TGUID; out Obj): HResult;
|
|
begin
|
|
if GetInterface(IID, Obj) then Result := S_OK else Result := E_NOINTERFACE;
|
|
end;
|
|
|
|
function TOleCtlIntf.RemoveMenus(hmenuShared: HMenu): HResult;
|
|
begin
|
|
while GetMenuItemCount(hmenuShared) > 0 do
|
|
RemoveMenu(hmenuShared, 0, MF_BYPOSITION);
|
|
Result := S_OK;
|
|
end;
|
|
|
|
function TOleCtlIntf.RequestBorderSpace(
|
|
const borderwidths: TRect): HResult;
|
|
begin
|
|
Result := INPLACE_E_NOTOOLSPACE;
|
|
end;
|
|
|
|
function TOleCtlIntf.RequestNewObjectLayout: HResult;
|
|
var
|
|
Extent: TPoint;
|
|
W, H: Integer;
|
|
DC: HDC;
|
|
PixelsPerInch: Integer;
|
|
begin
|
|
Result := fOleCtl.FOleObject.GetExtent(DVASPECT_CONTENT, Extent);
|
|
if Result <> S_OK then Exit;
|
|
|
|
W := fOleCtl.Width;
|
|
H := fOleCtl.Height;
|
|
if (W = 0) or (H = 0) then
|
|
begin
|
|
DC := GetDC(0);
|
|
PixelsPerInch := GetDeviceCaps(DC, LOGPIXELSY);
|
|
ReleaseDC(0, DC);
|
|
|
|
W := MulDiv(Extent.X, PixelsPerInch, 2540);
|
|
H := MulDiv(Extent.Y, PixelsPerInch, 2540);
|
|
if (fOleCtl.FMiscStatus and OLEMISC_INVISIBLEATRUNTIME <> 0) and
|
|
(fOleCtl.FOleControl = nil) then
|
|
begin
|
|
if W > 32 then W := 32;
|
|
if H > 32 then H := 32;
|
|
end;
|
|
end;
|
|
fOleCtl.SetBoundsRect( MakeRect( fOleCtl.Left, fOleCtl.Top,
|
|
fOleCtl.Left + W, fOleCtl.Top + H ) );
|
|
end;
|
|
|
|
function TOleCtlIntf.SaveObject: HResult;
|
|
begin
|
|
Result := S_OK;
|
|
end;
|
|
|
|
function TOleCtlIntf.Scroll(scrollExtent: TPoint): HResult;
|
|
begin
|
|
Result := E_NOTIMPL;
|
|
end;
|
|
|
|
function TOleCtlIntf.SetActiveObject(
|
|
const activeObject: IOleInPlaceActiveObject;
|
|
pszObjName: POleStr): HResult;
|
|
begin
|
|
Result := S_OK;
|
|
end;
|
|
|
|
function TOleCtlIntf.SetBorderSpace(pborderwidths: PRect): HResult;
|
|
begin
|
|
Result := E_NOTIMPL;
|
|
end;
|
|
|
|
function TOleCtlIntf.SetMenu(hmenuShared, holemenu: HMenu;
|
|
hwndActiveObject: HWnd): HResult;
|
|
var
|
|
Menu: HMenu;
|
|
begin
|
|
Menu := fOleCtl.GetMainMenu;
|
|
Result := S_OK;
|
|
if Menu <> 0 then
|
|
begin
|
|
//Menu.SetOle2MenuHandle(hmenuShared);
|
|
Result := OleSetMenuDescriptor( holemenu,
|
|
fOleCtl.ParentForm.GetWindowHandle,
|
|
hwndActiveObject, nil, nil);
|
|
end;
|
|
end;
|
|
|
|
function TOleCtlIntf.SetStatusText(pszStatusText: POleStr): HResult;
|
|
begin
|
|
Result := S_OK;
|
|
end;
|
|
|
|
function TOleCtlIntf.ShowObject: HResult;
|
|
begin
|
|
fOleCtl.HookControlWndProc;
|
|
Result := S_OK;
|
|
end;
|
|
|
|
function TOleCtlIntf.ShowPropertyFrame: HResult;
|
|
begin
|
|
Result := E_NOTIMPL;
|
|
end;
|
|
|
|
function TOleCtlIntf.TransformCoords(var ptlHimetric: TPoint;
|
|
var ptfContainer: TPointF; flags: Integer): HResult;
|
|
var DC: HDC;
|
|
PixelsPerInch: Integer;
|
|
begin
|
|
DC := GetDC(0);
|
|
PixelsPerInch := GetDeviceCaps(DC, LOGPIXELSY);
|
|
ReleaseDC(0, DC);
|
|
|
|
if flags and XFORMCOORDS_HIMETRICTOCONTAINER <> 0 then
|
|
begin
|
|
ptfContainer.X := MulDiv(ptlHimetric.X, PixelsPerInch, 2540);
|
|
ptfContainer.Y := MulDiv(ptlHimetric.Y, PixelsPerInch, 2540);
|
|
end else
|
|
begin
|
|
ptlHimetric.X := Integer(Round(ptfContainer.X * 2540 / PixelsPerInch));
|
|
ptlHimetric.Y := Integer(Round(ptfContainer.Y * 2540 / PixelsPerInch));
|
|
end;
|
|
Result := S_OK;
|
|
end;
|
|
|
|
constructor TOleCtlIntf.Create;
|
|
begin
|
|
inherited;
|
|
end;
|
|
|
|
|
|
end.
|