| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473 |
- (*
- * NeuglsWorkStudio
- * HTML Interface Javascript Extendtion
- * This unit implmented TNCJsExtented which used for extend the capablity of
- * javascript.
- *
- * Author : Neugls
- * Create time: 4/27/2011
- *
- * Thanks for : Henri Gourvest
- *
- *
- *
- *
- *
- *)
- unit JSExtented;
- interface
- uses
- SysUtils, Classes, ceflib, Rtti, cefvcl;
- const
- csErrorParameters ='Error Parameters';
- csHaveNoThisMember ='Have no member';
- csChromiumCouldNotBeNil ='Chromium could not be nil, please first set the Chromium property';
- type
- TVCLJsExtended=class(TComponent)
- type
- TANameType=(ntMethod,ntField,ntProperty);
- {Inner class}
- TNCJSHandle=class(TCefv8HandlerOwn)
- private
- FContainer:TVCLJsExtended;
- protected
- function Execute(const name: ustring; const obj: ICefv8Value;
- const arguments: TCefv8ValueArray; var retval: ICefv8Value;
- var exception: ustring): Boolean; override;
- procedure JsCallMethod(Method:TRttiMethod;out ReturnVal:ICefv8Value; const Param:TCefv8ValueArray);overload;
- procedure JsCallMethod(Method:TRttiMethod;out ReturnVal:ICefv8Value);overload;
- function MethodParamLength(Mn:string):Integer;
- public
- constructor Create(Container:TVCLJsExtended);
- end;
- private
- FProcessObject:TObject;
- FJsHandle:TNCJSHandle;
- FTypeInfo:Pointer;
- FCustomChromium:TChromium;
- FFrame:ICefFrame;
- public
- Frame:ICefFrame{ read FFrame write FFrame};
- property ProcessObject:TObject read FProcessObject;
- property ATypeInfo:Pointer read FTypeInfo;
- procedure SetProcessObject(value:TObject;ATypeInfo:Pointer);
- Procedure ExecuteJavaScript(const jsCode, scriptUrl: string; startLine: Integer);overload;
- Procedure ExecuteJavaScript(const jsCode:string);overload;
- constructor create(AOwner:TComponent);override;
- property Chromium:TChromium read FCustomChromium write FCustomChromium;
- end;
- TVCLNcJsExtended = class(TVCLJsExtended)
- published
- property Chromium;
- end;
- TNCWebBrowser=class(TChromium)
- end;
- procedure Register;
- implementation
- uses TypInfo;
- procedure Register;
- begin
- RegisterComponents('NwControls', [TVCLNcJsExtended]);
- RegisterComponents('NwControls', [TChromium]);
- end;
- { TVCLJsExtended }
- constructor TVCLJsExtended.create(AOwner:TComponent);
- begin
- inherited create(AOwner);
- FProcessObject:=nil;
- FJsHandle:=TNCJSHandle.Create(Self);
- end;
- procedure TVCLJsExtended.ExecuteJavaScript(const jsCode, scriptUrl: string;
- startLine: Integer);
- begin
- if not Assigned(FCustomChromium) then
- begin
- raise Exception.Create(csChromiumCouldNotBeNil);
- Exit;
- end;
- FCustomChromium.Browser.MainFrame.ExecuteJavaScript(jsCode,scriptUrl,startLine);
- end;
- procedure TVCLJsExtended.ExecuteJavaScript(const jsCode:string);
- begin
- ExecuteJavaScript(jsCode,'',0);
- end;
- procedure TVCLJsExtended.SetProcessObject(value: TObject;ATypeInfo:Pointer);
- var
- RttiContext:TRttiContext;
- RttiType:TRttiType;
- RM:TRttiMethod;
- RP:TRttiProperty;
- RF:TRttiField;
- JsStr,name:String;
- I:Integer;
- begin
- {
- 根据object所提供的方法属性生成js字符串,希望注册.
- }
- FProcessObject:=value;
- FTypeInfo:=ATypeInfo;
- RttiType:=RttiContext.GetType(FTypeInfo);
- name:=RttiType.Name;
- JsStr:=Format('var %s;',[name]);
- JsStr:=Format('%s if(!%s) %s={};',[JsStr,name,name]);
- {Process method}
- for RM in RttiType.GetMethods do
- begin
- JsStr:=JsStr+Format(#$A#$D' native function %s(',[RM.Name]);
- if Length(RM.GetParameters)=0 then
- JsStr:=Format('%s);',[JsStr])
- else
- begin
- for I := 0 to Length(RM.GetParameters)-2 do
- JsStr:=Format('%s %s,',[JsStr,chr(ord('A')+I)]);
- I:=Length(RM.GetParameters)-1;
- JsStr:=Format('%s %s);',[JsStr,chr(ord('A')+I)]);
- end;
- end;
- {Process Field}
- for RF in RttiType.GetFields do
- begin
- JsStr:=Format('%s'#$A#$D' var %s;',[JsStr,RF.Name]);
- case RF.FieldType.TypeKind of
- tkUnknown: ;
- tkInteger: JsStr:=Format('%s'#$A#$D' %s=%d;',[JsStr,RF.Name,RF.GetValue(FProcessObject).AsInteger]);
- tkChar: JsStr:=Format('%s'#$A#$D' %s="%s";',[JsStr,RF.Name,RF.GetValue(FProcessObject).AsString]);
- tkEnumeration: JsStr:=Format('%s'#$A#$D' %s=%d;',[JsStr,RF.Name,RF.GetValue(FProcessObject).AsInteger]);
- tkFloat: JsStr:=Format('%s'#$A#$D' %s=%f;',[JsStr,RF.Name,RF.GetValue(FProcessObject).AsExtended]);
- tkString: JsStr:=Format('%s'#$A#$D' %s="%s";',[JsStr,RF.Name,RF.GetValue(FProcessObject).AsString]);
- tkSet: JsStr:=Format('%s'#$A#$D' %s=%d;',[JsStr,RF.Name,RF.GetValue(FProcessObject).AsInteger]);
- tkClass:{support later} JsStr:=Format('%s'#$A#$D' %s={};',[JsStr,RF.Name]);
- tkMethod: ;
- tkWChar: JsStr:=Format('%s'#$A#$D' %s="%s";',[JsStr,RF.Name,RF.GetValue(FProcessObject).AsString]);
- tkLString: JsStr:=Format('%s'#$A#$D' %s="%s";',[JsStr,RF.Name,RF.GetValue(FProcessObject).AsString]);
- tkWString: JsStr:=Format('%s'#$A#$D' %s="%s";',[JsStr,RF.Name,RF.GetValue(FProcessObject).AsString]);
- tkVariant: ;
- tkArray: ;
- tkRecord: ;
- tkInterface: ;
- tkInt64: JsStr:=Format('%s'#$A#$D' %s=%d;',[JsStr,RF.Name,RF.GetValue(FProcessObject).AsInteger]);
- tkDynArray: ;
- tkUString: JsStr:=Format('%s'#$A#$D' %s="%s";',[JsStr,RF.Name,RF.GetValue(FProcessObject).AsString]);
- tkClassRef: ;
- tkPointer: ;
- tkProcedure: ;
- end;
- end;
- {Process property}
- for RP in RttiType.GetProperties do
- begin
- JsStr:=Format('%s'#$A#$D' var %s;',[JsStr,RP.Name]);
- case RF.FieldType.TypeKind of
- tkUnknown: ;
- tkInteger: JsStr:=Format('%s'#$A#$D' %s=%d;',[JsStr,RP.Name,RP.GetValue(FProcessObject).AsInteger]);
- tkChar: JsStr:=Format('%s'#$A#$D' %s="%s";',[JsStr,RP.Name,RP.GetValue(FProcessObject).AsString]);
- tkEnumeration: JsStr:=Format('%s'#$A#$D' %s=%d;',[JsStr,RP.Name,RP.GetValue(FProcessObject).AsInteger]);
- tkFloat: JsStr:=Format('%s'#$A#$D' %s=%f;',[JsStr,RP.Name,RP.GetValue(FProcessObject).AsExtended]);
- tkString: JsStr:=Format('%s'#$A#$D' %s="%s";',[JsStr,RP.Name,RP.GetValue(FProcessObject).AsString]);
- tkSet: JsStr:=Format('%s'#$A#$D' %s=%d;',[JsStr,RP.Name,RP.GetValue(FProcessObject).AsInteger]);
- tkClass:{support later} JsStr:=Format('%s'#$A#$D' %s={};',[JsStr,RP.Name]);
- tkMethod: ;
- tkWChar: JsStr:=Format('%s'#$A#$D' %s="%s";',[JsStr,RP.Name,RP.GetValue(FProcessObject).AsString]);
- tkLString: JsStr:=Format('%s'#$A#$D' %s="%s";',[JsStr,RP.Name,RP.GetValue(FProcessObject).AsString]);
- tkWString: JsStr:=Format('%s'#$A#$D' %s="%s";',[JsStr,RP.Name,RP.GetValue(FProcessObject).AsString]);
- tkVariant: ;
- tkArray: ;
- tkRecord: ;
- tkInterface: ;
- tkInt64: JsStr:=Format('%s'#$A#$D' %s=%d;',[JsStr,RP.Name,RP.GetValue(FProcessObject).AsInteger]);
- tkDynArray: ;
- tkUString: if not RP.GetValue(FProcessObject).IsObject then JsStr:=Format('%s'#$A#$D' %s="%s";',[JsStr,RP.Name,RP.GetValue(FProcessObject).AsString]);
- tkClassRef: ;
- tkPointer: ;
- tkProcedure: ;
- end;
- end;
- if not CefRegisterExtension(RttiType.Name,JsStr,FJsHandle) then
- Raise Exception.Create('Register JavaScript Extension Error');
- end;
- { TVCLJsExtended.TNCJSHandle }
- constructor TVCLJsExtended.TNCJSHandle.Create(
- Container: TVCLJsExtended);
- begin
- inherited Create;
- FContainer:=Container;
- end;
- function TVCLJsExtended.TNCJSHandle.Execute(const name: ustring;
- const obj: ICefv8Value; const arguments: TCefv8ValueArray;
- var retval: ICefv8Value; var exception: ustring): Boolean;
- var
- RttiContext:TRttiContext;
- rm:TRttiMember;
- M:TRttiMethod;
- F:TRttiField;
- P:TRttiProperty;
- A:TRttiArrayType;
- nameType:TANameTYpe;
- o:TObject;
- n:string;
- function ObjectHaveName(const AObject:TObject; const name:String;out isMethod:TANameTYpe; out mb:TRttiMember):Boolean;
- var
- RttiType:TRttiType;
- RM:TRttiMethod;
- RP:TRttiProperty;
- RF:TRttiField;
- begin
- Result:=false;
- RttiType:=RttiContext.GetType(FContainer.FTypeInfo);
- for RM in RttiType.GetMethods do
- begin
- if CompareText(RM.Name,name)=0 then
- begin
- isMethod:=ntMethod;
- mb:=RM;
- Exit(True);
- end;
- end;
- for RP in RttiType.GetProperties do
- begin
- if CompareText(RP.Name,name)=0 then
- begin
- isMethod:=ntProperty;
- mb:=RP;
- Exit(True);
- end;
- end;
- for RF in RttiType.GetFields do
- begin
- if CompareText(RF.Name,name)=0 then
- begin
- isMethod:=ntField;
- mb:=RF;
- Exit(True);
- end;
- end;
- end;
- begin
- Result:=true;
- O:=FContainer.ProcessObject;
- n:=name;
- if not ObjectHaveName(O,name,nameType,rm) then
- begin
- exception:=csHaveNoThisMember;
- Exit(False);
- end;
- case nameType of
- ntMethod:
- begin
- M:=rm as TRttiMethod;
- //Assert(M.MethodKind<>mkFunction);
- if Length(M.GetParameters)>0 then
- begin
- if (Length(arguments)>0) and (Length(arguments)=Length(M.GetParameters)) then
- begin
- JsCallMethod(M,retval,arguments);
- end
- else
- begin
- exception:=csErrorParameters;
- Exit(False);
- end;
- end
- else
- begin
- JsCallMethod(M,retval);
- end;
- end;
- ntField:
- begin
- F:=rm as TRttiField;
- case F.FieldType.TypeKind of
- tkUnknown: ;
- tkInteger: retval:=TCefv8ValueRef.CreateInt(F.GetValue(FContainer.ProcessObject).AsInteger);
- tkChar: retval:=TCefv8ValueRef.CreateString(F.GetValue(FContainer.ProcessObject).AsString);
- tkEnumeration: retval:=TCefv8ValueRef.CreateInt(F.GetValue(FContainer.ProcessObject).AsInteger);
- tkFloat: retval:=TCefv8ValueRef.CreateDouble(F.GetValue(FContainer.ProcessObject).AsExtended);
- tkString: retval:=TCefv8ValueRef.CreateString(F.GetValue(FContainer.ProcessObject).AsString);
- tkSet: retval:=TCefv8ValueRef.CreateInt(F.GetValue(FContainer.ProcessObject).AsInteger);
- tkClass: ;//retval:=TCefv8ValueRef.CreateObject(F.GetValue(FContainer.ProcessObject).AsObject);
- tkMethod: ;
- tkWChar: retval:=TCefv8ValueRef.CreateString(F.GetValue(FContainer.ProcessObject).AsString);
- tkLString: retval:=TCefv8ValueRef.CreateString(F.GetValue(FContainer.ProcessObject).AsString);
- tkWString: retval:=TCefv8ValueRef.CreateString(F.GetValue(FContainer.ProcessObject).AsString);
- tkVariant: ;
- tkArray:
- begin
- {
- retval:=TCefv8ValueRef.CreateArray;
- A:=F.FieldType as TRttiArrayType;
- //support only one demision array
- if A.DimensionCount=1 then
- for I := 0 to A.TotalElementCount do
- begin
- case A.ElementType.TypeKind of
- tkUnknown: retval.SetValueByIndex(I,TCefv8ValueRef.create());
- tkInteger: ;
- tkChar: ;
- tkEnumeration: ;
- tkFloat: ;
- tkString: ;
- tkSet: ;
- tkClass: ;
- tkMethod: ;
- tkWChar: ;
- tkLString: ;
- tkWString: ;
- tkVariant: ;
- tkArray: ;
- tkRecord: ;
- tkInterface: ;
- tkInt64: ;
- tkDynArray: ;
- tkUString: ;
- tkClassRef: ;
- tkPointer: ;
- tkProcedure: ;
- end;
- retval.SetValueByIndex(I,TCefv8ValueRef.create)
- end;
- retval.SetValueByIndex()
- end;;
- tkRecord: ;
- tkInterface: ;
- tkInt64: retval:=TCefv8ValueRef.CreateInt(F.GetValue(FContainer.ProcessObject).AsInteger);
- tkDynArray: ;
- tkUString: retval:=TCefv8ValueRef.CreateString(F.GetValue(FContainer.ProcessObject).AsString);
- tkClassRef: ;
- tkPointer: retval:=TCefv8ValueRef.CreateInt(F.GetValue(FContainer.ProcessObject).AsInteger);
- tkProcedure: ; }
- end;
- end;
- end;
- ntProperty:
- begin
- P:=rm as TRttiProperty;
- case P.PropertyType.TypeKind of
- tkUnknown: ;
- tkInteger: retval:=TCefv8ValueRef.CreateInt(p.GetValue(FContainer.ProcessObject).AsInteger);
- tkChar: retval:=TCefv8ValueRef.CreateString(p.GetValue(FContainer.ProcessObject).AsString);
- tkEnumeration: retval:=TCefv8ValueRef.CreateInt(p.GetValue(FContainer.ProcessObject).AsInteger);
- tkFloat: retval:=TCefv8ValueRef.CreateDouble(p.GetValue(FContainer.ProcessObject).AsExtended);
- tkString: retval:=TCefv8ValueRef.CreateString(p.GetValue(FContainer.ProcessObject).AsString);
- tkSet: retval:=TCefv8ValueRef.CreateInt(p.GetValue(FContainer.ProcessObject).AsInteger);
- tkClass: ;//retval:=TCefv8ValueRef.CreateObject(p.GetValue(FContainer.ProcessObject).AsObject);
- tkMethod: ;
- tkWChar: retval:=TCefv8ValueRef.CreateString(p.GetValue(FContainer.ProcessObject).AsString);
- tkLString: retval:=TCefv8ValueRef.CreateString(p.GetValue(FContainer.ProcessObject).AsString);
- tkWString: retval:=TCefv8ValueRef.CreateString(p.GetValue(FContainer.ProcessObject).AsString);
- tkVariant: ;
- tkArray:;
- end;
- end;
- end;
- end;
- procedure TVCLJsExtended.TNCJSHandle.JsCallMethod(Method: TRttiMethod;
- out ReturnVal: ICefv8Value; const Param: TCefv8ValueArray);
- var
- VA:array of TValue;
- I:Integer;
- rva:TValue;
- AInstance:TObject;
- begin
- if Param<>nil then
- begin
- SetLength(VA,Length(Param));
- for I := 0 to Length(Method.GetParameters)-1 do
- begin
- if Param[I].IsBool then
- VA[I]:=TValue.From<Boolean>(Param[I].GetBoolValue);
- if Param[I].IsInt then
- begin
- VA[I]:=TValue.From<Integer>(Param[I].GetIntValue);
- Continue;
- end;
- if Param[I].IsDouble then
- begin
- VA[I]:=TValue.From<Double>(Param[I].GetDoubleValue);
- Continue;
- end;
- if Param[I].IsString then
- VA[I]:=TValue.From<String>(Param[I].GetStringValue);
- if Param[I].IsObject then
- {VA[I].AsObject:=Param[I].get};
- //if Param[I].is then
- end;
- end
- else
- ;//VA:=nil;
- AInstance:=FContainer.ProcessObject;
- Rva:=Method.Invoke(AInstance,VA);
- case rva.Kind of
- tkUnknown: ;
- tkInteger: ReturnVal:=TCefv8ValueRef.CreateInt(rva.AsInteger);
- tkChar: ReturnVal:=TCefv8ValueRef.CreateString(rva.AsString);
- tkEnumeration: ReturnVal:=TCefv8ValueRef.CreateInt(rva.AsOrdinal);
- tkFloat: ReturnVal:=TCefv8ValueRef.CreateDouble(rva.AsExtended);
- tkString: ReturnVal:=TCefv8ValueRef.CreateString(rva.AsString);
- tkSet: ReturnVal:=TCefv8ValueRef.CreateInt(rva.AsInteger);
- tkClass: ;//ReturnVal:=TCefv8ValueRef.CreateObject(rva.AsObject);
- tkMethod: ;
- tkWChar: ReturnVal:=TCefv8ValueRef.CreateString(rva.AsString);
- tkLString: ReturnVal:=TCefv8ValueRef.CreateString(rva.AsString);
- tkWString: ReturnVal:=TCefv8ValueRef.CreateString(rva.AsString);
- tkVariant: ;
- tkArray:;
- tkRecord: ;
- tkInterface: ;
- tkInt64: ReturnVal:=TCefv8ValueRef.CreateInt(rva.AsInteger);
- tkDynArray: ;
- tkUString: ReturnVal:=TCefv8ValueRef.CreateString(rva.AsString);
- tkClassRef: ;
- tkPointer: ;
- tkProcedure: ;
- end;
- end;
- procedure TVCLJsExtended.TNCJSHandle.JsCallMethod(Method: TRttiMethod;
- out ReturnVal: ICefv8Value);
- begin
- JsCallMethod(Method,ReturnVal,nil);
- end;
- function TVCLJsExtended.TNCJSHandle.MethodParamLength(Mn: string): Integer;
- var
- Rtx:TRttiContext;
- M:TRttiMethod;
- RT:TRttiType;
- begin
- RT:=Rtx.GetType(FContainer.FTypeInfo);
- M:=Rt.GetMethod(Mn);
- Result:=Length(M.GetParameters);
- end;
- {$M-}
- end.
|