PDA

View Full Version : سوال: جایگزین برای TWebBrowser



Moharram
یک شنبه 06 اردیبهشت 1394, 17:25 عصر
سلام

یه Page داریم که وقتی تو فایرفاکس نمایش داده میشه خیلی سریعه اما تو اینترنت اکسپلورر خیلی کند میشه.

همین Page رو تو یه برنامه با استفاده از TWebBrowser نمایش میدیم، مثل خروجی IE کنده. مثل اینکه خود TWebBrowser هم از IE استفاده میکنه!

میخواستم ببینم آیا برای نمایش Page، کنترل یا اکتیوایکسی موجود هست یا نه؟

یه کنترل به اسم Mozilla ActiveX Control پیدا کردم، اما نتونستم یه تست اولیه بزنم و سرعت Load شدنش رو با TWeBrowser مقایسه کنم، چون Page ما رو نتونست باز کنه.

حالا شاید با توابع JS اون Page مشکل داشته یا مشکل دیگه ای ...

دوستان پیشنهادی ندارند؟

ممنون

یوسف زالی
یک شنبه 06 اردیبهشت 1394, 20:26 عصر
سلام.
chromium
awesomium
embeded
و ...

هر کدوم ضعف و قوت خودشون رو دارند. اگر حوصله دارید کرومیوم کامپوننت خوبیه، ولی یکم کد نوشتن براش سخت تره. همین موارد رو در گوگل جستجو کنید مطلب زیاده.

Moharram
سه شنبه 08 اردیبهشت 1394, 18:01 عصر
با تشکر از جناب You-See (http://barnamenevis.org/member.php?70247-You-See)

کامپوننت Chromium خیلی خوبه و اون Page رو که تو IE و TWebBrowser خیلی سنگین اجرا میشد بخوبی باز میکنه.

اینم لینک دانلودش برای استفاده دوستان: Chromium Embedded Framework (https://getmywarez.com/delphi/14836-delphi-cef3-chromium-embedded-framework-3-full-source-d7-xe7.html)

اما واقعا متوجه نمیشم که چرا TWebBrowser و حتی خود IE دچار مشکل شدند!!!

Moharram
سه شنبه 22 اردیبهشت 1394, 17:52 عصر
هر کدوم ضعف و قوت خودشون رو دارند. اگر حوصله دارید کرومیوم کامپوننت خوبیه، ولی یکم کد نوشتن براش سخت تره. همین موارد رو در گوگل جستجو کنید مطلب زیاده.

همونطور که جناب You-See گفتن، کار کردن با Chromium یه مقدار سخته. گفتم اینجا یک سری از مسائلی که خودم باهاشون برخورد کردم رو بنویسم.


دریافت Event های صادر شده از داخل JS در Delphi


برای اینکار، لازمه که Event خودمون رو در قالب یک کلاس تعریف کنیم. به شکل زیر:

TEventManager = class(TObject)
public
procedure MyEvent(x : Integer);
end;

همونطور که مشخصه قراره که رویداد MyEvent فراخوانی بشه و پارامتر x رو همراه خودش بیاره!


در مرحله بعد کلاس زیر رو با ارث بری از یکی از کلاسهای CEF تعریف می کنیم:

TCustomRenderProcessHandler = class(TCefRenderProcessHandlerOwn)
protected
procedure OnWebKitInitialized; override;
end;


حالا یک متغیر از کلاس TEventManager به اسم EventManager بصورت Global تعریف می کنیم.


لازمه که تو بخش Initialization متغیرهای زیر رو Create کنیم. (دقت کنید که تو FormCreate جواب نمیده!)

CefRenderProcessHandler := TCustomRenderProcessHandler.Create;
EventManager := TEventManager.Create;

متغیر CefRenderProcessHandler داخل یونیت ceflib خود کامپوننت تعریف شده و ما اینجا با استفاده از یک کلاس مشتق شده، اون رو Create می کنیم.


حالا باید برای تابع OnWebKitInitialized کد بنویسیم:

procedure TCustomRenderProcessHandler.OnWebKitInitialized;
begin
TCefRTTIExtension.Register('returnvalue', ReturnValue);
end;

با اینکار با استفاده از پارامتر returnvalue تعریف شده با تابع Register میتونیم از سمت JS رویداد MyEvent رو فراخوانی کنیم.
به این صورت:


کد زیر رو داخل یک فایل html ذخیره می کنیم.

<script language="javascript">
function sum_event(par1,par2)
{
eventmanager.MyEvent(par1+par2);
}
</script>
<html>
<body>
</body>
</html>

همونطور که دیده میشه پارامترهای ورودی تابع sum_event با هم جمع می شن و با استفاده از متغیر eventmanager که قبلا تعریف کرده بودیم، رویداد MyEvent فراخوانی میشه.


برای تست میشه تابع sum_event رو داخل تگ Body فراخوانی کرد و صفحه Html مذکور رو تو CEF باز کرد. برای کامل تر شدن این مثال سعی می کنیم که فراخوانی تابع Sum_event رو از Delphi انجام بدیم.


ابتدا با دستور زیر صفحه رو روی Chromium باز می کنیم:

Chromium1.Browser.MainFrame.LoadUrl(edAddress.Text );

edAddres.text حاوی آدرس فایل html هستش.


سپس با دستور زیر تابع sum_event رو اجرا می کنیم:

Chromium1.Browser.MainFrame.ExecuteJavaScript('sum _event(5,6)','',0);

اگر برای MyEvent تو سمت دلفی کد نوشته باشیم، با اجرای خط فوق اون Event فراخوانی میشه.

Moharram
چهارشنبه 23 اردیبهشت 1394, 10:13 صبح
یکی دیگه از مسائلی که باهاش برخورد کردم رو می آرم، هرچند هنوز راه حل خاصی براش ندارم!


دریافت Return از تابعهای JS در Delphi


قبلا با TWebBrowser این مساله اینجوری حل شده بود، که تو JS یک Element از HTML مقداردهی میشد و بعد تو سمت Delphi با استفاده از کلاس IHTML2Document میشد مقدار اون Element رو خوند.

تو Chromium گفتم که با همون روش ارسال Event شاید بشه یه کارهایی کرد، پس یک متغیر و دو تا تابع برای Set و Get تو کلاس TEventManager نعریف کردم و تو سمت JS هم اون متغیر رو مقداردهی کردم تا مثلا Return تابع باشه تا بعدا تو Delphi بتونم بخونمش.

تا اینجا همه چی درسته، اما وقتی از دلفی تابع JS رو فراخوانی میکنی، قبل از اینکه تو JS به خط آخر تابع و مقداردهی به متغیر Return برسه، تو سمت دلفی قبل از اینکه Return مقدار معتبری بگیره، میرسیم سروقت خوندن مقدارش، که طبیعتا مقدار درستی نیست.

به عبارت دیگر فراخوانی توابع JS با Chromium بصورت Non-Blocking عمل میکنه، و هر چقدر هم که عملیات داخل تابع طول بکشه، انگار مثل یک Thread وظیفه فراخوانی تابع JS رو به اون میده و سریع برمیگیرده تو بخش فراخواننده که همون دلفی باشه ... .

البته میشه تو سمت دلفی با یک تابع Sleep تا حدودی معطل موند تا Return آماده بشه، اما راه حل قشنگی نیست. ضمن اینکه بسته به روند طول کشیدن اجرای تابعهای مختلف در JS نمیدونیم برای هر کدوم چند میلی ثانیه باید صبر کنیم!

جالبه که مشابه همین تست رو با TWebBrowser زدم و اونجا بصورت Blocking عمل میکنه. یعنی تا وقتی که اجرای تابع JS تموم نشده، کنترل به دست برنامه دلفی نمی افته، و در نتیجه با اون روش Set و Get میشه مقدار Return رو از داخل دلفی خوند.

حالا این روش ارسال Return با Set و Get همین جوری به ذهنم رسید ... !

لطفا اگه دوستان نظری راجع به روش بالا یا راه حلهای دیگری برای مساله ارسال Return دارند، بیان کنند.

ممنون

یوسف زالی
چهارشنبه 23 اردیبهشت 1394, 10:38 صبح
یک راه غیر قشنگش ساخت یک ترد روی innerHTML از Element مورد نظره.

Moharram
چهارشنبه 27 خرداد 1394, 15:59 عصر
سلام

در اون روش ارائه شده در سه پست بالاتر از این، در مورد دریافت Event های صادر شده از داخل JS در Delphi انگار مشکلی وجود داره !!!؟

مثلا تو یه کاربرد خاص فرض کنید، در سمت JS در داخل یک Timer بطور مداوم event رو فراخوانی کنیم، در اینصورت میزان حافظه مصرفی VM Size برنامه همین جور، بی رویه میره بالا و تا جایی میرسه که Application هنگ میکنه !!! این VM Size رو توی Task Manager میشه چک کرد.

نمیدونم مشکل کار تو داخل خود کلاسهای Chromium هستش یا اینکه روش بالا مشکلی داره ؟

جستجو هم کردم اما به چیزی خاصی نرسیدم !!!