⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 axctrls.pas

📁 这是不可多得的源代码
💻 PAS
📖 第 1 页 / 共 5 页
字号:
  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 + -