Keywords: Add to Favorites dialog, modal window, ishelluihelper, doaddtofavdlg, doorganizefavdlg
1 Overview
Call the Add to Favorites dialog (as follows) There is different from the calling "Finishing Favorites" dialog, the former is more complicated than the latter. Adding a link to a favorite clip After saving the link, it may also have the setting of offline access, from IE 4.0 to IE 5.0, and some changes have changed.
2, iShelluiHelper interface Microsoft specializes in interface ishelluihelper to implement access to some features of Windows Shell API, adding links to favorites, is one of them, is the following addFavorite function.
HRESULT IshelluiHelper :: Addfavorite (BSTR URL, VARIANT * TITLE);
The instance code is as follows:
void CMyHtmlView :: OnAddToFavorites () {IShellUIHelper * pShellUIHelper; HRESULT hr = CoCreateInstance (CLSID_ShellUIHelper, NULL, CLSCTX_INPROC_SERVER, IID_IShellUIHelper, (LPVOID *) & pShellUIHelper);
IF (succeeded (hr)) {_variant_t vttitle (gettitle (). allocsysString ()); cstring strurl = m_webbrowser.getlocationURL ();
Pshelluihelper-> addfavorite (Strurl.allocsystring (), & vttitle); pshelluihelper-> release ();}}
We noticed that the "addfavorite" function here does not require a parent window handle as "doorganizefavdlg". This also causes the "Add to Favorites" dialog that is displayed in IE, "Add to Favorites" dialog box displayed through the ISHELLUIHELPER interface is "non-modal", with a taskbar button independent of our application, which makes our browser It seems very unprofessional (I am a person who pursues perfection, this is one of the reasons why my browser is delayed). So we naturally think that "ShDocvw.dll" except "doorganizefavdlg", there should be a similar function, you can pass a parent window handle to display the modal window, perhaps like this:
TypedEf uint (Callback * lpfnaddfav) (HWND, LPTSTR, LPTSTSTSTS);
In fact, such a function does exist in "SHDOCVW.DLL", "doaddtofavdlg".
3, the DoaddTofavdlg function "DoaddTofavdlg" function is also one of the functions exposed "Shdocvw.dll", whose prototype is as follows: typedef Bool (Callback * Lpfnaddfav) (HWND, Tchar *, UINT, TCHAR *, UINT, LPITEMIDLIST); first Parameters are the parent window handle, the second and fourth parameters are the initial directory (generally the collection of favorites) and the name of the link to add (such as the Title of the web), the third and the first The five parameters are the lengths of the second and fourth buffers, and the last parameter is a pointer (PIDL) that points to the Item Identifier List associated with the second parameter directory. But the most strange thing is that there is no link URL like "addfavorite" function, how is the link added? The answer is "manually created".
The second parameter will contain a complete link path name (such as "x: /xxx/mylink.ur") in the Add to Favorites dialog box (such as "x: /xxx/mylink.ur") in the Add to Favorites dialog box, and we will The URL of the web page is to create a link, the code is as follows (for simplification, save "Shdocvw.dll" has been in memory, see "Internet Explorer programming (3)" Squain Collection "dialog box") : void CMyHtmlView :: OnFavAddtofav () {typedef BOOL (CALLBACK * LPFNADDFAV) (HWND, TCHAR *, UINT, TCHAR *, UINT, LPITEMIDLIST); HMODULE hMod = (HMODULE) LoadLibrary ( "shdocvw.dll"); if (hMod ) {LPFNADDFAV lpfnDoAddToFavDlg = (LPFNADDFAV) GetProcAddress (hMod, "DoAddToFavDlg"); if (lpfnDoAddToFavDlg) {TCHAR szPath [MAX_PATH]; LPITEMIDLIST pidlFavorites; if (SHGetSpecialFolderPath (NULL, szPath, CSIDL_FAVORITES, TRUE) && (SUCCEEDED (SHGetSpecialFolderLocation (NULL , CSIDL_FAVORITES, & pidlFavorites)))) {TCHAR szTitle [MAX_PATH]; strcpy (szTitle, GetLocationName ()); TCHAR szURL [MAX_PATH]; strcpy (szURL, GetLocationURL ()); BOOL bOK = lpfnDoAddToFavDlg (m_hWnd, szPath, sizeof ( Szpath) / sizeof (Szpath [0]), SZTITLE, SIZEOF (SZTITLE) / SIZEOF (Sztitl e [0]), pidlFavorites); CoTaskMemFree (pidlFavorites); if (bOK) CreateInternetShortcut (szURL, szPath, ""); // Create Shortcut Internet}} FreeLibrary (hMod);} return;} function creates Internet achieve CreateInternetShortcut Shortcuts, you can use the method of reading the INI file, but better is the use of the IUNIFORMRESOLOCATOR interface.
HRESULT CMyHtmlView :: CreateInternetShortcut (LPCSTR pszURL, LPCSTR pszURLfilename, LPCSTR szDescription, LPCTSTR szIconFile, int nIndex) {HRESULT hres; CoInitialize (NULL); IUniformResourceLocator * pHook; hres = CoCreateInstance (CLSID_InternetShortcut, NULL, CLSCTX_INPROC_SERVER, IID_IUniformResourceLocator, (void ** ) & pHook); if (SUCCEEDED (hres)) {IPersistFile * ppf; IShellLink * psl; // Query IShellLink for the IPersistFile interface for hres = pHook-> QueryInterface (IID_IPersistFile, (void **) & ppf); hres = pHook- > Queryinterface (iid_ishelllink, (void **) & psl); if (successded (hres)) {Word WSZ [Max_Path]; // Buffer for unicode string // set the path to the shortcut target. Phook-> seturl (pszurl, 0); hres = psl-> seticonlocation (Sziconfile, Nindex); if (successded (hres)) {// set the description of the shortcut. Hres = psl-> setdescription (SUCCEEDEDED) { // EnSure That the string consists of ansi characters. Multi ByTetowideChar (cp_acp, 0, pszurlfilename, -1, wsz, max_path); // Save the Shortcut via the ipersistfile :: save member function. Hres = ppf-> save (wsz, true);}} // Release the Pointer To Ipf-> release (); psl-> release ();} // Release the pointer to ishelllink. Phook-> release ();} Return hres;} Good, the above method is trouble, but finally solved The "modal window" problem makes our procedure not to despise users. But the problem is coming, we found that "Allow Untiling" is disabled, "Custom" is not talked, although 90% of people have not used IE offline browsing. Do we want to be shattered? We don't have to create a link as you don't have to manually create a link. On the one hand, it is necessary to modally display the window, just like IE, you can customize offline browsing. 4. Script Mode Many web pages will have a button or link "Add this page to Favorites", which actually adds web pages to your favorites through the following script display mode "Add to Favorites" dialog box.
Window.External.addfavorite (location.href, document.title); here's the WebBrowser built-in COM automation object to implement the extension of the Document Object Model (DOM) (we can also implement your own extension via IDochostuiHandler). Checking MSDN can learn that the method of the External object is the same as the method provided by the ISHELLUIHELPER interface. We have reason to believe that iShelluiHelper provides access to WebBrowser's built-in External objects, if you create an instance of the ISHELLUIHELPER interface in the appropriate place, you may call the "AddFavorite" function to display the modal dialog. The problem is that we have not found such a place. From the script from the above, we naturally think another way. If you can make the web page to perform the above script, isn't it a problem? Just do as follows: void CMyHtmlView :: OnFavAddtofav () {CString strUrl = GetLocationURL (); CString strTitle = GetLocationName (); CString strjs = "javascript: window.external.AddFavorite ( '" strUrl "'," "'" strtitle ");"; EXECScript (strjs);} void cmieview :: execScript (cstract strjs) {ccomqiptrphtmldoc = (htmldocument2 *) gethtmlDocument ();
IF (PHTMLDoc! = null)
{
CCOMQIPTR
PHTMLWND;
PHTMLDOC-> GET_PARENTWINDOW (& phtmlwnd);
IF (phtmlwnd! = null)
{
CCOMBSTR BSTRJS = Strjs.allocsystring ();
CCOMBSTR BSTRLAN = SysallocString (L "JavaScript");
Variant varret;
PHTMLWND-> EXECScript (BSTRJS, BSTRLAN, & VARRET);
}
}
}
First obtain the parent window of the document from ChtmlView, the pointer of the parent window of the document, then call its method ExecScript to perform the script (in fact, any script can be performed). The test found that this method is very effective, not only the window is modal, but also does not need to manually create a link, but more importantly, "Allow Upline" and "Custom" buttons can also be used. 5, the problem still does not resolve the execution script looks effective, and once our program implements AdochostuiHandler interface to advance the webbrowser, it will find that once the execution script contains the call to the "External" object, it will appear " A script error for missing objects. The reason is that when the MSHTML parsing engine (not WebBrowser) checks the host interface, its getExternal method is called to obtain a reference to an automation interface to extend the DOM. HRESULT IDOCHOSTUIHANDAL :: getExternal (idispatch ** ppdispatch) but sometimes we did not want to extend DOM, and we also hope that WebBrowser uses its own DOM extension. The bad is the documentation of the getExternal method, saying that PPDisPatch must be set to null, in other words, WebBrowser does not have the built-in External object, then our window.external.addfavorite has become ubiquitous . I have tried to find the external External object built into WebBrowser, although there is no success, but the method of solving the problem is found. 6. Perfect solution Webbrowser built-in External objects we can't find, but it must exist, we just want to let WebBrowser have completed itself. Realization is very simple, find the handle of the "Internet Explorer_server" window included in WebBrowser, and send a message. The following code assumes that m_hwndie is the handle of the Internet Explorer_server window. #define id_ie_id_addfav 2261 :: SendMessage (m_hwndie, wm_command, makewparam (ket_ie_id_addfav), 0x0), 0); Test a test result, is it the same as the "Add to Favorites" in Internet Explorer. As for why do this, follow-up article. Reference: MSDN: Adding Internet Explorer Favorites To Your Application MSDN: ISHELLUIHELPER InterfaceMsDN: External ObjectMsDN: IDOchostuiHandler Interface Reference Address: Internet Explorer Programming (4) Add to Favorites dialog