📄 axctrls.pas
字号:
if (E is EOleSysError) and (EOleSysError(E).ErrorCode < 0) then
Result := EOleSysError(E).ErrorCode else
Result := E_UNEXPECTED;
end;
procedure FreeObjects(List: TList);
var
I: Integer;
begin
for I := List.Count - 1 downto 0 do TObject(List[I]).Free;
end;
procedure FreeObjectList(List: TList);
begin
if List <> nil then
begin
FreeObjects(List);
List.Free;
end;
end;
function CoAllocMem(Size: Integer): Pointer;
begin
Result := CoTaskMemAlloc(Size);
if Result = nil then OleError(E_OUTOFMEMORY);
FillChar(Result^, Size, 0);
end;
procedure CoFreeMem(P: Pointer);
begin
if P <> nil then CoTaskMemFree(P);
end;
function CoAllocString(const S: string): POleStr;
var
W: WideString;
Size: Integer;
begin
W := S;
Size := (Length(W) + 1) * 2;
Result := CoAllocMem(Size);
Move(PWideChar(W)^, Result^, Size);
end;
{ Fill list with properties of a given IDispatch }
procedure EnumDispatchProperties(Dispatch: IDispatch; PropType: TGUID;
VTCode: Integer; PropList: TStrings);
const
INVOKE_PROPERTYSET = INVOKE_PROPERTYPUT or INVOKE_PROPERTYPUTREF;
var
I: Integer;
TypeInfo: ITypeInfo;
TypeAttr: PTypeAttr;
FuncDesc: PFuncDesc;
VarDesc: PVarDesc;
procedure SaveName(Id: Integer);
var
Name: WideString;
begin
OleCheck(TypeInfo.GetDocumentation(Id, @Name, nil, nil, nil));
if PropList.IndexOfObject(TObject(Id)) = -1 then
PropList.AddObject(Name, TObject(Id));
end;
function IsPropType(const TypeInfo: ITypeInfo; TypeDesc: PTypeDesc): Boolean;
var
RefInfo: ITypeInfo;
RefAttr: PTypeAttr;
IsNullGuid: Boolean;
begin
IsNullGuid := IsEqualGuid(PropType, GUID_NULL);
Result := IsNullGuid and (VTCode = VT_EMPTY);
if Result then Exit;
case TypeDesc.vt of
VT_PTR: Result := IsPropType(TypeInfo, TypeDesc.ptdesc);
VT_USERDEFINED:
begin
OleCheck(TypeInfo.GetRefTypeInfo(TypeDesc.hreftype, RefInfo));
OleCheck(RefInfo.GetTypeAttr(RefAttr));
try
Result := IsEqualGUID(RefAttr.guid, PropType);
if not Result and (RefAttr.typekind = TKIND_ALIAS) then
Result := IsPropType(RefInfo, @RefAttr.tdescAlias);
finally
RefInfo.ReleaseTypeAttr(RefAttr);
end;
end;
else
Result := IsNullGuid and (TypeDesc.vt = VTCode);
end;
end;
function HasMember(const TypeInfo: ITypeInfo; Cnt, MemID, InvKind: Integer): Boolean;
var
I: Integer;
FuncDesc: PFuncDesc;
begin
for I := 0 to Cnt - 1 do
begin
OleCheck(TypeInfo.GetFuncDesc(I, FuncDesc));
try
if (FuncDesc.memid = MemID) and (FuncDesc.invkind and InvKind <> 0) then
begin
Result := True;
Exit;
end;
finally
TypeInfo.ReleaseFuncDesc(FuncDesc);
end;
end;
Result := False;
end;
begin
OleCheck(Dispatch.GetTypeInfo(0,0,TypeInfo));
if TypeInfo = nil then Exit;
OleCheck(TypeInfo.GetTypeAttr(TypeAttr));
try
for I := 0 to TypeAttr.cVars - 1 do
begin
OleCheck(TypeInfo.GetVarDesc(I, VarDesc));
try
if (VarDesc.wVarFlags and VARFLAG_FREADONLY <> 0) and
IsPropType(TypeInfo, @VarDesc.elemdescVar.tdesc) then
SaveName(VarDesc.memid);
finally
TypeInfo.ReleaseVarDesc(VarDesc);
end;
end;
for I := 0 to TypeAttr.cFuncs - 1 do
begin
OleCheck(TypeInfo.GetFuncDesc(I, FuncDesc));
try
if ((FuncDesc.invkind = INVOKE_PROPERTYGET) and (FuncDesc.cParams < 1) and
HasMember(TypeInfo, TypeAttr.cFuncs, FuncDesc.memid, INVOKE_PROPERTYSET) and
IsPropType(TypeInfo, @FuncDesc.elemdescFunc.tdesc)) or
((FuncDesc.invkind and INVOKE_PROPERTYSET <> 0) and (FuncDesc.cParams < 2) and
HasMember(TypeInfo, TypeAttr.cFuncs, FuncDesc.memid, INVOKE_PROPERTYGET) and
IsPropType(TypeInfo,
@FuncDesc.lprgelemdescParam[FuncDesc.cParams - 1].tdesc)) then
SaveName(FuncDesc.memid);
finally
TypeInfo.ReleaseFuncDesc(FuncDesc);
end;
end;
finally
TypeInfo.ReleaseTypeAttr(TypeAttr);
end;
end;
{ Font and Picture support }
function GetFontAccess(Font: TFont): IFontAccess;
begin
if Font.FontAdapter = nil then
Font.FontAdapter := TFontAdapter.Create(Font);
Result := Font.FontAdapter as IFontAccess;
end;
function GetPictureAccess(Picture: TPicture): IPictureAccess;
begin
if Picture.PictureAdapter = nil then
Picture.PictureAdapter := TPictureAdapter.Create(Picture);
Result := Picture.PictureAdapter as IPictureAccess;
end;
procedure GetOleFont(Font: TFont; var OleFont: IFontDisp);
begin
GetFontAccess(Font).GetOleFont(OleFont);
end;
procedure SetOleFont(Font: TFont; OleFont: IFontDisp);
begin
GetFontAccess(Font).SetOleFont(OleFont);
end;
procedure GetOlePicture(Picture: TPicture; var OlePicture: IPictureDisp);
begin
GetPictureAccess(Picture).GetOlePicture(OlePicture);
end;
procedure SetOlePicture(Picture: TPicture; OlePicture: IPictureDisp);
begin
GetPictureAccess(Picture).SetOlePicture(OlePicture);
end;
function GetKeyModifiers: Integer;
begin
Result := 0;
if GetKeyState(VK_SHIFT) < 0 then Result := 1;
if GetKeyState(VK_CONTROL) < 0 then Result := Result or 2;
if GetKeyState(VK_MENU) < 0 then Result := Result or 4;
end;
function GetEventShift(Shift: TShiftState): Integer;
const
ShiftMap: array[0..7] of Byte = (0, 1, 4, 5, 2, 3, 6, 7);
begin
Result := ShiftMap[Byte(Shift) and 7];
end;
function GetEventButton(Button: TMouseButton): Integer;
begin
Result := 1 shl Ord(Button);
end;
{ TOleStream }
constructor TOleStream.Create(const Stream: IStream);
begin
FStream := Stream;
end;
function TOleStream.Read(var Buffer; Count: Longint): Longint;
begin
OleCheck(FStream.Read(@Buffer, Count, @Result));
end;
function TOleStream.Seek(Offset: Longint; Origin: Word): Longint;
var
Pos: Largeint;
begin
OleCheck(FStream.Seek(Offset, Origin, Pos));
Result := Longint(Pos);
end;
function TOleStream.Write(const Buffer; Count: Longint): Longint;
begin
OleCheck(FStream.Write(@Buffer, Count, @Result));
end;
function TOleStream.GetIStream: IStream;
begin
Result := FStream;
end;
{ TEnumConnections }
type
TEnumConnections = class(TInterfacedObject, IEnumConnections)
private
FConnectionPoint: TConnectionPoint;
FController: IUnknown;
FIndex: Integer;
FCount: Integer;
protected
{ IEnumConnections }
function Next(celt: Longint; out elt; pceltFetched: PLongint): HResult; stdcall;
function Skip(celt: Longint): HResult; stdcall;
function Reset: HResult; stdcall;
function Clone(out enumconn: IEnumConnections): HResult; stdcall;
public
constructor Create(ConnectionPoint: TConnectionPoint; Index: Integer);
end;
constructor TEnumConnections.Create(ConnectionPoint: TConnectionPoint;
Index: Integer);
begin
inherited Create;
FConnectionPoint := ConnectionPoint;
// keep ConnectionPoint's controller alive as long as we're in use
FController := FConnectionPoint.Controller;
FIndex := Index;
FCount := ConnectionPoint.FSinkList.Count;
end;
{ TEnumConnections.IEnumConnections }
function TEnumConnections.Next(celt: Longint; out elt;
pceltFetched: PLongint): HResult;
type
TConnectDatas = array[0..1023] of TConnectData;
var
I: Integer;
P: Pointer;
begin
I := 0;
while (I < celt) and (FIndex < FCount) do
begin
P := FConnectionPoint.FSinkList[FIndex];
if P <> nil then
begin
Pointer(TConnectDatas(elt)[I].pUnk) := nil;
TConnectDatas(elt)[I].pUnk := IUnknown(P);
TConnectDatas(elt)[I].dwCookie := FIndex + 1;
Inc(I);
end;
Inc(FIndex);
end;
if pceltFetched <> nil then pceltFetched^ := I;
if I = celt then Result := S_OK else Result := S_FALSE;
end;
function TEnumConnections.Skip(celt: Longint): HResult; stdcall;
begin
Result := S_FALSE;
while (celt > 0) and (FIndex < FCount) do
begin
if FConnectionPoint.FSinkList[FIndex] <> nil then Dec(celt);
Inc(FIndex);
end;
if celt = 0 then Result := S_OK;
end;
function TEnumConnections.Reset: HResult; stdcall;
begin
FIndex := 0;
Result := S_OK;
end;
function TEnumConnections.Clone(out enumconn: IEnumConnections): HResult; stdcall;
begin
try
enumconn := TEnumConnections.Create(FConnectionPoint, FIndex);
Result := S_OK;
except
Result := E_UNEXPECTED;
end;
end;
{ TConnectionPoint }
constructor TConnectionPoint.Create(Container: TConnectionPoints;
const IID: TGUID; Kind: TConnectionKind;
OnConnect: TConnectEvent);
begin
inherited Create(IUnknown(Container.FController));
FContainer := Container;
FContainer.FConnectionPoints.Add(Self);
FSinkList := TList.Create;
FIID := IID;
FKind := Kind;
FOnConnect := OnConnect;
end;
destructor TConnectionPoint.Destroy;
var
I: Integer;
begin
if FContainer <> nil then FContainer.FConnectionPoints.Remove(Self);
if FSinkList <> nil then
begin
for I := 0 to FSinkList.Count - 1 do
if FSinkList[I] <> nil then RemoveSink(I);
FSinkList.Free;
end;
inherited Destroy;
end;
function TConnectionPoint.AddSink(const Sink: IUnknown): Integer;
var
I: Integer;
begin
I := 0;
while I < FSinkList.Count do
begin
if FSinkList[I] = nil then
Break
else
Inc(I);
end;
if I >= FSinkList.Count then
FSinkList.Add(Pointer(Sink))
else
FSinkList[I] := Pointer(Sink);
Sink._AddRef;
Result := I;
end;
procedure TConnectionPoint.RemoveSink(Cookie: Longint);
var
Sink: Pointer;
begin
Sink := FSinkList[Cookie];
FSinkList[Cookie] := nil;
IUnknown(Sink)._Release;
end;
{ TConnectionPoint.IConnectionPoint }
function TConnectionPoint.GetConnectionInterface(out iid: TIID): HResult;
begin
iid := FIID;
Result := S_OK;
end;
function TConnectionPoint.GetConnectionPointContainer(
out cpc: IConnectionPointContainer): HResult;
begin
cpc := IUnknown(FContainer.FController) as IConnectionPointContainer;
Result := S_OK;
end;
function TConnectionPoint.Advise(const unkSink: IUnknown;
out dwCookie: Longint): HResult;
begin
if (FKind = ckSingle) and (FSinkList.Count > 0) and
(FSinkList[0] <> nil) then
begin
Result := CONNECT_E_CANNOTCONNECT;
Exit;
end;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -