我需要编写一个在其中使用浏览器组件的 Windows 应用程序。我选择了 RAD Studio 的 C++ Builder,因为我过去已经使用过它,但是,我在 C++ 编程方面的经验不如我在 web-dev 方面的经验丰富(我主要是 web 开发人员:JS、PHP 等...),所以,我在实现我的项目时遇到了一些问题。我希望,我错过了 C++ 专业专家可以尽快解决的一些非常基本的问题。
内置的 TWebBroswer 组件有很多缺点,所以我决定使用 Chromium ( https://github.com/hgourvest/dcef3 )。安装它并使它不仅在 Delphi 中工作,而且在 C++ Builder 中也需要花费时间,但是,我有一个 TChromium 项目,目前可以编译并正常工作:我可以浏览页面,执行 JS和更多。
尽管如此,我仍然无法解决一个问题:访问文档的 DOM。在 Google 搜索结果中,我发现没有任何帮助:一个有相同问题但没有答案的主题(http://www.cyberforum.ru/cpp-builder/thread996496.html)和文档。
在文档中,有人说我必须为此目的使用 VisitDom 方法,但我不知道如何在 C++ Builder 中执行此操作。
在此 C++ 演示中:https ://code.google.com/p/chromiumembedded/source/browse/trunk/cef3/tests/cefclient/dom_test.cpp?r=689我看到以下代码:
class ClientDOMVisitor : public CefDOMVisitor {
public:
ClientDOMVisitor() {
}
virtual void Visit(CefRefPtr<CefDOMDocument> document) OVERRIDE {
// Register a click listener for the button.
CefRefPtr<CefDOMNode> button = document->GetElementById("button");
ASSERT(button.get());
button->AddEventListener("click", new ClientDOMEventListener(), false);
}
IMPLEMENT_REFCOUNTING(ClientDOMVisitor);
};
然后,在 VisitDom 方法中:
VisitDOM(new ClientDOMVisitor)
当我试图编译这段代码时,会发生错误(在 C++ Builder 中),例如:
[BCC32 Error] Unit1.cpp(184): E2303 Type name expected
后来,我尝试使用来自这个主题的建议(不是 DOMVisitor - StringVisitor,但我认为,如果我能让其中一个工作,我对第二个没有问题):https ://groups.google.com /forum/#!msg/delphichromiumembedded/DckdcKOCLzw/-zgUXOUTXa4J它是用Delphi编写的,所以我不确定我是否正确地将代码翻译成C++。
在 Unit1.h 中,我已按照讨论将 ICefStringVisitor 添加到 TForm1,并将 Visit 方法添加到私有声明部分:
class TForm1 : public TForm, ICefStringVisitor
{
__published: // IDE-managed Components
// ... I've hide a part of code, nothing useful here ...
TChromium *Chromium1;
void __fastcall Chromium1BeforeBrowse(TObject *Sender, const ICefBrowser *browser,
const ICefFrame *frame, const ICefRequest *request, bool isRedirect,
bool Result);
void __fastcall Chromium1LoadEnd(TObject *Sender, const ICefBrowser *browser, const ICefFrame *frame,
int httpStatusCode);
private: // User declarations
void __fastcall Visit(const UnicodeString str);
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
在 Unit1.cpp 我添加了:
void __fastcall TForm1::Visit(const UnicodeString str)
{
ShowMessage(str);
}
void __fastcall TForm1::Chromium1LoadEnd(TObject *Sender, const ICefBrowser *browser, const ICefFrame *frame, int httpStatusCode)
{
ICefFrame * ncFrame = const_cast<ICefFrame *>(frame);
// doesn't compile without const_cast
ncFrame->GetSource(this);
}
此代码编译并运行,但我立即收到此错误并且应用程序终止:
Pure virtual function called
我厌倦了为此而挣扎。任何有经验的人都可以建议我如何在 RAD Studio C++ Builder 中使用所有这些 VisitDom、ViewSource 和其他方法吗?正如我所见,在 Delpi 中,这相当容易。
PS如果它会有所帮助,在ceflib.hpp中我发现了以下声明:
__interface ICefDomVisitor;
typedef System::DelphiInterface<ICefDomVisitor> _di_ICefDomVisitor;
__interface INTERFACE_UUID("{8FD3D3A6-EA3A-4A72-8501-0276BD5C3D1D}") ICefFrame : public ICefBase
{
public:
virtual bool __fastcall IsValid(void) = 0 ;
virtual void __fastcall Undo(void) = 0 ;
virtual void __fastcall Redo(void) = 0 ;
virtual void __fastcall Cut(void) = 0 ;
virtual void __fastcall Copy(void) = 0 ;
virtual void __fastcall Paste(void) = 0 ;
virtual void __fastcall Del(void) = 0 ;
virtual void __fastcall SelectAll(void) = 0 ;
virtual void __fastcall ViewSource(void) = 0 ;
virtual void __fastcall GetSource(const _di_ICefStringVisitor visitor) = 0 ;
virtual void __fastcall GetSourceProc(const _di_TCefStringVisitorProc proc) = 0 ;
virtual void __fastcall GetText(const _di_ICefStringVisitor visitor) = 0 ;
virtual void __fastcall GetTextProc(const _di_TCefStringVisitorProc proc) = 0 ;
virtual void __fastcall LoadRequest(const _di_ICefRequest request) = 0 ;
virtual void __fastcall LoadUrl(const ustring url) = 0 ;
virtual void __fastcall LoadString(const ustring str, const ustring url) = 0 ;
virtual void __fastcall ExecuteJavaScript(const ustring code, const ustring scriptUrl, int startLine) = 0 ;
virtual bool __fastcall IsMain(void) = 0 ;
virtual bool __fastcall IsFocused(void) = 0 ;
virtual ustring __fastcall GetName(void) = 0 ;
virtual __int64 __fastcall GetIdentifier(void) = 0 ;
virtual _di_ICefFrame __fastcall GetParent(void) = 0 ;
virtual ustring __fastcall GetUrl(void) = 0 ;
virtual _di_ICefBrowser __fastcall GetBrowser(void) = 0 ;
virtual _di_ICefv8Context __fastcall GetV8Context(void) = 0 ;
virtual void __fastcall VisitDom(const _di_ICefDomVisitor visitor) = 0 ;
virtual void __fastcall VisitDomProc(const _di_TCefDomVisitorProc proc) = 0 ;
__property ustring Name = {read=GetName};
__property ustring Url = {read=GetUrl};
__property _di_ICefBrowser Browser = {read=GetBrowser};
__property _di_ICefFrame Parent = {read=GetParent};
};