65.9K
CodeProject 正在变化。 阅读更多。
Home

在您的 WebBrowser 中调用隐藏命令

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.77/5 (15投票s)

2004 年 9 月 12 日

2分钟阅读

viewsIcon

137191

downloadIcon

2281

演示了一种创新的方法来调用隐藏命令,以在你的基于 WebBrowser 的应用程序中显示模态对话框,例如“添加到收藏夹”对话框,“导入/导出向导”对话框。

IE Window Class Names

Demo

引言

通常,当在 MFC 应用程序中宿主 WebBrowser 控件时,我们会调用 `m_pBrowserApp` ( `IWebBrowser2` 接口) 的 `ExecWB` 方法来调用常见的 web 浏览器命令 (缩放浏览器,选择浏览器中的所有文本等)。

我们还调用 `queryInterface` 来获取 `IOleCommandTarget` 接口的 `IDispatch` 指针,并调用它的 `Exec` 方法来调用“在此页面中查找”对话框或“查看源代码”命令。但是仍然存在一些我们**无法**调用的对话框,即“**添加到收藏夹**”对话框,“**导入/导出向导**”对话框。虽然我们可以通过 `IShellUIHelper` 接口调用“AddFavorite”命令和“ImportExportFavorites”命令,但前一个命令会导致一个与应用程序主框架无关的非模态“添加到收藏夹”对话框,而后一个命令的结果非常简单。

本文将介绍一种创新但简单的方法,在你的 web 浏览器中调用**模态**“添加到收藏夹”对话框和**模态**“导入/导出向导”对话框。

背景

这个想法来自 MSDN 中“**WebBrowser 定制**”的 `IDocHostUIHandler::ShowContextMenu` 演示。 `IDocHostUIHandler::ShowContextMenu` 演示向我们展示了从相关资源文件 "SHDOCLC.DLL" 手动构建 IE 上下文菜单并从中删除“**查看源代码**”的方法。代码的关键点是弹出上下文菜单后,它调用 `SendMessage()` API,通过 `WM_COMMAND` 消息将 `TrackPopupMenu()` 返回的 **MenuItem ID** 发送到“**Internet Explorer_Server**”窗口。因此,如果我们获取“添加到收藏夹”命令或“导入/导出向导”命令的 MenuItem ID,我们或许可以解决上述问题。

......
// Show shortcut menu
int iSelection = ::TrackPopupMenu(hMenu,
                                  TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD,
                                  ppt->x,
                                  ppt->y,
                                  0,
                                  hwnd,
                                  (RECT*)NULL);
// Send selected shortcut menu item command to shell
LRESULT lr = ::SendMessage(hwnd, WM_COMMAND, iSelection, NULL);
......

使用代码

一些命令消息由“**Internet Explorer_Server**”窗口处理,而另一些命令消息由其父“**Shell DocObject View**”窗口处理。因此,首先要从你的 `CHtmlView` 中获取这两个窗口的窗口句柄。为了简化解决方案,我从 Paul DiLascia 那里借用了下面可爱的 `CFindWnd` 类。

////////////////////////////////////////////////////////////////
// MSDN Magazine -- August 2003
// If this code works, it was written by Paul DiLascia.
// If not, I don't know who wrote it.
// Compiles with Visual Studio .NET on Windows XP. Tab size=3.
//
// ---
// This class encapsulates the process of finding a window with a given class name
// as a descendant of a given window. To use it, instantiate like so:
//
//        CFindWnd fw(hwndParent,classname);
//
// fw.m_hWnd will be the HWND of the desired window, if found.
//
class CFindWnd {
private:
    //////////////////
    // This private function is used with EnumChildWindows to find the child
    // with a given class name. Returns FALSE if found (to stop enumerating).
    //
    static BOOL CALLBACK FindChildClassHwnd(HWND hwndParent, LPARAM lParam) {
        CFindWnd *pfw = (CFindWnd*)lParam;
        HWND hwnd = FindWindowEx(hwndParent, NULL, pfw->m_classname, NULL);
        if (hwnd) {
            pfw->m_hWnd = hwnd;    // found: save it
            return FALSE;            // stop enumerating
        }
        EnumChildWindows(hwndParent, FindChildClassHwnd, lParam); // recurse
        return TRUE;                // keep looking
    }

public:
    LPCSTR m_classname;            // class name to look for
    HWND m_hWnd;                    // HWND if found

    // ctor does the work--just instantiate and go
    CFindWnd(HWND hwndParent, LPCSTR classname)
        : m_hWnd(NULL), m_classname(classname)
    {
        FindChildClassHwnd(hwndParent, (LPARAM)this);
    }
};

void CDemoView::InvokeShellDocObjCommand(int nID)
{
    CFindWnd FindIEWnd( m_wndBrowser.m_hWnd, "Shell DocObject View");
    ::SendMessage( FindIEWnd.m_hWnd, WM_COMMAND, 
                        MAKEWPARAM(LOWORD(nID), 0x0), 0 );
}

void CDemoView::InvokeIEServerCommand(int nID)
{
    CFindWnd FindIEWnd( m_wndBrowser.m_hWnd, "Internet Explorer_Server");
    ::SendMessage( FindIEWnd.m_hWnd, WM_COMMAND, 
                        MAKEWPARAM(LOWORD(nID), 0x0), 0 );
}

由“Internet Explorer_Server”窗口处理的命令 ID

#define ID_IE_CONTEXTMENU_ADDFAV        2261
#define ID_IE_CONTEXTMENU_VIEWSOURCE    2139
#define ID_IE_CONTEXTMENU_REFRESH       6042

由“Shell DocObject View”窗口处理的命令 ID

#define ID_IE_FILE_SAVEAS               258
#define ID_IE_FILE_PAGESETUP            259
#define ID_IE_FILE_PRINT                260
#define ID_IE_FILE_NEWWINDOW            275
#define ID_IE_FILE_PRINTPREVIEW         277
#define ID_IE_FILE_NEWMAIL              279
#define ID_IE_FILE_SENDDESKTOPSHORTCUT  284
#define ID_IE_HELP_ABOUTIE              336
#define ID_IE_HELP_HELPINDEX            337
#define ID_IE_HELP_WEBTUTORIAL          338
#define ID_IE_HELP_FREESTUFF            341
#define ID_IE_HELP_PRODUCTUPDATE        342
#define ID_IE_HELP_FAQ                  343
#define ID_IE_HELP_ONLINESUPPORT        344
#define ID_IE_HELP_FEEDBACK             345
#define ID_IE_HELP_BESTPAGE             346
#define ID_IE_HELP_SEARCHWEB            347
#define ID_IE_HELP_MSHOME               348
#define ID_IE_HELP_VISITINTERNET        349
#define ID_IE_HELP_STARTPAGE            350
#define ID_IE_FILE_IMPORTEXPORT         374
#define ID_IE_FILE_ADDTRUST             376
#define ID_IE_FILE_ADDLOCAL             377
#define ID_IE_FILE_NEWPUBLISHINFO       387
#define ID_IE_FILE_NEWCORRESPONDENT     390
#define ID_IE_FILE_NEWCALL              395
#define ID_IE_HELP_NETSCAPEUSER         351
#define ID_IE_HELP_ENHANCEDSECURITY     375

以下代码演示了如何调用**模态“添加到收藏夹”对话框**。

void CDemoView::OnFavAddtofav()
{
    InvokeIEServerCommand(ID_IE_CONTEXTMENU_ADDFAV);
}

关注点

你知道,整夜工作,最终找到答案。我称之为幸福!

© . All rights reserved.