نقل قول: جایگزین برای TWebBrowser
سلام.
chromium
awesomium
embeded
و ...
هر کدوم ضعف و قوت خودشون رو دارند. اگر حوصله دارید کرومیوم کامپوننت خوبیه، ولی یکم کد نوشتن براش سخت تره. همین موارد رو در گوگل جستجو کنید مطلب زیاده.
نقل قول: جایگزین برای TWebBrowser
با تشکر از جناب You-See
کامپوننت Chromium خیلی خوبه و اون Page رو که تو IE و TWebBrowser خیلی سنگین اجرا میشد بخوبی باز میکنه.
اینم لینک دانلودش برای استفاده دوستان: Chromium Embedded Framework
اما واقعا متوجه نمیشم که چرا TWebBrowser و حتی خود IE دچار مشکل شدند!!!
نقل قول: جایگزین برای TWebBrowser
نقل قول:
نوشته شده توسط
You-See
هر کدوم ضعف و قوت خودشون رو دارند. اگر حوصله دارید کرومیوم کامپوننت خوبیه، ولی یکم کد نوشتن براش سخت تره. همین موارد رو در گوگل جستجو کنید مطلب زیاده.
همونطور که جناب 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 فراخوانی میشه.
دریافت Return از تابعهای JS در Delphi
یکی دیگه از مسائلی که باهاش برخورد کردم رو می آرم، هرچند هنوز راه حل خاصی براش ندارم!
دریافت 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 دارند، بیان کنند.
ممنون
نقل قول: جایگزین برای TWebBrowser
یک راه غیر قشنگش ساخت یک ترد روی innerHTML از Element مورد نظره.
حافظه گیری بالا در دریافت Event های صادر شده از داخل JS در Delphi
سلام
در اون روش ارائه شده در سه پست بالاتر از این، در مورد دریافت Event های صادر شده از داخل JS در Delphi انگار مشکلی وجود داره !!!؟
مثلا تو یه کاربرد خاص فرض کنید، در سمت JS در داخل یک Timer بطور مداوم event رو فراخوانی کنیم، در اینصورت میزان حافظه مصرفی VM Size برنامه همین جور، بی رویه میره بالا و تا جایی میرسه که Application هنگ میکنه !!! این VM Size رو توی Task Manager میشه چک کرد.
نمیدونم مشکل کار تو داخل خود کلاسهای Chromium هستش یا اینکه روش بالا مشکلی داره ؟
جستجو هم کردم اما به چیزی خاصی نرسیدم !!!