In Delphi , With below code I can send data to Javascript and it work well , but how can send data from Javascript to Delphi ?
first , I Use below code in Javascript but did not work :
JS_DELPHI._geta() ;
even below code did not work :
TMyExtension._geta() ;
I think my code in Delphi have not some essential code.
unit Unit1;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
FMX.Controls.Presentation, FMX.StdCtrls, ceffmx, FMX.Edit , ceflib ,
uCEFBaseRefCounted, uCEFInterfaces, uCEFTypes, uCEFListValue, uCEFBrowser, uCEFFrame, uCEFRequest,
uCEFv8Context, uCEFv8Exception, uCEFv8StackTrace, uCEFDomNode, uCEFProcessMessage, uCEFApplicationCore;
type
TForm1 = class(TForm)
ChromiumFMX1: TChromiumFMX;
Button1: TButton;
Edit1: TEdit;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
type
//这里建议用class 不建议用class(TThread) 不然有些地方要报错
TMyExtension = class(TThread) // or just class, (extension code execute in thread)
public
class function _geta:string;
end;
TCustomRenderProcessHandler = class(TCefRenderProcessHandlerOwn)
protected
procedure OnWebKitInitialized; override;
end;
var
Form1: TForm1;
d : Integer ;
m : TMyExtension ;
CefRenderProcessHandler : TCustomRenderProcessHandler ;
implementation
{$R *.fmx}
{$R *.LgXhdpiPh.fmx ANDROID}
{$R *.XLgXhdpiTb.fmx ANDROID}
{$R *.SSW3.fmx ANDROID}
procedure TForm1.Button1Click(Sender: TObject);
begin
ChromiumFMX1.Load('http://localhost/index.html');
Edit1.Text := '555 ';
ShowMessage('hiiiiiiiiiiiiiiiii');
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
ChromiumFMX1.Browser.MainFrame.ExecuteJavaScript(' d1();',ChromiumFMX1.browser.MainFrame.GetURL, 0);
end;
class function TMyExtension._geta: string;
begin
ShowMessage('dddddddddddddddddddddddd');
Result:='salam';
end;
procedure TCustomRenderProcessHandler.OnWebKitInitialized;
begin
{$IFDEF DELPHI14_UP}
TCefRTTIExtension.Register('JS_DELPHI', TMyExtension);
{$ENDIF}
end;
initialization
CefRemoteDebuggingPort := 9000;
CefRenderProcessHandler := TCustomRenderProcessHandler.Create;
CefBrowserProcessHandler := TCefBrowserProcessHandlerOwn.Create;
end.
end.
Related
I want to rearrange TListView's Items dynamically such as, I have following items:
Item #1 Apple
Item #2 Banana
Item #3 Orange
and so on.....
I want to set Orange in Item #1, is it possible?
I've used something like this in 10.2 and 10.3 not sure when the TComparer came about
Here is a unit with two basic sorters - you can change the code to do whatever in the compare function
unit MyFMXListView_ItemSorters;
interface
uses
System.Generics.Defaults
, FMX.ListView.Appearances
;
type
TMyListViewItemComparer_AscendingItemText = class( TComparer<TListViewItem> )
function Compare(const Left, Right: TListViewItem): Integer; override;
end;
TMyListViewItemComparer_DescendingItemText = class( TComparer<TListViewItem> )
function Compare(const Left, Right: TListViewItem): Integer; override;
end;
implementation
uses
sysutils;
{ TMyListViewItemComparer_Ascending }
function TMyListViewItemComparer_AscendingItemText.Compare(const Left,
Right: TListViewItem): Integer;
begin
result := CompareText(Left.Text,Right.Text);
end;
{ TMyListViewItemComparer_DescendingItemText }
function TMyListViewItemComparer_DescendingItemText.Compare(const Left,
Right: TListViewItem): Integer;
begin
result := CompareText(Right.Text,Left.Text);
end;
end.
if you use this unit in your form then all you need to do is call the TListView.Items.Sort( TMyListViewItemComparer_AscendingItemText.Create );
e.g.Basic Form
unit Unit1;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
FMX.ListView.Types, FMX.ListView.Appearances, FMX.ListView.Adapters.Base,
FMX.StdCtrls, FMX.Controls.Presentation, FMX.ListView;
type
TForm1 = class(TForm)
lv1: TListView;
pnlTop: TPanel;
btnAscending: TButton;
btnDescending: TButton;
procedure FormShow(Sender: TObject);
procedure btnAscendingClick(Sender: TObject);
procedure btnDescendingClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
uses
MyFMXListView_ItemSorters
;
{$R *.fmx}
procedure TForm1.btnAscendingClick(Sender: TObject);
begin
lv1.Items.Sort( TMyListViewItemComparer_AscendingItemText.Create );
end;
procedure TForm1.btnDescendingClick(Sender: TObject);
begin
lv1.Items.Sort( TMyListViewItemComparer_DescendingItemText.Create );
end;
procedure TForm1.FormShow(Sender: TObject);
var
myTListViewItem : TListViewItem;
begin
lv1.ItemAppearance.ItemHeight := 24;
lv1.Items.Add.Text := 'Banana';
lv1.Items.Add.Text := 'Apple';
lv1.Items.Add.Text := 'Orange';
end;
Three images below ( After Create, After Ascending click and after Descending click )
I have built and run the code below as an Android app.
The app works a expected but I get a segemtation fault in the TIdSSLIOhandler when closing down.
Is the Indy components not compatible with FireMonkey?
unit Main;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, IdIOHandler,
IdIOHandlerSocket, IdIOHandlerStack, IdSSL, IdSSLOpenSSL, IdBaseComponent,
IdComponent, IdTCPConnection, IdTCPClient, IdHTTP, FMX.Layouts, FMX.Memo,
FMX.StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Memo1: TMemo;
http: TIdHTTP;
ioSocket: TIdSSLIOHandlerSocketOpenSSL;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
LiServer:string;
procedure DBCom(var retdata: TStringlist);
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.fmx}
{$R *.LgXhdpiPh.fmx ANDROID}
procedure TForm1.Button1Click(Sender: TObject);
var m: TMemoryStream;
retdata: TStringList;
i:integer;
begin
m:=TMemoryStream.Create;
//--- init data
retdata:=TStringList.Create;
retdata.Add('F=1');
//--- add data
retdata.Add('Data=1');
//--- send data to server database
DBCom(retdata);
for i := 0 to retdata.Count-1 do
memo1.Lines.Add(retdata[i]);
//--- free allocated resources
retdata.Free;
m.Free;
end;
procedure TForm1.Button2Click(Sender: TObject);
var m: TMemoryStream;
retdata: TStringList;
i:integer;
begin
m:=TMemoryStream.Create;
//--- init data
retdata:=TStringList.Create;
retdata.Add('F=1');
//--- add data
retdata.Add('Data=A');
//--- send data to server database
DBCom(retdata);
for i := 0 to retdata.Count-1 do
memo1.Lines.Add(retdata[i]);
//--- free allocated resources
retdata.Free;
m.Free;
end;
//============ communication with DB
procedure TForm1.DBCom(var retdata:TStringlist);
var m: TMemoryStream;
errcode,i,msgid,status,id:Integer;
begin
m:=TMemoryStream.Create;
//--- send data to server database
http.Post(LiServer, retdata, m);
m.Position:=0;
retdata.LoadFromStream(m);
//--- free allocated resources
m.Free;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
LiServer:='http://server.com/url.php';
end;
end.
The error occurs in this procedure on the SSL_CTX_free(fContext) line.
procedure TIdSSLContext.DestroyContext;
begin
if fContext <> nil then begin
SSL_CTX_free(fContext);
fContext := nil;
end;
end;
#Remy Lebeau had given me the answer I was looking for in the note above.
I am a newbie with Firemonkey and XE3 environment.
My program does some calculations and should give feedback to user with a TeeChart component.
OnClick()
begin
while(boolContinue) do
begin
NextStep(boolContinue);
DoSomeCalculations();
UpdateTeeChart();
end;
end;
I used Application.ProcessMessage in Delphi7. In a FireMonkey application it seems to take almost a second to make a single ProcessMessage call.
What is proper way to update TChart (TLineSeries / TeeChart Lite v 2012.06.120613)?
I tryied:
- HandleMessage (works, but slow)
- process paint messages only (works, but slow)
- Invalidate (doesnt work)
- Repaint (doesnt work)
I also tryied to use threads with no success.
Edit:
Added a simple test program:
unit Unit1;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Rtti, System.Classes,
System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Dialogs,
FMXTee.Engine, FMXTee.Procs, FMXTee.Chart, FMXTee.Series;
type
TForm1 = class(TForm)
Chart1: TChart;
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.fmx}
procedure TForm1.Button1Click(Sender: TObject);
var
line : TLineSeries;
ii, x1, x2 : integer;
begin
line := TLineSeries.Create(chart1);
line.ParentChart := chart1;
for ii := 1 to 100 do
begin
line.AddXY(ii, random(20));
// Do some calculations...
self.Caption := IntToStr(ii);
for x1 := 1 to 10000 do
for x2 := 1 to 1000 do
begin
end;
end;
end;
end.
Solution found!
The subject is also discussed here and solution was found there:
https://forums.embarcadero.com/message.jspa?messageID=427282
Now the charts repaints and it takes only ~2 seconds to run.
unit Unit1;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Rtti, System.Classes,
System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Dialogs,
FMXTee.Engine, FMXTee.Procs, FMXTee.Chart, FMXTee.Series, Windows;
type MyThread = class(TThread)
protected
procedure Execute; override;
public
line : TLineSeries;
constructor Create; overload;
destructor Destroy; override;
end;
type
TForm1 = class(TForm)
Chart1: TChart;
Button1: TButton;
Label2: TLabel;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.fmx}
constructor MyThread.Create;
begin
inherited Create(true);
FreeOnTerminate := true;
end;
destructor MyThread.Destroy;
begin
inherited;
end;
procedure MyThread.Execute;
var
ii, x1, x2 : integer;
begin
for ii := 1 to 100 do
begin
line.AddXY(ii, random(20));
// Do some calculations...
for x1 := 1 to 10000 do
for x2 := 1 to 1000 do
begin
end;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
MT : MyThread;
line : TLineSeries;
begin
chart1.BottomAxis.Minimum := 0;
chart1.BottomAxis.Maximum := 100;
chart1.BottomAxis.AutomaticMinimum := false;
chart1.BottomAxis.AutomaticMaximum := false;
chart1.Legend.Visible := false;
line := TLineSeries.Create(chart1);
line.ParentChart := chart1;
MT := MyThread.Create;
MT.line := line;
MT.Start;
end;
end.
I have problem with host application, which loads DLL form and interfaceing some function and properties.
The purpose is load a dll, show name as module name, set connection to ADOTable component and show form with data. Everything is working fine. But after close the host app a host app crashed and I get windows that hostapp.exe stopped working.
I do not know whether it is by freeing library or setting nil for interface.
Do you have any solution? Thanks.
Interface CODE
unit u_baseplugin_intf;
interface
uses Data.Win.ADODB, Data.DB;
type
IBaseModuleInterface = interface
['{060A9C46-B3CF-4BA4-B025-2DC1D9F45076}']
function GetModuleName: Ansistring;stdcall;
procedure SetConn(sConn:TAdoConnection);stdcall;
procedure showF;stdcall;
procedure freeF;stdcall;
property ModuleName: Ansistring read GetModuleName;
property Connection : TAdoConnection write SetConn;
end;
implementation
end.
DLL code
library profileslist;
uses
System.SysUtils,
System.Classes,
u_baseplugin_intf,
u_profileslist in 'u_profileslist.pas' {Form_DLL};
{$R *.res}
function LoadModule:IBaseModuleInterface;stdcall;
begin
result:=TForm_DLL.Create(nil);
end;
exports
LoadModule;
begin
end.
DLL Form code
unit u_profileslist;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.Grids, Vcl.DBGrids, Vcl.StdCtrls,
u_baseplugin_intf, Data.DB,Data.Win.ADODB;
type
TForm_DLL = class(TForm, IBaseModuleInterface)
DBGrid1: TDBGrid;
ADOTable1: TADOTable;
DataSource1: TDataSource;
procedure FormShow(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
{Interface methods implementation}
function GetModuleName: AnsiString;stdcall;
procedure SetConn(sConn:TAdoConnection);stdcall;
public
{ Public declarations }
{Interface methods implementation}
procedure ShowF;stdcall;
procedure FreeF;stdcall;
end;
var
Form_DLL: TForm_DLL;
implementation
{$R *.dfm}
{Interface methods implementation}
function TForm_DLL.GetModuleName;
begin
Result := 'Profiles list';
end;
procedure TForm_DLL.SetConn(sConn: TAdoConnection);
begin
AdoTable1.Connection:=sConn;
end;
procedure TForm_DLL.ShowF;
begin
ShowModal;
end;
procedure TForm_DLL.FreeF;
begin
FreeAndNil(Form_DLL);
end;
{Form_DLL methods implementation}
procedure TForm_DLL.FormClose(Sender: TObject; var Action: TCloseAction);
begin
AdoTable1.Active:=false;
end;
procedure TForm_DLL.FormShow(Sender: TObject);
begin
AdoTable1.Active:=true;
end;
end.
HOST app code
program hostapp;
uses
Vcl.Forms,
u_hostapp in 'u_hostapp.pas' {Form1},
u_baseplugin_intf in 'u_baseplugin_intf.pas';
{$R *.res}
begin
Application.Initialize;
Application.MainFormOnTaskbar := True;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.
Host app FORM code
unit u_hostapp;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls,
u_baseplugin_intf,
Data.Win.ADODB, Data.DB;
type
TForm1 = class(TForm)
ADOConnection1: TADOConnection;
Button1: TButton;
Label1: TLabel;
procedure Button1Click(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
type
TModuleInterface = function:IBaseModuleInterface; stdcall;
var
Form1: TForm1;
implementation
{$R *.dfm}
var
aModuleIntf : IBaseModuleInterface;
dllHandle : cardinal;
procedure LoadModule( aLibName : pWideChar );
var
lModule : TModuleInterface;
begin
dllHandle := LoadLibrary(aLibName) ;
if dllHandle <> 0 then
begin
#lModule := GetProcAddress(dllHandle, 'LoadModule') ;
if Assigned (lModule) then
aModuleIntf := lModule //call the function
else
begin
ShowMessage('GetModuleIntf not found.') ;
FreeLibrary(dllHandle) ;
end;
end
else
begin
ShowMessage(aLibName+' not found.') ;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
aModuleIntf.Connection:=AdoConnection1;
aModuleIntf.ShowF;
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
aModuleIntf.Connection:=nil;
aModuleIntf.freeF;
aModuleIntf:=nil;
FreeLibrary(dllHandle);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
LoadModule('profileslist.dll');
Label1.Caption:=aModuleIntf.ModuleName;
end;
end.
You never assign to Form_DLL. This means that when you call FreeF, you then perform FreeAndNil(Form_DLL). Since Form_DLL is nil, this does nothing, and the form still exists.
Fix that by changing LoadModule:
function LoadModule:IBaseModuleInterface;stdcall;
begin
Assert(not Assigned(Form_DLL));
Form_DLL:=TForm_DLL.Create(nil);
result:=Form_DLL;
end;
Although, I'd probably change the design completely by removing Form_DLL altogether. The host app maintains a reference to the form, on which the call to Free can be made. In other words, remove Form_DLL and implement FreeF like this:
procedure TForm_DLL.FreeF;
begin
Free; // or Destroy
end;
Or even better, use reference counted interfaces on the implementing object and let aModuleIntf:=nil take the form down.
Im trying to make a FMX form in a dll, after about 17 hours (of trying diffrent approches) i got it working, except i get a exception trying to unload the dll. I have no idea how to make it work, maybe someone could help me and point out what im doing wrong?
side note:
i cant have a FMX form in my VCL application becouse of the AA drawing, i just need it on my text while drawing on a canvas and while having a FMX form on a VCL application, i dont get that cleartype on text :( im trying to make a some sort of OSD/HUD.
Project showing my problem:
exe unit1.pas
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
uses
unitLoadDLL, Winapi.GDIPOBJ;
procedure TForm1.Button1Click(Sender: TObject);
begin
showme();
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
closeme();
end;
end.
exe unitLoadDll.pas
unit unitLoadDLL;
interface
uses Windows, Dialogs;
type
TShowme = procedure();
TCloseme = procedure();
var
showme : TShowme = nil;
closeme : TCloseme = nil;
DllHandle : THandle;
implementation
initialization
if DllHandle = 0 then begin
DllHandle := LoadLibrary('C:\Users\Ja\Desktop\dupa\dll\Win32\Debug\Project1.dll');
if DllHandle > 0 then begin
#showme := GetProcAddress(DllHandle,'showme');
#closeme := GetProcAddress(DllHandle,'closeme');
end
else begin
MessageDlg('Select Image functionality is not available', mtInformation, [mbOK], 0);
end;
end;
finalization
if DLLHandle <> 0 then
FreeLibrary(DLLHandle);
end.
dll project1.dpr
library Project1;
uses
FMX.Forms,
System.SysUtils,
System.Classes,
Unit1 in 'Unit1.pas' {Form1};
{$R *.res}
procedure showme(); stdcall export;
begin
TForm1.showme;
end;
procedure closeme(); stdcall export;
begin
TForm1.closeme;
end;
exports
showme, closeme;
begin
end.
dll unit1.pas
unit Unit1;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Dialogs;
type
TForm1 = class(TForm)
Label1: TLabel;
private
{ Private declarations }
public
class procedure showme();
class procedure closeme();
end;
var
Form1: TForm1;
implementation
{$R *.fmx}
class procedure TForm1.showme();
begin
Form1 := TForm1.Create(Application);
Form1.Show;
end;
class procedure TForm1.closeme();
begin
Form1.Free;
end;
end.
EDIT (FIX):
All answers ware helpfull, but what i've done is, that the GDI+ was shutdown BEFORE the dll unload... that appear's to be the problem.
new unitLoadDll.pas
unit unitLoadDLL;
interface
uses Windows, Dialogs;
type
TShowme = procedure();
TCloseme = procedure();
var
showme : TShowme = nil;
closeme : TCloseme = nil;
DllHandle : THandle;
function LoadLib : Boolean;
procedure UnloadLib;
implementation
function LoadLib : Boolean;
begin
if DllHandle = 0 then begin
DllHandle := LoadLibrary('C:\Users\Ja\Desktop\dupa\dll\Win32\Debug\Project1.dll');
if DllHandle > 0 then begin
#showme := GetProcAddress(DllHandle,'showme');
#closeme := GetProcAddress(DllHandle,'closeme');
end
else begin
MessageDlg('Select Image functionality is not available', mtInformation, [mbOK], 0);
end;
end;
Result := DllHandle <> 0;
end;
procedure UnloadLib;
begin
if DLLHandle <> 0 then begin
FreeLibrary(DLLHandle);
DllHandle := 0;
end;
end;
initialization
LoadLib;
finalization
UnloadLib;
end.
new unit1.pas
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Winapi.GDIPOBJ;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
uses
unitLoadDLL;
procedure TForm1.Button1Click(Sender: TObject);
begin
showme();
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
closeme();
end;
end.
in unit1.pas i moved the Winapi.GDIPOBJ to "uses" just after interface directive, and it worked...
Thank you all for your answers! See you soon! very soon...
Does it help if you import sharemem on both sides?
You are not using packages, so both sides probably have an own instance all RTL state, as well as VMT tables (though that is only a problem with certain IS and AS cases). And the memory manager is RTL state :-)