Delphi3 เริ่มมีองค์ประกอบ TwebBrowser แต่ปรากฏในรูปแบบของการควบคุม ActiveX ในเวลานั้นและจำเป็นต้องได้รับการแนะนำด้วยตัวเอง แผงส่วนประกอบเปิดอยู่ ฉันมักจะได้ยินว่า Delphi ดุร้ายมาก จะเป็นสิ่งที่น่ารำคาญมากขึ้น
นี่คือประสบการณ์บางอย่างเกี่ยวกับการใช้ TwebBrowser เพื่อสร้างโปรแกรมและตัวอย่างและข้อมูลที่รวบรวมจากอินเทอร์เน็ต
1. การเริ่มต้นและการสรุป
เมื่อคุณดำเนินการวิธีการของ TwebBrowser เพื่อดำเนินการที่ต้องการเช่น Execwb ฯลฯ คุณอาจพบข้อผิดพลาดเช่น "พยายามเปิดใช้งานเป้าหมายที่หายไปที่ไม่ได้ลงทะเบียน" หรือ "Ole Object ไม่ลงทะเบียน" หรือไม่มีข้อผิดพลาด แต่ไม่มีข้อผิดพลาด ยังไม่ได้ทำ เมื่อฉันใช้โปรแกรมนี้ฉันพบว่าบางครั้ง Execwb ทำงานได้ แต่บางครั้งก็ไม่ได้ผล นอกจากนี้ยังเป็นโอกาสโดยบังเอิญที่ฉันรู้ว่าวัตถุ OLE จำเป็นต้องเริ่มต้นและยกเลิก (มีบางสิ่งที่จะเข้าใจ)
ฉันใช้วิธีการที่กล่าวถึงในบทความก่อนหน้าของฉัน "Delphi Program Window Animation & Solutions สำหรับการจัดเรียงแบบปกติ" ในที่สุดก็เสร็จแล้ว! เหตุผลที่ฉันคิดว่าอาจเป็นเพราะ twebbrowser เป็นวัตถุ OLE ที่ฝังอยู่และไม่ใช่ VCL ที่เขียนใน Delphi
การเริ่มต้น
Oleinitialize (ไม่มี);
การสรุป
พยายาม
Oleuninitialize;
ยกเว้น
จบ;
ประโยคเหล่านี้จะถูกวางไว้หลังจากข้อความทั้งหมดในหน้าต่างหลักก่อน "สิ้นสุด"
------------------------------------------------------ -----------------------------
2. emptyparam
ใน Delphi 5 วิธีการนำทางของ TwebBrowser มีการโอเวอร์โหลดหลายครั้ง:
ขั้นตอนการนำทาง (URL const: กว้างที่สุด);
ขั้นตอนการนำทาง (URL const: Wridestring; VAR Flags:
Olevariant);
ขั้นตอนการนำทาง (URL const: Wridestring; VAR Flags:
Olevariant;
ขั้นตอนการนำทาง (URL const: Wridestring; VAR Flags:
Olevariant;
Olevariant);
ขั้นตอนการนำทาง (URL const: Wridestring; VAR Flags:
Olevariant;
Olevariant;
ในแอปพลิเคชันจริงเมื่อเรียกใช้วิธีหลังเนื่องจากเราไม่ค่อยใช้พารามิเตอร์หลัง แต่การประกาศฟังก์ชันต้องใช้พารามิเตอร์ตัวแปรวิธีการทั่วไปมีดังนี้:
วาจา
T: Olevariant;
เริ่ม
WebBrowser1.Navigate (Edit1.Text, T, T, T, T, T);
จบ;
เป็นเรื่องยากมากที่จะกำหนดตัวแปร T (และยังมีสถานที่มากมายที่จะใช้) ในความเป็นจริงเราสามารถใช้ emptyparam แทน (emptyparam เป็นตัวแปรที่ว่างเปล่าทั่วไปอย่ากำหนดค่าให้กับมัน) เพียงหนึ่งประโยค:
WebBrowser1.Navigate (Edit1.Text, emptyparam, embtyparam, embtyparam, emptyparam);
แม้ว่ามันจะนานกว่าเล็กน้อย แต่ก็สะดวกกว่าการกำหนดตัวแปรทุกครั้ง แน่นอนว่าวิธีแรกสามารถใช้ได้
WebBrowser1.Navigate (edit1.Text)
------------------------------------------------------ -----------------------------
3. การดำเนินการคำสั่งทั่วไปสามารถทำได้โดยใช้วิธีการ EXECWB
ขั้นตอน execwb (cmdid: olecmdid; cmdexecopt:
Olecmdexecopt);
ขั้นตอน execwb (cmdid: olecmdid; cmdexecopt: olecmdexecopt;
var pvain:
Olevariant);
ขั้นตอนการดำเนินการ (cmdid: rolecmdid; cmdexecopt:
Olecmdexecopt;
Olevariant;
เปิด: กล่องโต้ตอบ "Open Internet Address" จะปรากฏขึ้นและ CommandID คือ Olecmdid_open (ถ้าเวอร์ชันเบราว์เซอร์คือ IE5.0
จากนั้นคำสั่งนี้จะไม่พร้อมใช้งาน)
บันทึกเป็น: เรียกกล่องโต้ตอบบันทึกเป็น
execwb (Olecmdid_saveas, Olecmdexecopt_dodefault,
emptyparam,
emptyparam);
พิมพ์, การพิมพ์ตัวอย่างและการตั้งค่าหน้า: โทร "พิมพ์", "Print Preview" และ "การตั้งค่าหน้า" (IE5.5 ขึ้นไปรองรับรุ่น "ประเภท" เท่านั้น
พิมพ์ตัวอย่างดังนั้นการใช้งานควรตรวจสอบว่ามีคำสั่งนี้หรือไม่)
execwb (Olecmdid_print, Olecmdexecopt_dodefault,
emptyparam,
emptyparam);
ถ้า querystatuswb (OLECMDID_PRINTPREVIEW) = 3 แล้ว
execwb (OLECMDID_PRINTPREVIEW, OLECMDEXECOPT_DODEFAULT,
emptyparam, emptyparam);
execwb (OLECMDID_PAGESETUP, OLECMDEXECOPT_DODEFAULT,
emptyparam,
emptyparam);
ตัด, คัดลอก, วาง, เลือกทั้งหมด: ไม่จำเป็นต้องพูดมากเกี่ยวกับฟังก์ชั่นเป็นสิ่งสำคัญที่จะต้องทราบว่าการตัดและการวางไม่เพียง แต่ให้ข้อความสำหรับการแก้ไขเฟรม แต่ยังไม่ได้แก้ไขบนหน้าเว็บ
ข้อความของกล่องแก้ไขก็มีประสิทธิภาพเช่นกัน รับสถานะการเปิดใช้งานคำสั่ง
มีสองวิธีในการดำเนินการคำสั่ง (การคัดลอกเป็นตัวอย่างการตัดการวางและการเลือกทั้งหมดจะแทนที่คำหลักที่เกี่ยวข้อง
เพียงแค่เปลี่ยนมันคือตัดวางและเลือกทั้งหมดตามลำดับ):
A. ใช้วิธีการ querystatuswb ของ twebbrowser
if (querystatuswb (olecmdid_copy) = olecmdf_enabled) หรือ
Olecmdf_supported) จากนั้น
execwb (olecmdid_copy, olecmdexecopt_dodefault,
emptyparam,
emptyparam);
B. ใช้วิธีการ queryCommandEnabled ของ IHTMLDOCUMENT2
วาจา
หมอ: Ihtmldocument2;
เริ่ม
DOC: = WebBrowser1.Document เป็น IHTMLDOCUMENT2;
ถ้า doc.QueryCommandEnabled ('Copy') แล้ว
doc.execcommand ('คัดลอก', false, emptyparam);
จบ;
ค้นหา: อ้างถึงฟังก์ชั่น "ค้นหา" ที่เก้า
------------------------------------------------------ -----------------------------
4. ขนาดตัวอักษร
คล้ายกับห้ารายการจาก "สูงสุด" ถึง "ขั้นต่ำ" ในเมนู "ตัวอักษร" (สอดคล้องกับจำนวนเต็ม 0 ~ 4 ที่ใหญ่ที่สุด ฯลฯ สมมติว่าชื่อของรายการเมนูห้ารายการมีดังนี้แท็ก
คุณสมบัติถูกตั้งค่าเป็น 0 ~ 4 ตามลำดับ)
A. อ่านขนาดตัวอักษรของหน้าปัจจุบัน
วาจา
T: Olevariant;
เริ่ม
WebBrowser1.execwb (Olecmdid_zoom,
OLECMDEXECOPT_DONTPROMPTUSER
emptyparam, t);
กรณี t ของ
4: ใหญ่ที่สุดตรวจสอบ: = จริง;
3: ใหญ่กว่าตรวจสอบ: = จริง;
2: Middle.Checked: = true;
1: เล็กตรวจสอบ: = true;
0: เล็กที่สุดตรวจสอบ: = จริง;
จบ;
จบ;
B. ตั้งค่าขนาดตัวอักษรหน้า
ใหญ่ที่สุดตรวจสอบ: = เท็จ;
ใหญ่กว่าตรวจสอบ: = เท็จ;
Middle.Checked: = false;
เล็กตรวจสอบ: = เท็จ;
เล็กที่สุดตรวจสอบ: = เท็จ;
tmenuitem (ผู้ส่ง) ตรวจสอบ: = true;
t: = tmenuitem (ผู้ส่ง) .tag;
WebBrowser1.execwb (Olecmdid_zoom,
OLECMDEXECOPT_DONTPROMPTUSER
t, t);
------------------------------------------------------ -----------------------------
5. เพิ่มในรายการโปรดและจัดรายการโปรด
const
clsid_shelluihelper: tguid =
'{64AB4BB7-111E-11D1-8F79-00C04FC2FBE1}';
วาจา
P: ขั้นตอน (Handle: Thandle; Path: Pchar);
ขั้นตอน TFORM1.OrganizeFavorite (ผู้ส่ง: TOBJECT);
วาจา
H: hwnd;
เริ่ม
h: = loadlibrary (pchar ('shdocvw.dll'));
ถ้า h <> 0 แล้ว
เริ่ม
P: = getProcaddress (h, pchar ('doorganizefavdlg'));
หากได้รับมอบหมาย (p) แล้ว p (application.handle,
pchar (favfolder));
จบ;
Freelibrary (H);
จบ;
ขั้นตอน tform1.addfavorite (ผู้ส่ง: tobject);
วาจา
shelluihelper: ishelluihelper;
URL ชื่อ: Olevariant;
เริ่ม
ชื่อเรื่อง: = WebBrowser1.LocationName;
URL: = WebBrowser1.locationUrl;
ถ้า url <> '' แล้ว
เริ่ม
shelluihelper: = createComObject (clsid_shelluihelper) AS
Ishelluihelper;
shelluihelper.addfavorite (url, title);
จบ;
จบ;
วิธีการใช้วิธีการด้านบนเพื่อเปิดกล่องโต้ตอบ "เพิ่มลงในรายการโปรด" ผ่านอินเตอร์เฟส Ishelluihelper นั้นค่อนข้างง่าย แต่มีข้อเสียเปรียบนั่นคือหน้าต่างที่เปิดไม่ใช่หน้าต่างโหมด แต่เป็นอิสระจากแอปพลิเคชัน เป็นไปได้ว่าถ้าคุณใช้วิธีเดียวกับขั้นตอนการจัดระเบียบเพื่อเปิดกล่องโต้ตอบคุณสามารถใช้หน้าต่างโหมดตามธรรมชาติเพราะคุณสามารถระบุที่จับของหน้าต่างพาเรนต์ (เอฟเฟกต์เหมือนกับการเปิด "เพิ่มไปยังที่ชื่นชอบ" กล่องโต้ตอบใน Explorer และ IE) เห็นได้ชัดว่าปัญหานี้ มันไม่สำคัญว่ามันเป็นหน้าต่างรูปแบบหรือไม่)
กระบวนการต่อไปนี้จะบอกต้นแบบฟังก์ชันของ doaddtofavdlg ควรสังเกตว่ากล่องโต้ตอบที่เปิดด้วยวิธีนี้ไม่ได้ดำเนินการ "เพิ่มในรายการโปรด" ต้องการวางทางลัดอินเทอร์เน็ต
ขั้นตอน tform1.addfavorite (เช่น: tembeddedwb);
ขั้นตอน createUrl (Aurlpath, Aurl: PCHAR);
วาจา
urlfile: Tinifile;
เริ่ม
urlfile: = tinifile.create (สตริง (aurlpath));
rlfile.writestring ('internetshortcut', 'url',
สตริง (aurl));
rlfile.free;
จบ;
วาจา
addfav: ฟังก์ชั่น (ด้าม: thandle;
urlpath: pchar;
ชื่อเรื่อง: pchar;
FavidList: PitemidList): BOOL;
FDOC: ihtmldocument2;
urlpath, url, ชื่อ: array [0..max_path] ของถ่าน;
H: hwnd;
PIDL: PitemidList;
Fretok: บูล;
เริ่ม
fdoc: = ihtmldocument2 (เช่น. document);
ถ้า fdoc = nil จากนั้นออก;
strpcopy (ชื่อ, fdoc.get_title);
strpcopy (url, fdoc.get_url);
ถ้า url <> '' แล้ว
เริ่ม
h: = loadlibrary (pchar ('shdocvw.dll'));
ถ้า h <> 0 แล้ว
เริ่ม
shgetspecialfolderLocation (0, csidl_favorites, pidl);
addfav: = getProcaddress (H, pchar ('doaddtofavdlg'));
ถ้าได้รับมอบหมาย (addfav) แล้ว
fretok: = addfav (มือจับ, urlpath, sizeof (urlpath),
ชื่อเรื่องขนาด (ชื่อ) PIDL)
จบ;
Freelibrary (H);
ถ้า fretok แล้ว
createurl (urlpath, url);
จบ
จบ;
------------------------------------------------------ -----------------------------
6. ทำให้ WebBrowser Focus
TwebBrowser นั้นพิเศษมาก
Explorer มีคีย์ลัดโซลูชันมีดังนี้:
ขั้นตอน TFORM1.SetFocustodoc;
เริ่ม
ถ้า webBrowser1.Document <> nil แล้ว
ด้วย webBrowser1.Application as ioleobject ทำ
Doverb (oleiverb_uiactivate, nil, webBrowser1, 0, handle
getClientRect);
จบ;
นอกจากนั้นฉันยังพบวิธีที่ง่ายกว่าซึ่งอยู่ที่นี่:
ถ้า webBrowser1.Document <> nil แล้ว
ihtmlwindow2 (ihtmldocument2 (webBrowser1.Document) .ParentWindow) .focus
เพิ่งพบวิธีที่ง่ายกว่านี้อาจเป็นวิธีที่ง่ายที่สุด:
ถ้า webBrowser1.Document <> nil แล้ว
ihtmlWindow4 (webBrowser1.Document) .focus
นอกจากนี้คุณต้องพิจารณาว่าเอกสารได้รับโฟกัสหรือไม่:
ถ้า ihtmlwindow4 (WebBrowser1.Document) .hasfocus แล้ว
------------------------------------------------------ -----------------------------
7. คลิกปุ่ม "ส่ง"
เช่นเดียวกับปุ่ม "เริ่มต้น" ในแต่ละฟอร์มในโปรแกรมแต่ละแบบฟอร์มบนหน้าเว็บยังมีปุ่ม "เริ่มต้น" นั่นคือปุ่มที่มีแอตทริบิวต์ "ส่ง" เทียบเท่ากับการคลิก "ส่ง" บนเมาส์ อย่างไรก็ตาม TwebBrowser ดูเหมือนจะไม่ตอบสนองต่อคีย์ ENTER และแม้ว่า keypreview ของแบบฟอร์มที่มี TwebBrowser จะถูกตั้งค่าเป็นจริงปุ่มที่ส่งโดยผู้ใช้ไปยัง TwebBrowser ไม่สามารถสกัดกั้นในเหตุการณ์คีย์บอร์ดของแบบฟอร์มได้
ทางออกของฉันคือการใช้ส่วนประกอบ ApplicatineVents หรือเขียนเหตุการณ์ onMessage ของวัตถุ tapplication ด้วยตัวเองตัดสินประเภทข้อความและตอบกลับข้อความคีย์บอร์ด สำหรับการคลิกที่ปุ่ม "ส่ง" คุณสามารถทำได้โดยการวิเคราะห์ซอร์สโค้ดเว็บ แต่ฉันพบวิธีที่ง่ายและเร็วขึ้น มีคนอื่นเขียน
A. ใช้ฟังก์ชัน SendKeys เพื่อส่งปุ่ม Enter ไปยัง WebBrowser
ใน Delphi
5 มีไฟล์ SNDKEY32.PAS ในไดเรกทอรีข้อมูล/extras/sendkeys บนซีดีซึ่งมีสองฟังก์ชั่น SendKeys และ appactivate มันง่ายมาก
SendKeys ('~', true); // กดปุ่ม Return
คำอธิบายพารามิเตอร์โดยละเอียดของฟังก์ชัน SendKeys ฯลฯ รวมอยู่ในไฟล์ SNDKEY32.PAS
B. ส่งข้อความคีย์บอร์ดที่ได้รับไปยัง WebBrowser ในเหตุการณ์ OnMessage
โพรซีเดอร์ TFORM1.ApplicationEvents1Message (var msg: tmsg;
VAR จัดการ: บูลีน);
{แก้ไขความผิดปกติของคีย์ภายใน webBrowser
ควบคุม}
const
stdkeys = [vk_tab, vk_return];
extkeys = [vk_delete, vk_back, vk_left, vk_right];
คีย์ขยาย}
fextended = $ 01000000;
เริ่ม
จัดการ: = false;
ด้วยผงชูรสทำ
if ((ข้อความ> = wm_keyfirst) และ (ข้อความ <= wm_keylast))
และ
((wparam ใน stdkeys) หรือ
{$ ifdef ver120} (getKeyState (vk_control) <0) หรือ {$ endif}
(wparam ใน extkeys) และ
((lparam และ fextended) = fextended)) จากนั้น
พยายาม
ถ้า ischild (handle, hwnd) จากนั้น {จัดการเบราว์เซอร์ทั้งหมด
ข้อความที่เกี่ยวข้อง}
เริ่ม
ด้วย {$ ifdef
แอปพลิเคชัน ver120} _ {$ else} แอปพลิเคชัน {$ endif} AS
ioleinplaceactiveObject ทำ
จัดการ: = translateAccelerator (msg) = s_ok;
ถ้าไม่จัดการแล้ว
เริ่ม
จัดการ: = จริง;
TranslateMessage (MSG);
DispatchMessage (MSG);
จบ;
จบ;
ยกเว้น
จบ;
สิ้นสุด;
(วิธีนี้มาจาก embeddedwb.pas)
------------------------------------------------------ -----------------------------
8. รับซอร์สโค้ดหน้าเว็บและ HTML โดยตรงจาก TwebBrowser
ก่อนอื่นแนะนำวิธีที่ง่ายมากเพื่อรับซอร์สโค้ดของหน้าเว็บที่ TwebBrowser เข้าถึง วิธีการทั่วไปคือการใช้อินเทอร์เฟซ empersistStreaminit ที่จัดทำโดยวัตถุเอกสารในการควบคุม TwebBrowser เพื่อนำไปใช้งาน ขนาดซอร์สโค้ด HTML จัดสรรบล็อกหน่วยความจำ Global HEAP สร้างสตรีมจากนั้นเขียนข้อความ HTML ลงในสตรีม แม้ว่าโปรแกรมจะไม่ซับซ้อน แต่ก็มีวิธีการที่ง่ายกว่าดังนั้นรหัสการใช้งานจึงไม่ได้รับอีกต่อไป ในความเป็นจริงโดยทั่วไปฟังก์ชั่น IE ทั้งหมด twebbrowser ควรมีวิธีที่ค่อนข้างง่ายในการใช้งานและสิ่งเดียวกันนี้เป็นจริงสำหรับการได้รับซอร์สโค้ดหน้าเว็บ รหัสต่อไปนี้แสดงซอร์สโค้ดหน้าเว็บใน memo1
memo1.lines.add (ihtmldocument2 (webBrowser1.Document) .body.outerhtml);
ในเวลาเดียวกันมันเป็นเรื่องง่ายมากที่จะบันทึกไฟล์ HTML เป็นไฟล์ข้อความเมื่อเรียกดู TwebBrowser และไม่จำเป็นต้องใช้เครื่องมือการแยกวิเคราะห์ไวยากรณ์เนื่องจาก TwebBrowser เสร็จสมบูรณ์ดังนี้:
memo1.lines.add (ihtmldocument2 (webBrowser1.Document) .body.outertext);
------------------------------------------------------ -----------------------------
9. ฟังก์ชั่น "ค้นหา"
กล่องโต้ตอบการค้นหาสามารถเรียกได้โดยการกดปุ่ม CTRL-F เมื่อเอกสารได้รับการโฟกัส โปรแกรมที่จะทำ
วาจา
หมอ: Ihtmldocument2;
txtrange: ihtmltxtrange;
เริ่ม
DOC: = WebBrowser1.Document เป็น IHTMLDOCUMENT2;
doc.selectall;
// ประโยคนี้มีความสำคัญอย่างยิ่งเนื่องจากหลักฐานที่สามารถใช้งานได้
// เอกสารมีพื้นที่เลือกข้อความอยู่แล้ว เนื่องจากคำสั่งต่อไปนี้ดำเนินการ
// ดูกระบวนการเลือกเอกสารทั้งหมด
txtrange: = doc.selection.createrange เป็น ihtmltxtrange;
txTrange.findText ('ข้อความที่จะค้นหา', 0.0);
txTrange.Select;
จบ;
นอกจากนี้คุณสามารถรับเนื้อหาข้อความที่เลือกในปัจจุบันจาก txt.get_text ซึ่งมีประโยชน์ในบางจุด
------------------------------------------------------ -----------------------------
10. แยกลิงค์ทั้งหมดในหน้าเว็บ
วิธีนี้มาจากเพื่อนของฟอรัม Monopoly Forum Hopfield ตอบคำถาม
วาจา
หมอ: Ihtmldocument2;
ทั้งหมด: ihtmlelementcollection;
Len, I: จำนวนเต็ม;
รายการ: Olevariant;
เริ่ม
DOC: = WebBrowser1 .document เป็น ihtmldocument2;
ทั้งหมด: = doc.get_links;
Len: = all.length;
สำหรับ i: = 0 ถึง len-1 เริ่มต้น
รายการ: = all.item (i, varempty);
memo1.lines.add (item.href);
จบ;
จบ;
------------------------------------------------------ -----------------------------
11. ตั้งค่าการเข้ารหัสของ twebbrowser
ทำไมฉันถึงพลาดโอกาสมากมายเสมอ? ในความเป็นจริงฉันควรจะคิดถึงมันเป็นเวลานาน แต่ความแตกต่างในความคิดจะทำให้โลกแตกต่าง ถ้าฉันคิดเกี่ยวกับมันมากขึ้นและลองมากขึ้นมันจะไม่ได้รับการจัดอันดับที่ 11 นี่คือฟังก์ชั่นซึ่งง่ายต่อการแก้ปัญหาอย่างไม่น่าเชื่อ
ขั้นตอน SetCharset (AwebBrowser: TwebBrowser; AcharSet:
สตริง);
วาจา
Refreshlevel: Olevariant;
เริ่ม
ihtmldocument2 (awebbrowser.document) .set_charset (acharset);
Refreshlevel: = 7; // 7 นี้ควรมาจากรีจิสทรีเพื่อช่วยเหลือข้อบกพร่อง
AWEBBROWSER.REFRESH2 (Refreshlevel);
จบ;