📄 sf_flash.pas
字号:
function FontToOleFont(Font: TFont): Variant;
var
Temp: IFontDisp;
begin
GetOleFont(Font, Temp);
Result := Temp;
end;
procedure OleFontToFont(const OleFont: Variant; Font: TFont);
begin
SetOleFont(Font, IUnknown(OleFont) as IFontDisp);
end;
function StringToVarOleStr(const S: string): Variant;
begin
VarClear(Result);
TVarData(Result).VOleStr := StringToOleStr(S);
TVarData(Result).VType := varOleStr;
end;
{ TEventDispatch }
constructor TEventDispatch.Create(Control: TsfOleControl);
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._AddRef;
end;
function TEventDispatch._Release: Integer;
begin
Result := FControl._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;
{ TEnumPropDesc }
constructor TEnumPropDesc.Create(DispID, ValueCount: Integer;
const TypeInfo: ITypeInfo);
var
I: Integer;
VarDesc: PVarDesc;
Name: 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, @Name,
nil, nil, nil));
with FValues^[I] do
begin
Value := TVarData(VarDesc^.lpVarValue^).VInteger;
Ident := Name;
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;
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 := StrToInt(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(@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 := IntToStr(V);
end;
{ TsfOleControl }
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;
constructor TsfOleControl.Create(AOwner: TComponent);
var
I: Integer;
begin
inherited Create(AOwner);
FGrabProcess := False;
FInLoading := False;
FTransparent := true;
Include(FComponentStyle, csCheckPropAvail);
InitControlData;
Inc(FControlData^.InstanceCount);
if FControlData^.FontCount > 0 then
begin
FFonts := TList.Create;
FFonts.Count := FControlData^.FontCount;
for I := 0 to FFonts.Count-1 do
FFonts[I] := TFont.Create;
end;
if FControlData^.PictureCount > 0 then
begin
FPictures := TList.Create;
FPictures.Count := FControlData^.PictureCount;
for I := 0 to FPictures.Count-1 do
begin
FPictures[I] := TPicture.Create;
TPicture(FPictures[I]).OnChange := PictureChanged;
end;
end;
FEventDispatch := TEventDispatch.Create(Self);
CreateInstance;
if FFlashNotExists then Exit;
InitControlInterface(FOleObject);
OleCheck(FOleObject.GetMiscStatus(DVASPECT_CONTENT, FMiscStatus));
if (FControlData^.Reserved and cdDeferSetClientSite) = 0 then
if ((FMiscStatus and OLEMISC_SETCLIENTSITEFIRST) <> 0) or
((FControlData^.Reserved and cdForceSetClientSite) <> 0) then
OleCheck(FOleObject.SetClientSite(Self));
OleCheck(FOleObject.QueryInterface(IPersistStreamInit, FPersistStream));
if FMiscStatus and OLEMISC_INVISIBLEATRUNTIME <> 0 then
Visible := False;
OleCheck(RequestNewObjectLayout);
end;
destructor TsfOleControl.Destroy;
procedure FreeList(var L: TList);
var
I: Integer;
begin
if L <> nil then
begin
for I := 0 to L.Count-1 do
TObject(L[I]).Free;
L.Free;
L := nil;
end;
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;
if FBackBuffer <> nil then FBackBuffer.Free;
if FBuffer2 <> nil then FBuffer2.Free;
if FBuffer <> nil then FBuffer.Free;
inherited Destroy;
end;
procedure TsfOleControl.BrowseProperties;
begin
DoObjectVerb(OLEIVERB_PROPERTIES);
end;
procedure TsfOleControl.CreateControl;
var
Stream: IStream;
CS: IOleClientSite_Flash;
X: Integer;
begin
if FOleObject = nil then Exit;
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(Self));
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,
Self, FPropConnection);
InterfaceConnect(FOleObject, FControlData^.EventIID,
FEventDispatch, FEventsConnection);
if FControlData^.Flags and cfBackColor <> 0 then
OnChanged(DISPID_BACKCOLOR);
if FControlData^.Flags and cfEnabled <> 0 then
OnChanged(DISPID_ENABLED);
if FControlData^.Flags and cfFont <> 0 then
OnChanged(DISPID_FONT);
if FControlData^.Flags and cfForeColor <> 0 then
OnChanged(DISPID_FORECOLOR);
FOleControl.OnAmbientPropertyChange(DISPID_UNKNOWN);
RequestNewObjectLayout;
except
DestroyControl;
raise;
end;
end;
procedure TsfOleControl.CreateEnumPropDescs;
function FindMember(DispId: Integer): Boolean;
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;
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
FControlData^.EnumPropDescs.Expand.Add(
TEnumPropDesc.Create(Dispid, RefAttr^.cVars, RefInfo));
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:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -