Keyword: HTML element, sink
1. After resuing webbrowser is implemented, we will find that sometimes we still need to process the elements (HTML element) in the browser ). This kind of processing includes two aspects: active and passive, such as "FAQ: how to access the webbrowser scroll bar", "FAQ: Operate the drop-down list", and "FAQ: two methods to access Multi-layer nested frame, and other articles demonstrate active processing. Generally, we obtain a Web Document Interface (ihtmldocumentx) from webbrowser, from which we can access all HTML elements contained in the browser. Passive processing is called sink in COM technology, and I prefer event notification. When the document download progress changes, we can get the progresschange notification. When webbrowser downloads the HTML document, we can get the documentcomplete notification. When the link is clicked, or how do we receive notifications when an image is dragged? This article hopes to provide some answers. 2. How htmlobj template sink an HTML element is not the focus of this article. I am not very familiar with the theory or too lazy to thoroughly understand it, so I use a ready-made library for implementation. The chtmlobj template in a codeproject article is very useful. The following example is an instantiation of HTML anchor element.
# Include "htmlobj. H" class chtmlanchorelement: Public chtmlobj <ihtmlanchorelement, & diid_htmlanchorevents> {public: chtmlanchorelement (chtmldocument2 * pparentdoc2); Virtual ~ Break (); Virtual hresult oninvoke (dispid dispidmember, refiid riid, lcid, word wflags, dispparams * blocks, variant * pvarresult, interval info * p1_info, uint * puargerr );}; hresult identifier: oninvoke (dispid identifier, refiid riid, lcid, word wflags, dispparams * identifier, variant * pvarresult, interval info * p1_info, uint * puargerr) {hresult hR = e_notimpl; switch (dispidmember) {Case dispid_htmlelementevents_onmouseover: {// when the mouse goes through the link, we will be notified here hR = s_ OK; // todo: Add code to handle on mouse over eventsbreak ;} case dispid_htmlelementevents_onmouseout: {// when the mouse is removed from the link, we will receive a notification here. For other dispatch IDs, you can add hR = s_ OK as needed; // todo: add code to handle on mouse out eventsbreak;} default: {break;} return hr ;}
When we get the HTML interface pointer of a link, we can call the chtmlanchorelement to inherit from the setsite (iunknown * punksite) member function of chtmlobj to pass in the interface pointer. In the chtmlobj class, a smart pointer m_sphtmlobj is used to save the corresponding HTML element interface pointer. When the onmousehover and onmouseout Event Notifications arrive, all the members of ihtmlanchorelement can be accessed from m_sphtmlobj, for example, the URL obtained from href is not described here. 3. After the chtmlelements class has chtmlobj, we will find that multiple chtmlobj of the same type is often required in practice. For example, a chtmlobj is required to sink the HTML document of each frame in a webpage containing a frame. Therefore, we need to effectively manage these chtmlobj of the same type. The following is a simple template class chtmlelements that I wrote. It uses cmap to manage multiple chtmlobj objects.
Template <class thtmlelement>
ClassChtmlelements {
TypedefCmap <lpdispatch, lpdispatch, thtmlelement *, thtmlelement *> cmapdisptohtmlelement; cmapdisptohtmlelement m_htmlelements; bool issiteconnected (lpdispatch Pdisp) {thtmlelement * pelement;
ReturnM_htmlelements.lookup (Pdisp, pelement );}
Public: Chtmlelements (
Void){}~ Chtmlelements (
Void){}
Public:
VoidSetsite (lpdispatch Pdisp) {If (issiteconnected (Pdisp) // check to avoid unnecessary sinks {
Return;} Thtmlelement * pelement =
NewThtmlelement; // create an instance of the corresponding class through the template type to connect pelement-> setsite (Pdisp); m_htmlelements.setat (Pdisp, pelement );}
// Call clear in the appropriate place to release the managed memory
Void clear (void)
{
Position Pos = m_htmlelements.getstartposition ();
Thtmlelement * pelement = NULL;
Lpdispatch Pdisp = NULL;
While (Pos! = NULL)
{
M_htmlelements.getnextassoc (Pos, Pdisp, pelement );
M_htmlelements.removekey (Pdisp );
Delete pelement;
}
}
};
Suppose we have a chtmldocument2 class derived from chtmlobj like chtmlanchorelement, which is declared as follows when chtmlelements is used:
TypedefChtmlelements <chtmldocument2> chtmlelements;
TypedefChtmlelements <chtmlanchorelement> chtmlanchors;
ClassCmyview:
PublicChtmlview {
Private: Chtmldocuments m_htmldocs; chtmlanchors m_htmlanchors ;}
In documentcomplete, you can connect to the file object in the browser as follows:
VoidCmyview: ondocumentcomplete (lpdispatch Pdisp, lpctstr lpszurl) {m_htmldocs.setsite (Pdisp );}
To connect all the anchor elements in the document at one time, you can use ihtmldocument2: get_anchors to obtain the ihtmlelementcollection containing all the ihtmlanchorelement interface pointers, traverse each element, and call m_htmlanchors.setsite. Of course, the whole link of one-time sink may not be a good note. I prefer to respond to events in chtmldocument2 and access the HTML element of the current position through other means. 4. Conclusion Event Notification in response to HTML elements is a very powerful method for browser programming. It can further control the documents and HTML elements in the browser and implement more advanced functions, for example, the so-called "Super drag-and-drop" (the ghost window browser provides this function, but no browser actually perfectly implements drag-and-drop on URLs, text, and images ). 5. References codeproject: htmlobj template reference address: Internet Explorer programming brief (10) responding to Event Notifications from HTML elements-several useful classes