我这里直接给他代码,是转载的大神的,具体地址忘了。
(*
* 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
VCL
.
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
;
end
.
|
这是一个控件,他的功能是把delphi函数预注册到程序环境中,这样,在本程序内的所有chrome控件,都可以通过js调用到delphi函数,不过请注意,最好不要用到boolean类型的变量,这样会导致js调用不到delphi。